aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/util')
-rw-r--r--src/quick/util/qquickanimation.cpp2
-rw-r--r--src/quick/util/qquickanimatorjob.cpp2
-rw-r--r--src/quick/util/qquickbehavior.cpp2
-rw-r--r--src/quick/util/qquickboundaryrule.cpp574
-rw-r--r--src/quick/util/qquickboundaryrule_p.h145
-rw-r--r--src/quick/util/qquickglobal.cpp7
-rw-r--r--src/quick/util/qquickimageprovider_p.h2
-rw-r--r--src/quick/util/qquickpath.cpp353
-rw-r--r--src/quick/util/qquickpath_p.h58
-rw-r--r--src/quick/util/qquickpath_p_p.h1
-rw-r--r--src/quick/util/qquickpixmapcache.cpp119
-rw-r--r--src/quick/util/qquickpixmapcache_p.h5
-rw-r--r--src/quick/util/qquickpropertychanges.cpp99
-rw-r--r--src/quick/util/qquickpropertychanges_p.h6
-rw-r--r--src/quick/util/qquickshortcut.cpp2
-rw-r--r--src/quick/util/qquickshortcut_p.h4
-rw-r--r--src/quick/util/qquickstate.cpp60
-rw-r--r--src/quick/util/qquickstate_p.h8
-rw-r--r--src/quick/util/qquickstate_p_p.h10
-rw-r--r--src/quick/util/qquickstategroup.cpp7
-rw-r--r--src/quick/util/qquickutilmodule.cpp9
-rw-r--r--src/quick/util/qquickvalidator.cpp46
-rw-r--r--src/quick/util/qquickvalidator_p.h3
-rw-r--r--src/quick/util/qquickvaluetypes.cpp5
-rw-r--r--src/quick/util/qquickvaluetypes_p.h2
-rw-r--r--src/quick/util/util.pri2
26 files changed, 1344 insertions, 189 deletions
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 2043b50545..fe5b372da8 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -2636,7 +2636,7 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
for (int j = 0; j < targets.count(); ++j) {
QQuickStateAction myAction;
QString errorMessage;
- const QString propertyName = props.at(i);
+ const QString &propertyName = props.at(i);
myAction.property = d->createProperty(targets.at(j), propertyName, this, &errorMessage);
if (myAction.property.isValid()) {
if (usingDefaultProperties)
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 03be78ab15..a9caedec4f 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -207,7 +207,7 @@ void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
stop();
} else if (!m_controller && m_job) {
- m_controller = QQuickWindowPrivate::get(window)->animationController;
+ m_controller = QQuickWindowPrivate::get(window)->animationController.get();
if (window->isSceneGraphInitialized())
readyToAnimate();
else
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index 76d464e7f8..ae5c481e2f 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -143,7 +143,7 @@ void QQuickBehavior::setAnimation(QQuickAbstractAnimation *animation)
void QQuickBehaviorPrivate::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState,QAbstractAnimationJob::State)
{
- if (!blockRunningChanged)
+ if (!blockRunningChanged && animation)
animation->notifyRunningChanged(newState == QAbstractAnimationJob::Running);
}
diff --git a/src/quick/util/qquickboundaryrule.cpp b/src/quick/util/qquickboundaryrule.cpp
new file mode 100644
index 0000000000..3558c8bfa0
--- /dev/null
+++ b/src/quick/util/qquickboundaryrule.cpp
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qquickboundaryrule_p.h"
+
+#include <qqmlcontext.h>
+#include <qqmlinfo.h>
+#include <private/qqmlproperty_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qobject_p.h>
+#include <private/qquickanimation_p_p.h>
+#include <QtCore/qloggingcategory.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcBR, "qt.quick.boundaryrule")
+
+class QQuickBoundaryReturnJob;
+class QQuickBoundaryRulePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickBoundaryRule)
+public:
+ QQuickBoundaryRulePrivate() {}
+
+ QQmlProperty property;
+ QEasingCurve easing = QEasingCurve(QEasingCurve::OutQuad);
+ QQuickBoundaryReturnJob *returnAnimationJob = nullptr;
+ // read-only properties, updated on each write()
+ qreal targetValue = 0; // after easing was applied
+ qreal peakOvershoot = 0;
+ qreal currentOvershoot = 0;
+ // settable properties
+ qreal minimum = 0;
+ qreal maximum = 0;
+ qreal minimumOvershoot = 0;
+ qreal maximumOvershoot = 0;
+ qreal overshootScale = 0.5;
+ int returnDuration = 100;
+ QQuickBoundaryRule::OvershootFilter overshootFilter = QQuickBoundaryRule::OvershootFilter::None;
+ bool enabled = true;
+ bool finalized = false;
+
+ qreal easedOvershoot(qreal overshootingValue);
+ void resetOvershoot();
+};
+
+class QQuickBoundaryReturnJob : public QAbstractAnimationJob
+{
+public:
+ QQuickBoundaryReturnJob(QQuickBoundaryRulePrivate *br, qreal to)
+ : QAbstractAnimationJob()
+ , boundaryRule(br)
+ , fromValue(br->targetValue)
+ , toValue(to) {}
+
+ int duration() const override { return boundaryRule->returnDuration; }
+
+ void updateCurrentTime(int) override;
+
+ void updateState(QAbstractAnimationJob::State newState,
+ QAbstractAnimationJob::State oldState) override;
+
+ QQuickBoundaryRulePrivate *boundaryRule;
+ qreal fromValue; // snapshot of initial value from which we're returning
+ qreal toValue; // target property value to which we're returning
+};
+
+void QQuickBoundaryReturnJob::updateCurrentTime(int t)
+{
+ // The easing property tells how to behave when the property is being
+ // externally manipulated beyond the bounds. During returnToBounds()
+ // we run it in reverse, by reversing time.
+ qreal progress = (duration() - t) / qreal(duration());
+ qreal easingValue = boundaryRule->easing.valueForProgress(progress);
+ qreal delta = qAbs(fromValue - toValue) * easingValue;
+ qreal value = (fromValue > toValue ? toValue + delta : toValue - delta);
+ qCDebug(lcBR) << t << "ms" << qRound(progress * 100) << "% easing" << easingValue << "->" << value;
+ QQmlPropertyPrivate::write(boundaryRule->property, value,
+ QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
+}
+
+void QQuickBoundaryReturnJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState)
+{
+ Q_UNUSED(oldState)
+ if (newState == QAbstractAnimationJob::Stopped) {
+ qCDebug(lcBR) << "return animation done";
+ boundaryRule->resetOvershoot();
+ boundaryRule->returnAnimationJob = nullptr;
+ delete this;
+ }
+}
+
+/*!
+ \qmltype BoundaryRule
+ \instantiates QQuickBoundaryRule
+ \inqmlmodule Qt.labs.animation
+ \ingroup qtquick-transitions-animations
+ \ingroup qtquick-interceptors
+ \brief Defines a restriction on the range of values that can be set on a numeric property.
+ \since 5.14
+
+ A BoundaryRule defines the range of values that a particular property is
+ allowed to have. When an out-of-range value would otherwise be set,
+ it applies "resistance" via an easing curve.
+
+ For example, the following BoundaryRule prevents DragHandler from dragging
+ the Rectangle too far:
+
+ \snippet qml/boundaryRule.qml 0
+
+ Note that a property cannot have more than one assigned BoundaryRule.
+
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation#Behaviors}{Behavior example}, {Qt QML}
+*/
+
+QQuickBoundaryRule::QQuickBoundaryRule(QObject *parent)
+ : QObject(*(new QQuickBoundaryRulePrivate), parent)
+ , QQmlPropertyValueInterceptor()
+{
+}
+
+QQuickBoundaryRule::~QQuickBoundaryRule()
+{
+ Q_D(QQuickBoundaryRule);
+ // stop any running animation and
+ // prevent QQuickBoundaryReturnJob::updateState() from accessing QQuickBoundaryRulePrivate
+ delete d->returnAnimationJob;
+}
+
+/*!
+ \qmlproperty bool QtQuick::BoundaryRule::enabled
+
+ This property holds whether the rule will be enforced when the tracked
+ property changes value.
+
+ By default a BoundaryRule is enabled.
+*/
+bool QQuickBoundaryRule::enabled() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->enabled;
+}
+
+void QQuickBoundaryRule::setEnabled(bool enabled)
+{
+ Q_D(QQuickBoundaryRule);
+ if (d->enabled == enabled)
+ return;
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::minimum
+
+ This property holds the smallest unconstrained value that the property is
+ allowed to have. If the property is set to a smaller value, it will be
+ constrained by \l easing and \l minimumOvershoot.
+
+ The default is \c 0.
+*/
+qreal QQuickBoundaryRule::minimum() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->minimum;
+}
+
+void QQuickBoundaryRule::setMinimum(qreal minimum)
+{
+ Q_D(QQuickBoundaryRule);
+ if (qFuzzyCompare(d->minimum, minimum))
+ return;
+ d->minimum = minimum;
+ emit minimumChanged();
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::minimumOvershoot
+
+ This property holds the amount that the property is allowed to be
+ less than \l minimum. Whenever the value is less than \l minimum
+ and greater than \c {minimum - minimumOvershoot}, it is constrained
+ by the \l easing curve. When the value attempts to go under
+ \c {minimum - minimumOvershoots} there is a hard stop.
+
+ The default is \c 0.
+*/
+qreal QQuickBoundaryRule::minimumOvershoot() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->minimumOvershoot;
+}
+
+void QQuickBoundaryRule::setMinimumOvershoot(qreal minimumOvershoot)
+{
+ Q_D(QQuickBoundaryRule);
+ if (qFuzzyCompare(d->minimumOvershoot, minimumOvershoot))
+ return;
+ d->minimumOvershoot = minimumOvershoot;
+ emit minimumOvershootChanged();
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::maximum
+
+ This property holds the largest unconstrained value that the property is
+ allowed to have. If the property is set to a larger value, it will be
+ constrained by \l easing and \l maximumOvershoot.
+
+ The default is \c 1.
+*/
+qreal QQuickBoundaryRule::maximum() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->maximum;
+}
+
+void QQuickBoundaryRule::setMaximum(qreal maximum)
+{
+ Q_D(QQuickBoundaryRule);
+ if (qFuzzyCompare(d->maximum, maximum))
+ return;
+ d->maximum = maximum;
+ emit maximumChanged();
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::maximumOvershoot
+
+ This property holds the amount that the property is allowed to be
+ more than \l maximum. Whenever the value is greater than \l maximum
+ and less than \c {maximum + maximumOvershoot}, it is constrained
+ by the \l easing curve. When the value attempts to exceed
+ \c {maximum + maximumOvershoot} there is a hard stop.
+
+ The default is 0.
+*/
+qreal QQuickBoundaryRule::maximumOvershoot() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->maximumOvershoot;
+}
+
+void QQuickBoundaryRule::setMaximumOvershoot(qreal maximumOvershoot)
+{
+ Q_D(QQuickBoundaryRule);
+ if (qFuzzyCompare(d->maximumOvershoot, maximumOvershoot))
+ return;
+ d->maximumOvershoot = maximumOvershoot;
+ emit maximumOvershootChanged();
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::overshootScale
+
+ This property holds the amount by which the \l easing is scaled during the
+ overshoot condition. For example if an Item is restricted from moving more
+ than 100 pixels beyond some limit, and the user (by means of some Input
+ Handler) is trying to drag it 100 pixels past the limit, if overshootScale
+ is set to 1, the user will succeed: the only effect of the easing curve is
+ to change the rate at which the item moves from overshoot 0 to overshoot
+ 100. But if it is set to 0.5, the BoundaryRule provides resistance such
+ that when the user tries to move 100 pixels, the Item will only move 50
+ pixels; and the easing curve modulates the rate of movement such that it
+ may move in sync with the user's attempted movement at the beginning, and
+ then slows down, depending on the shape of the easing curve.
+
+ The default is 0.5.
+*/
+qreal QQuickBoundaryRule::overshootScale() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->overshootScale;
+}
+
+void QQuickBoundaryRule::setOvershootScale(qreal overshootScale)
+{
+ Q_D(QQuickBoundaryRule);
+ if (qFuzzyCompare(d->overshootScale, overshootScale))
+ return;
+ d->overshootScale = overshootScale;
+ emit overshootScaleChanged();
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::currentOvershoot
+
+ This property holds the amount by which the most recently set value of the
+ intercepted property exceeds \l maximum or is less than \l minimum.
+
+ It is positive if the property value exceeds \l maximum, negative if the
+ property value is less than \l minimum, or 0 if the property value is
+ within both boundaries.
+*/
+qreal QQuickBoundaryRule::currentOvershoot() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->currentOvershoot;
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::peakOvershoot
+
+ This property holds the most-positive or most-negative value of
+ \l currentOvershoot that has been seen, until \l returnToBounds() is called.
+
+ This can be useful when the intercepted property value is known to
+ fluctuate, and you want to find and react to the maximum amount of
+ overshoot rather than to the fluctuations.
+
+ \sa overshootFilter
+*/
+qreal QQuickBoundaryRule::peakOvershoot() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->peakOvershoot;
+}
+
+/*!
+ \qmlproperty enum QtQuick::BoundaryRule::overshootFilter
+
+ This property specifies the aggregation function that will be applied to
+ the intercepted property value.
+
+ If this is set to \c BoundaryRule.None (the default), the intercepted
+ property will hold a value whose overshoot is limited to \l currentOvershoot.
+ If this is set to \c BoundaryRule.Peak, the intercepted property will hold
+ a value whose overshoot is limited to \l peakOvershoot.
+*/
+QQuickBoundaryRule::OvershootFilter QQuickBoundaryRule::overshootFilter() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->overshootFilter;
+}
+
+void QQuickBoundaryRule::setOvershootFilter(OvershootFilter overshootFilter)
+{
+ Q_D(QQuickBoundaryRule);
+ if (d->overshootFilter == overshootFilter)
+ return;
+ d->overshootFilter = overshootFilter;
+ emit overshootFilterChanged();
+}
+
+/*!
+ \qmlmethod bool QtQuick::BoundaryRule::returnToBounds
+
+ Returns the intercepted property to a value between \l minimum and
+ \l maximum, such that \l currentOvershoot and \l peakOvershoot are both
+ zero. This will be animated if \l returnDuration is greater than zero.
+
+ Returns true if the value needed to be adjusted, or false if it was already
+ within bounds.
+*/
+bool QQuickBoundaryRule::returnToBounds()
+{
+ Q_D(QQuickBoundaryRule);
+ if (d->returnAnimationJob) {
+ qCDebug(lcBR) << "animation already in progress";
+ return true;
+ }
+ if (currentOvershoot() > 0) {
+ if (d->returnDuration > 0)
+ d->returnAnimationJob = new QQuickBoundaryReturnJob(d, maximum());
+ else
+ write(maximum());
+ } else if (currentOvershoot() < 0) {
+ if (d->returnDuration > 0)
+ d->returnAnimationJob = new QQuickBoundaryReturnJob(d, minimum());
+ else
+ write(minimum());
+ } else {
+ return false;
+ }
+ if (d->returnAnimationJob) {
+ qCDebug(lcBR) << "animating from" << d->returnAnimationJob->fromValue << "to" << d->returnAnimationJob->toValue;
+ d->returnAnimationJob->start();
+ } else {
+ d->resetOvershoot();
+ qCDebug(lcBR) << "returned to" << d->property.read();
+ }
+ return true;
+}
+
+/*!
+ \qmlproperty qreal QtQuick::BoundaryRule::easing
+
+ This property holds the easing curve to be applied in overshoot mode
+ (whenever the \l minimum or \l maximum constraint is violated, while
+ the value is still within the respective overshoot range).
+
+ The default easing curve is \l QEasingCurve::OutQuad.
+*/
+QEasingCurve QQuickBoundaryRule::easing() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->easing;
+}
+
+void QQuickBoundaryRule::setEasing(const QEasingCurve &easing)
+{
+ Q_D(QQuickBoundaryRule);
+ if (d->easing == easing)
+ return;
+ d->easing = easing;
+ emit easingChanged();
+}
+
+/*!
+ \qmlproperty int QtQuick::BoundaryRule::returnDuration
+
+ This property holds the amount of time in milliseconds that
+ \l returnToBounds() will take to return the target property to the nearest bound.
+ If it is set to 0, returnToBounds() will set the property immediately
+ rather than creating an animation job.
+
+ The default is 100 ms.
+*/
+int QQuickBoundaryRule::returnDuration() const
+{
+ Q_D(const QQuickBoundaryRule);
+ return d->returnDuration;
+}
+
+void QQuickBoundaryRule::setReturnDuration(int duration)
+{
+ Q_D(QQuickBoundaryRule);
+ if (d->returnDuration == duration)
+ return;
+ d->returnDuration = duration;
+ emit returnDurationChanged();
+}
+
+void QQuickBoundaryRule::write(const QVariant &value)
+{
+ bool conversionOk = false;
+ qreal rValue = value.toReal(&conversionOk);
+ if (!conversionOk) {
+ qWarning() << "BoundaryRule doesn't work with non-numeric values:" << value;
+ return;
+ }
+ Q_D(QQuickBoundaryRule);
+ bool bypass = !d->enabled || !d->finalized || QQmlEnginePrivate::designerMode();
+ if (bypass) {
+ QQmlPropertyPrivate::write(d->property, value,
+ QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
+ return;
+ }
+
+ qmlExecuteDeferred(this);
+ d->targetValue = d->easedOvershoot(rValue);
+ QQmlPropertyPrivate::write(d->property, d->targetValue,
+ QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
+}
+
+void QQuickBoundaryRule::setTarget(const QQmlProperty &property)
+{
+ Q_D(QQuickBoundaryRule);
+ d->property = property;
+
+ QQmlEnginePrivate *engPriv = QQmlEnginePrivate::get(qmlEngine(this));
+ static int finalizedIdx = -1;
+ if (finalizedIdx < 0)
+ finalizedIdx = metaObject()->indexOfSlot("componentFinalized()");
+ engPriv->registerFinalizeCallback(this, finalizedIdx);
+}
+
+void QQuickBoundaryRule::componentFinalized()
+{
+ Q_D(QQuickBoundaryRule);
+ d->finalized = true;
+}
+
+/*!
+ \internal
+ Given that something is trying to set the target property to \a value,
+ this function applies the easing curve and returns the value that the
+ property should actually get instead.
+*/
+qreal QQuickBoundaryRulePrivate::easedOvershoot(qreal value)
+{
+ qreal ret = value;
+ Q_Q(QQuickBoundaryRule);
+ if (value > maximum) {
+ qreal overshootWas = currentOvershoot;
+ currentOvershoot = value - maximum;
+ if (!qFuzzyCompare(overshootWas, currentOvershoot))
+ emit q->currentOvershootChanged();
+ overshootWas = peakOvershoot;
+ peakOvershoot = qMax(currentOvershoot, peakOvershoot);
+ if (!qFuzzyCompare(overshootWas, peakOvershoot))
+ emit q->peakOvershootChanged();
+ ret = maximum + maximumOvershoot * easing.valueForProgress(
+ (overshootFilter == QQuickBoundaryRule::OvershootFilter::Peak ? peakOvershoot : currentOvershoot)
+ * overshootScale / maximumOvershoot);
+ qCDebug(lcBR).nospace() << value << " overshoots maximum " << maximum << " by "
+ << currentOvershoot << " (peak " << peakOvershoot << "): eased to " << ret;
+ } else if (value < minimum) {
+ qreal overshootWas = currentOvershoot;
+ currentOvershoot = value - minimum;
+ if (!qFuzzyCompare(overshootWas, currentOvershoot))
+ emit q->currentOvershootChanged();
+ overshootWas = peakOvershoot;
+ peakOvershoot = qMin(currentOvershoot, peakOvershoot);
+ if (!qFuzzyCompare(overshootWas, peakOvershoot))
+ emit q->peakOvershootChanged();
+ ret = minimum - minimumOvershoot * easing.valueForProgress(
+ -(overshootFilter == QQuickBoundaryRule::OvershootFilter::Peak ? peakOvershoot : currentOvershoot)
+ * overshootScale / minimumOvershoot);
+ qCDebug(lcBR).nospace() << value << " overshoots minimum " << minimum << " by "
+ << currentOvershoot << " (peak " << peakOvershoot << "): eased to " << ret;
+ } else {
+ resetOvershoot();
+ }
+ return ret;
+}
+
+/*!
+ \internal
+ Resets the currentOvershoot and peakOvershoot
+ properties to zero.
+*/
+void QQuickBoundaryRulePrivate::resetOvershoot()
+{
+ Q_Q(QQuickBoundaryRule);
+ if (!qFuzzyCompare(peakOvershoot, 0)) {
+ peakOvershoot = 0;
+ emit q->peakOvershootChanged();
+ }
+ if (!qFuzzyCompare(currentOvershoot, 0)) {
+ currentOvershoot = 0;
+ emit q->currentOvershootChanged();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickboundaryrule_p.cpp"
diff --git a/src/quick/util/qquickboundaryrule_p.h b/src/quick/util/qquickboundaryrule_p.h
new file mode 100644
index 0000000000..3325b675c5
--- /dev/null
+++ b/src/quick/util/qquickboundaryrule_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** 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 QQUICKBOUNDARYRULE_H
+#define QQUICKBOUNDARYRULE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtquickglobal_p.h>
+
+#include <private/qqmlpropertyvalueinterceptor_p.h>
+#include <qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAbstractAnimation;
+class QQuickBoundaryRulePrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickBoundaryRule : public QObject, public QQmlPropertyValueInterceptor
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickBoundaryRule)
+
+ Q_INTERFACES(QQmlPropertyValueInterceptor)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(qreal minimum READ minimum WRITE setMinimum NOTIFY minimumChanged)
+ Q_PROPERTY(qreal minimumOvershoot READ minimumOvershoot WRITE setMinimumOvershoot NOTIFY minimumOvershootChanged)
+ Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
+ Q_PROPERTY(qreal maximumOvershoot READ maximumOvershoot WRITE setMaximumOvershoot NOTIFY maximumOvershootChanged)
+ Q_PROPERTY(qreal overshootScale READ overshootScale WRITE setOvershootScale NOTIFY overshootScaleChanged)
+ Q_PROPERTY(qreal currentOvershoot READ currentOvershoot NOTIFY currentOvershootChanged)
+ Q_PROPERTY(qreal peakOvershoot READ peakOvershoot NOTIFY peakOvershootChanged)
+ Q_PROPERTY(OvershootFilter overshootFilter READ overshootFilter WRITE setOvershootFilter NOTIFY overshootFilterChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(int returnDuration READ returnDuration WRITE setReturnDuration NOTIFY returnDurationChanged)
+
+public:
+ enum OvershootFilter {
+ None,
+ Peak
+ };
+ Q_ENUM(OvershootFilter)
+
+ QQuickBoundaryRule(QObject *parent=nullptr);
+ ~QQuickBoundaryRule();
+
+ void setTarget(const QQmlProperty &) override;
+ void write(const QVariant &value) override;
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+ qreal minimum() const;
+ void setMinimum(qreal minimum);
+ qreal minimumOvershoot() const;
+ void setMinimumOvershoot(qreal minimum);
+
+ qreal maximum() const;
+ void setMaximum(qreal maximum);
+ qreal maximumOvershoot() const;
+ void setMaximumOvershoot(qreal maximum);
+
+ qreal overshootScale() const;
+ void setOvershootScale(qreal scale);
+
+ qreal currentOvershoot() const;
+ qreal peakOvershoot() const;
+
+ OvershootFilter overshootFilter() const;
+ void setOvershootFilter(OvershootFilter overshootFilter);
+
+ Q_INVOKABLE bool returnToBounds();
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &easing);
+
+ int returnDuration() const;
+ void setReturnDuration(int duration);
+
+Q_SIGNALS:
+ void enabledChanged();
+ void minimumChanged();
+ void minimumOvershootChanged();
+ void maximumChanged();
+ void maximumOvershootChanged();
+ void overshootScaleChanged();
+ void currentOvershootChanged();
+ void peakOvershootChanged();
+ void overshootFilterChanged();
+ void easingChanged();
+ void returnDurationChanged();
+
+private Q_SLOTS:
+ void componentFinalized();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickBoundaryRule)
+
+#endif // QQUICKBOUNDARYRULE_H
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
diff --git a/src/quick/util/qquickimageprovider_p.h b/src/quick/util/qquickimageprovider_p.h
index b5baf79319..67e17010d4 100644
--- a/src/quick/util/qquickimageprovider_p.h
+++ b/src/quick/util/qquickimageprovider_p.h
@@ -61,7 +61,7 @@ class QQuickImageResponsePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickImageResponse)
public:
- bool finished = false;
+ QAtomicInteger<qint32> finished = false;
void _q_finished() { finished = true; }
};
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 60d725d650..61319c388c 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
This type is the base for all path types. It cannot
be instantiated.
- \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic, PathArc,
+ \sa Path, PathAttribute, PathPercent, PathLine, PathPolyline, PathQuad, PathCubic, PathArc,
PathAngleArc, PathCurve, PathSvg
*/
@@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE
\ingroup qtquick-animation-paths
\brief Defines a path for use by \l PathView and \l Shape.
- A Path is composed of one or more path segments - PathLine, PathQuad,
+ A Path is composed of one or more path segments - PathLine, PathPolyline, PathQuad,
PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg.
The spacing of the items along the Path can be adjusted via a
@@ -104,6 +104,17 @@ QT_BEGIN_NAMESPACE
\li Yes
\li Yes
\row
+ \li PathPolyline
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \li PathMultiLine
+ \li Yes
+ \li Yes
+ \li Yes
+ \li Yes
+ \row
\li PathQuad
\li Yes
\li Yes
@@ -156,7 +167,7 @@ QT_BEGIN_NAMESPACE
\note Path is a non-visual type; it does not display anything on its own.
To draw a path, use \l Shape.
- \sa PathView, Shape, PathAttribute, PathPercent, PathLine, PathMove, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg
+ \sa PathView, Shape, PathAttribute, PathPercent, PathLine, PathPolyline, PathMove, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg
*/
QQuickPath::QQuickPath(QObject *parent)
: QObject(*(new QQuickPathPrivate), parent)
@@ -240,6 +251,8 @@ bool QQuickPath::isClosed() const
A path can contain the following path objects:
\list
\li \l PathLine - a straight line to a given position.
+ \li \l PathPolyline - a polyline specified as a list of coordinates.
+ \li \l PathMultiline - a list of polylines specified as a list of lists of coordinates.
\li \l PathQuad - a quadratic Bezier curve to a given position with a control point.
\li \l PathCubic - a cubic Bezier curve to a given position with two control points.
\li \l PathArc - an arc to a given position with a radius.
@@ -407,6 +420,19 @@ void QQuickPath::processPath()
emit changed();
}
+inline static void scalePath(QPainterPath &path, const QSizeF &scale)
+{
+ const qreal xscale = scale.width();
+ const qreal yscale = scale.height();
+ if (xscale == 1 && yscale == 1)
+ return;
+
+ for (int i = 0; i < path.elementCount(); ++i) {
+ const QPainterPath::Element &element = path.elementAt(i);
+ path.setElementPositionAt(i, element.x * xscale, element.y * yscale);
+ }
+}
+
QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed)
{
Q_D(QQuickPath);
@@ -465,7 +491,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
d->_attributePoints.last().values[percentString] = 1;
interpolate(d->_attributePoints.count() - 1, percentString, 1);
}
-
+ scalePath(path, d->scale);
// Adjust percent
qreal length = path.length();
@@ -491,7 +517,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
if (closed) {
QPointF end = path.currentPosition();
- *closed = length > 0 && startX == end.x() && startY == end.y();
+ *closed = length > 0 && startX * d->scale.width() == end.x() && startY * d->scale.height() == end.y();
}
pathLength = length;
@@ -525,6 +551,7 @@ QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPoint
QPointF end = path.currentPosition();
*closed = startX == end.x() && startY == end.y();
}
+ scalePath(path, d->scale);
// Note: Length of paths inside ShapePath is not used, so currently
// length is always 0. This avoids potentially heavy path.length()
@@ -570,7 +597,7 @@ void QQuickPath::gatherAttributes()
attributes.insert(attribute->name());
}
- d->_attributes = attributes.toList();
+ d->_attributes = attributes.values();
}
void QQuickPath::componentComplete()
@@ -603,7 +630,7 @@ QStringList QQuickPath::attributes() const
qobject_cast<QQuickPathAttribute *>(pathElement))
attrs.insert(attribute->name());
}
- return attrs.toList();
+ return attrs.values();
}
return d->_attributes;
}
@@ -723,6 +750,33 @@ void QQuickPath::invalidateSequentialHistory() const
d->prevBez.isValid = false;
}
+/*!
+ \qmlproperty size QtQuick::Path::scale
+
+ This property holds the scale factor for the path.
+ The width and height of \a scale can be different, to
+ achieve anisotropic scaling.
+
+ \note Setting this property will not affect the border width.
+
+ \since QtQuick 2.14
+*/
+QSizeF QQuickPath::scale() const
+{
+ Q_D(const QQuickPath);
+ return d->scale;
+}
+
+void QQuickPath::setScale(const QSizeF &scale)
+{
+ Q_D(QQuickPath);
+ if (scale == d->scale)
+ return;
+ d->scale = scale;
+ emit scaleChanged();
+ processPath();
+}
+
QPointF QQuickPath::sequentialPointAt(qreal p, qreal *angle) const
{
Q_D(const QQuickPath);
@@ -852,9 +906,28 @@ QPointF QQuickPath::backwardsPointAt(const QPainterPath &path, const qreal &path
return QPointF(0,0);
}
-QPointF QQuickPath::pointAt(qreal p) const
+/*!
+ \qmlmethod point Path::pointAtPercent(real t)
+
+ Returns the point at the percentage \a t of the current path.
+ The argument \a t has to be between 0 and 1.
+
+ \note Similarly to other percent methods in \l QPainterPath,
+ the percentage measurement is not linear with regards to the length,
+ if curves are present in the path.
+ When curves are present, the percentage argument is mapped to the \c t
+ parameter of the Bezier equations.
+
+ \sa QPainterPath::pointAt
+
+ \since QtQuick 2.14
+*/
+QPointF QQuickPath::pointAtPercent(qreal t) const
{
Q_D(const QQuickPath);
+ if (d->isShapePath) // this since ShapePath does not calculate the length at all,
+ return d->_path.pointAtPercent(t); // in order to be faster.
+
if (d->_pointCache.isEmpty()) {
createPointCache();
if (d->_pointCache.isEmpty())
@@ -862,7 +935,7 @@ QPointF QQuickPath::pointAt(qreal p) const
}
const int segmentCount = d->_pointCache.size() - 1;
- qreal idxf = p*segmentCount;
+ qreal idxf = t*segmentCount;
int idx1 = qFloor(idxf);
qreal delta = idxf - idx1;
if (idx1 > segmentCount)
@@ -1127,7 +1200,7 @@ void QQuickPathAttribute::setValue(qreal value)
}
\endqml
- \sa Path, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove
+ \sa Path, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove, PathPolyline
*/
/*!
@@ -2286,6 +2359,266 @@ void QQuickPathPercent::setValue(qreal value)
emit changed();
}
}
+
+/*!
+ \qmltype PathPolyline
+ \instantiates QQuickPathPolyline
+ \inqmlmodule QtQuick
+ \ingroup qtquick-animation-paths
+ \brief Defines a polyline through a list of coordinates.
+ \since QtQuick 2.14
+
+ The example below creates a triangular path consisting of four vertices
+ on the edge of the containing Shape's bounding box.
+ Through the containing shape's \l scale property, the path will be
+ rescaled together with its containing shape.
+
+ \qml
+ PathPolyline {
+ id: ppl
+ path: [ Qt.point(0.0, 0.0),
+ Qt.point(1.0, 0.0),
+ Qt.point(0.5, 1.0),
+ Qt.point(0.0, 0.0)
+ ]
+ }
+ \endqml
+
+ \sa Path, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove, PathPolyline
+*/
+
+/*!
+ \qmlproperty point QtQuick::PathPolyline::start
+
+ This read-only property contains the beginning of the polyline.
+*/
+
+/*!
+ \qmlproperty list<point> QtQuick::PathPolyline::path
+
+ This property defines the vertices of the polyline.
+
+ It can be a JS array of points constructed with \c Qt.point(),
+ a QList or QVector of QPointF, or QPolygonF.
+ If you are binding this to a custom property in some C++ object,
+ QPolygonF is the most appropriate type to use.
+*/
+
+QQuickPathPolyline::QQuickPathPolyline(QObject *parent) : QQuickCurve(parent)
+{
+}
+
+QVariant QQuickPathPolyline::path() const
+{
+ return QVariant::fromValue(m_path);
+}
+
+void QQuickPathPolyline::setPath(const QVariant &path)
+{
+ if (path.type() == QVariant::PolygonF) {
+ setPath(path.value<QPolygonF>());
+ } else if (path.canConvert<QVector<QPointF>>()) {
+ setPath(path.value<QVector<QPointF>>());
+ } else if (path.canConvert<QVariantList>()) {
+ // This handles cases other than QPolygonF or QVector<QPointF>, such as
+ // QList<QPointF>, QVector<QPoint>, QVariantList of QPointF, QVariantList of QPoint.
+ QVector<QPointF> pathList;
+ QVariantList vl = path.value<QVariantList>();
+ // If path is a QJSValue, e.g. coming from a JS array of Qt.point() in QML,
+ // then path.value<QVariantList>() is inefficient.
+ // TODO We should be able to iterate over path.value<QSequentialIterable>() eventually
+ for (const QVariant &v : vl)
+ pathList.append(v.toPointF());
+ setPath(pathList);
+ } else {
+ qWarning() << "PathPolyline: path of type" << path.type() << "not supported";
+ }
+}
+
+void QQuickPathPolyline::setPath(const QVector<QPointF> &path)
+{
+ if (m_path != path) {
+ const QPointF &oldStart = start();
+ m_path = path;
+ const QPointF &newStart = start();
+ emit pathChanged();
+ if (oldStart != newStart)
+ emit startChanged();
+ emit changed();
+ }
+}
+
+QPointF QQuickPathPolyline::start() const
+{
+ if (m_path.size()) {
+ const QPointF &p = m_path.first();
+ return p;
+ }
+ return QPointF();
+}
+
+void QQuickPathPolyline::addToPath(QPainterPath &path, const QQuickPathData &/*data*/)
+{
+ if (m_path.size() < 2)
+ return;
+
+ path.moveTo(m_path.first());
+ for (int i = 1; i < m_path.size(); ++i)
+ path.lineTo(m_path.at(i));
+}
+
+
+/*!
+ \qmltype PathMultiline
+ \instantiates QQuickPathMultiline
+ \inqmlmodule QtQuick
+ \ingroup qtquick-animation-paths
+ \brief Defines a set of polylines through a list of lists of coordinates.
+ \since QtQuick 2.14
+
+ This element allows to define a list of polylines at once.
+ Each polyline in the list will be preceded by a \l{QPainterPath::moveTo}{moveTo}
+ command, effectively making each polyline a separate one.
+ The polylines in this list are supposed to be non-intersecting with each other.
+ In any case, when used in conjunction with a \l ShapePath, the containing ShapePath's
+ \l ShapePath::fillRule applies.
+ That is, with the default \c OddEvenFill and non intersecting shapes, the largest shape in the list defines an area to be filled;
+ areas where two shapes overlap are holes; areas where three shapes overlap are filled areas inside holes, etc.
+
+ The example below creates a high voltage symbol by adding each path
+ of the symbol to the list of paths.
+ The coordinates of the vertices are normalized, and through the containing shape's
+ \l scale property, the path will be rescaled together with its containing shape.
+
+ \qml
+ PathMultiline {
+ paths: [
+ [Qt.point(0.5, 0.06698),
+ Qt.point(1, 0.93301),
+ Qt.point(0, 0.93301),
+ Qt.point(0.5, 0.06698)],
+
+ [Qt.point(0.5, 0.12472),
+ Qt.point(0.95, 0.90414),
+ Qt.point(0.05, 0.90414),
+ Qt.point(0.5, 0.12472)],
+
+ [Qt.point(0.47131, 0.32986),
+ Qt.point(0.36229, 0.64789),
+ Qt.point(0.51492, 0.58590),
+ Qt.point(0.47563, 0.76014),
+ Qt.point(0.44950, 0.73590),
+ Qt.point(0.46292, 0.83392),
+ Qt.point(0.52162, 0.75190),
+ Qt.point(0.48531, 0.76230),
+ Qt.point(0.57529, 0.53189),
+ Qt.point(0.41261, 0.59189),
+ Qt.point(0.53001, 0.32786),
+ Qt.point(0.47131, 0.32986)]
+ ]
+ }
+ \endqml
+
+ \sa Path, QPainterPath::setFillRule, PathPolyline, PathQuad, PathCubic, PathArc, PathAngleArc, PathCurve, PathSvg, PathMove
+*/
+
+/*!
+ \qmlproperty point QtQuick::PathMultiline::start
+
+ This read-only property contains the beginning of the polylines.
+*/
+
+/*!
+ \qmlproperty list<list<point>> QtQuick::PathMultiline::paths
+
+ This property defines the vertices of the polylines.
+
+ It can be a JS array of JS arrays of points constructed with \c Qt.point(),
+ a QList or QVector of QPolygonF, or QVector<QVector<QPointF>>.
+ If you are binding this to a custom property in some C++ object,
+ QVector<QPolygonF> or QVector<QVector<QPointF>> is the most
+ appropriate type to use.
+*/
+
+QQuickPathMultiline::QQuickPathMultiline(QObject *parent) : QQuickCurve(parent)
+{
+}
+
+QVariant QQuickPathMultiline::paths() const
+{
+ return QVariant::fromValue(m_paths);
+}
+
+void QQuickPathMultiline::setPaths(const QVariant &paths)
+{
+ if (paths.canConvert<QVector<QPolygonF>>()) {
+ const QVector<QPolygonF> pathPolygons = paths.value<QVector<QPolygonF>>();
+ QVector<QVector<QPointF>> pathVectors;
+ for (const QPolygonF &p : pathPolygons)
+ pathVectors << p;
+ setPaths(pathVectors);
+ } else if (paths.canConvert<QVector<QVector<QPointF>>>()) {
+ setPaths(paths.value<QVector<QVector<QPointF>>>());
+ } else if (paths.canConvert<QVariantList>()) {
+ // This handles cases other than QVector<QPolygonF> or QVector<QVector<QPointF>>, such as
+ // QList<QVector<QPointF>>, QList<QList<QPointF>>, QVariantList of QVector<QPointF>,
+ // QVariantList of QVariantList of QPointF, QVector<QList<QPoint>> etc.
+ QVector<QVector<QPointF>> pathsList;
+ QVariantList vll = paths.value<QVariantList>();
+ for (const QVariant &v : vll) {
+ // If we bind a QVector<QPolygonF> property directly, rather than via QVariant,
+ // it will come through as QJSValue that can be converted to QVariantList of QPolygonF.
+ if (v.canConvert<QPolygonF>()) {
+ pathsList.append(v.value<QPolygonF>());
+ } else {
+ QVariantList vl = v.value<QVariantList>();
+ QVector<QPointF> l;
+ for (const QVariant &point : vl) {
+ if (point.canConvert<QPointF>())
+ l.append(point.toPointF());
+ }
+ if (l.size() >= 2)
+ pathsList.append(l);
+ }
+ }
+ setPaths(pathsList);
+ } else {
+ qWarning() << "PathMultiline: paths of type" << paths.type() << "not supported";
+ setPaths(QVector<QVector<QPointF>>());
+ }
+}
+
+void QQuickPathMultiline::setPaths(const QVector<QVector<QPointF>> &paths)
+{
+ if (m_paths != paths) {
+ const QPointF &oldStart = start();
+ m_paths = paths;
+ const QPointF &newStart = start();
+ emit pathsChanged();
+ if (oldStart != newStart)
+ emit startChanged();
+ emit changed();
+ }
+}
+
+QPointF QQuickPathMultiline::start() const
+{
+ if (m_paths.size())
+ return m_paths.first().first();
+ return QPointF();
+}
+
+void QQuickPathMultiline::addToPath(QPainterPath &path, const QQuickPathData &)
+{
+ if (!m_paths.size())
+ return;
+ for (const QVector<QPointF> &p: m_paths) {
+ path.moveTo(p.first());
+ for (int i = 1; i < p.size(); ++i)
+ path.lineTo(p.at(i));
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qquickpath_p.cpp"
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index 6b9a40fe6d..5987ae8f35 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -290,7 +290,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve
Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
- Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 2)
+ Q_PROPERTY(qreal xAxisRotation READ xAxisRotation WRITE setXAxisRotation NOTIFY xAxisRotationChanged REVISION 9)
public:
QQuickPathArc(QObject *parent=nullptr)
@@ -321,7 +321,7 @@ Q_SIGNALS:
void radiusYChanged();
void useLargeArcChanged();
void directionChanged();
- Q_REVISION(2) void xAxisRotationChanged();
+ Q_REVISION(9) void xAxisRotationChanged();
private:
qreal _radiusX = 0;
@@ -424,6 +424,52 @@ private:
qreal _value = 0;
};
+class Q_QUICK_PRIVATE_EXPORT QQuickPathPolyline : public QQuickCurve
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
+ Q_PROPERTY(QVariant path READ path WRITE setPath NOTIFY pathChanged)
+public:
+ QQuickPathPolyline(QObject *parent=nullptr);
+
+ QVariant path() const;
+ void setPath(const QVariant &path);
+ void setPath(const QVector<QPointF> &path);
+ QPointF start() const;
+ void addToPath(QPainterPath &path, const QQuickPathData &data) override;
+
+Q_SIGNALS:
+ void pathChanged();
+ void startChanged();
+
+private:
+ QVector<QPointF> m_path;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPathMultiline : public QQuickCurve
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF start READ start NOTIFY startChanged)
+ Q_PROPERTY(QVariant paths READ paths WRITE setPaths NOTIFY pathsChanged)
+public:
+ QQuickPathMultiline(QObject *parent=nullptr);
+
+ QVariant paths() const;
+ void setPaths(const QVariant &paths);
+ void setPaths(const QVector<QVector<QPointF>> &paths);
+ QPointF start() const;
+ void addToPath(QPainterPath &path, const QQuickPathData &) override;
+
+Q_SIGNALS:
+ void pathsChanged();
+ void startChanged();
+
+private:
+ QPointF absolute(const QPointF &relative) const;
+
+ QVector<QVector<QPointF>> m_paths;
+};
+
struct QQuickCachedBezier
{
QQuickCachedBezier() {}
@@ -445,6 +491,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPath : public QObject, public QQmlParserStatu
Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
+ Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
Q_CLASSINFO("DefaultProperty", "pathElements")
Q_INTERFACES(QQmlParserStatus)
public:
@@ -466,14 +513,18 @@ public:
QPainterPath path() const;
QStringList attributes() const;
qreal attributeAt(const QString &, qreal) const;
- QPointF pointAt(qreal) const;
+ Q_REVISION(14) Q_INVOKABLE QPointF pointAtPercent(qreal t) const;
QPointF sequentialPointAt(qreal p, qreal *angle = nullptr) const;
void invalidateSequentialHistory() const;
+ QSizeF scale() const;
+ void setScale(const QSizeF &scale);
+
Q_SIGNALS:
void changed();
void startXChanged();
void startYChanged();
+ Q_REVISION(14) void scaleChanged();
protected:
QQuickPath(QQuickPathPrivate &dd, QObject *parent = nullptr);
@@ -540,6 +591,7 @@ QML_DECLARE_TYPE(QQuickPathArc)
QML_DECLARE_TYPE(QQuickPathAngleArc)
QML_DECLARE_TYPE(QQuickPathSvg)
QML_DECLARE_TYPE(QQuickPathPercent)
+QML_DECLARE_TYPE(QQuickPathPolyline)
QML_DECLARE_TYPE(QQuickPath)
#endif // QQUICKPATH_H
diff --git a/src/quick/util/qquickpath_p_p.h b/src/quick/util/qquickpath_p_p.h
index 9735d51264..e26001ec77 100644
--- a/src/quick/util/qquickpath_p_p.h
+++ b/src/quick/util/qquickpath_p_p.h
@@ -84,6 +84,7 @@ public:
QQmlNullableValue<qreal> startX;
QQmlNullableValue<qreal> startY;
qreal pathLength = 0;
+ QSizeF scale = QSizeF(1, 1);
bool closed = false;
bool componentComplete = true;
bool isShapePath = false;
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index ced0acd9ab..56ad8ebf0b 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -49,7 +49,7 @@
#include <QtGui/private/qimage_p.h>
#include <qpa/qplatformintegration.h>
-#include <QtQuick/private/qsgtexture_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/private/qsgtexturereader_p.h>
#include <QQuickWindow>
@@ -207,7 +207,7 @@ protected:
private:
friend class QQuickPixmapReaderThreadObject;
void processJobs();
- void processJob(QQuickPixmapReply *, const QUrl &, const QString &, QQuickImageProvider::ImageType, QQuickImageProvider *);
+ void processJob(QQuickPixmapReply *, const QUrl &, const QString &, QQuickImageProvider::ImageType, const QSharedPointer<QQuickImageProvider> &);
#if QT_CONFIG(qml_network)
void networkRequestDone(QNetworkReply *);
#endif
@@ -241,7 +241,7 @@ class QQuickPixmapData
{
public:
QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QQuickImageProviderOptions &po, const QString &e)
- : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error),
+ : refCount(1), frameCount(1), frame(0), inCache(false), pixmapStatus(QQuickPixmap::Error),
url(u), errorString(e), requestSize(s),
providerOptions(po), appliedTransform(QQuickImageProviderOptions::UsePluginDefaultTransform),
textureFactory(nullptr), reply(nullptr), prevUnreferenced(nullptr),
@@ -250,8 +250,8 @@ public:
declarativePixmaps.insert(pixmap);
}
- QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform)
- : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading),
+ QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform, int frame=0, int frameCount=1)
+ : refCount(1), frameCount(frameCount), frame(frame), inCache(false), pixmapStatus(QQuickPixmap::Loading),
url(u), requestSize(r),
providerOptions(po), appliedTransform(aTransform),
textureFactory(nullptr), reply(nullptr), prevUnreferenced(nullptr), prevUnreferencedPtr(nullptr),
@@ -261,8 +261,8 @@ public:
}
QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *texture,
- const QSize &s, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform)
- : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Ready),
+ const QSize &s, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform, int frame=0, int frameCount=1)
+ : refCount(1), frameCount(frameCount), frame(frame), inCache(false), pixmapStatus(QQuickPixmap::Ready),
url(u), implicitSize(s), requestSize(r),
providerOptions(po), appliedTransform(aTransform),
textureFactory(texture), reply(nullptr), prevUnreferenced(nullptr),
@@ -272,7 +272,7 @@ public:
}
QQuickPixmapData(QQuickPixmap *pixmap, QQuickTextureFactory *texture)
- : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Ready),
+ : refCount(1), frameCount(1), frame(0), inCache(false), pixmapStatus(QQuickPixmap::Ready),
appliedTransform(QQuickImageProviderOptions::UsePluginDefaultTransform),
textureFactory(texture), reply(nullptr), prevUnreferenced(nullptr),
prevUnreferencedPtr(nullptr), nextUnreferenced(nullptr)
@@ -299,6 +299,8 @@ public:
void removeFromCache();
uint refCount;
+ int frameCount;
+ int frame;
bool inCache:1;
@@ -396,9 +398,9 @@ static void maybeRemoveAlpha(QImage *image)
}
}
-static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
+static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, int *frameCount,
const QSize &requestSize, const QQuickImageProviderOptions &providerOptions,
- QQuickImageProviderOptions::AutoTransform *appliedTransform = nullptr)
+ QQuickImageProviderOptions::AutoTransform *appliedTransform = nullptr, int frame = 0)
{
QImageReader imgio(dev);
if (providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform)
@@ -406,6 +408,12 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
else if (appliedTransform)
*appliedTransform = imgio.autoTransform() ? QQuickImageProviderOptions::ApplyTransform : QQuickImageProviderOptions::DoNotApplyTransform;
+ if (frame < imgio.imageCount())
+ imgio.jumpToImage(frame);
+
+ if (frameCount)
+ *frameCount = imgio.imageCount();
+
QSize scSize = QQuickImageProviderWithOptions::loadSize(imgio.size(), requestSize, imgio.format(), providerOptions);
if (scSize.isValid())
imgio.setScaledSize(scSize);
@@ -558,9 +566,12 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
QByteArray all = reply->readAll();
QBuffer buff(&all);
buff.open(QIODevice::ReadOnly);
- if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize, job->providerOptions))
+ int frameCount;
+ if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, &frameCount, job->requestSize, job->providerOptions, nullptr, job->data->frame))
error = QQuickPixmapReply::Decoding;
- }
+ else
+ job->data->frameCount = frameCount;
+ }
// send completion event to the QQuickPixmapReply
mutex.lock();
if (!cancelled.contains(job))
@@ -683,10 +694,11 @@ void QQuickPixmapReader::processJobs()
const QUrl url = job->url;
QString localFile;
QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
- QQuickImageProvider *provider = nullptr;
+ QSharedPointer<QQuickImageProvider> provider;
if (url.scheme() == QLatin1String("image")) {
- provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ provider = enginePrivate->imageProvider(imageProviderId(url)).staticCast<QQuickImageProvider>();
if (provider)
imageType = provider->imageType();
@@ -721,7 +733,7 @@ void QQuickPixmapReader::processJobs()
}
void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, const QString &localFile,
- QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider)
+ QQuickImageProvider::ImageType imageType, const QSharedPointer<QQuickImageProvider> &provider)
{
// fetch
if (url.scheme() == QLatin1String("image")) {
@@ -737,7 +749,8 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
return;
}
- QQuickImageProviderWithOptions *providerV2 = QQuickImageProviderWithOptions::checkedCast(provider);
+ // This is safe because we ensure that provider does outlive providerV2 and it does not escape the function
+ QQuickImageProviderWithOptions *providerV2 = QQuickImageProviderWithOptions::checkedCast(provider.get());
switch (imageType) {
case QQuickImageProvider::Invalid:
@@ -817,17 +830,24 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
if (providerV2) {
response = providerV2->requestImageResponse(imageId(url), runningJob->requestSize, runningJob->providerOptions);
} else {
- QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider);
+ QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider.get());
response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize);
}
+ {
+ QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished()));
+ // as the response object can outlive the provider QSharedPointer, we have to extend the pointee's lifetime by that of the response
+ // we do this by capturing a copy of the QSharedPointer in a lambda, and dropping it once the lambda has been called
+ auto provider_copy = provider; // capturing provider would capture it as a const reference, and copy capture with initializer is only available in C++14
+ QObject::connect(response, &QQuickImageResponse::destroyed, response, [provider_copy]() {
+ // provider_copy will be deleted when the connection gets deleted
+ });
+ }
// Might be that the async provider was so quick it emitted the signal before we
// could connect to it.
- if (static_cast<QQuickImageResponsePrivate*>(QObjectPrivate::get(response))->finished) {
+ if (static_cast<QQuickImageResponsePrivate*>(QObjectPrivate::get(response))->finished.loadAcquire()) {
QMetaObject::invokeMethod(threadObject, "asyncResponseFinished",
Qt::QueuedConnection, Q_ARG(QQuickImageResponse*, response));
- } else {
- QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished()));
}
asyncResponses.insert(response, runningJob);
@@ -861,10 +881,13 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
mutex.unlock();
return;
} else {
- if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, runningJob->providerOptions)) {
+ int frameCount;
+ if (!readImage(url, &f, &image, &errorStr, &readSize, &frameCount, runningJob->requestSize, runningJob->providerOptions, nullptr, runningJob->data->frame)) {
errorCode = QQuickPixmapReply::Loading;
if (f.fileName() != localFile)
errorStr += QString::fromLatin1(" (%1)").arg(f.fileName());
+ } else if (runningJob->data) {
+ runningJob->data->frameCount = frameCount;
}
}
} else {
@@ -973,17 +996,18 @@ class QQuickPixmapKey
public:
const QUrl *url;
const QSize *size;
+ int frame;
QQuickImageProviderOptions options;
};
inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs)
{
- return *lhs.size == *rhs.size && *lhs.url == *rhs.url && lhs.options == rhs.options;
+ return *lhs.size == *rhs.size && *lhs.url == *rhs.url && lhs.options == rhs.options && lhs.frame == rhs.frame;
}
inline uint qHash(const QQuickPixmapKey &key)
{
- return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.options.autoTransform() * 0x5c5c5c5c);
+ return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.frame*23) ^ (key.options.autoTransform() * 0x5c5c5c5c);
}
class QQuickPixmapStore : public QObject
@@ -1245,7 +1269,7 @@ void QQuickPixmapData::release()
void QQuickPixmapData::addToCache()
{
if (!inCache) {
- QQuickPixmapKey key = { &url, &requestSize, providerOptions };
+ QQuickPixmapKey key = { &url, &requestSize, frame, providerOptions };
pixmapStore()->m_cache.insert(key, this);
inCache = true;
PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
@@ -1256,7 +1280,7 @@ void QQuickPixmapData::addToCache()
void QQuickPixmapData::removeFromCache()
{
if (inCache) {
- QQuickPixmapKey key = { &url, &requestSize, providerOptions };
+ QQuickPixmapKey key = { &url, &requestSize, frame, providerOptions };
pixmapStore()->m_cache.remove(key);
inCache = false;
PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
@@ -1264,14 +1288,16 @@ void QQuickPixmapData::removeFromCache()
}
}
-static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, bool *ok)
+static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, int frame, bool *ok)
{
if (url.scheme() == QLatin1String("image")) {
QSize readSize;
QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
- QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
- QQuickImageProviderWithOptions *providerV2 = QQuickImageProviderWithOptions::checkedCast(provider);
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ QSharedPointer<QQuickImageProvider> provider = enginePrivate->imageProvider(imageProviderId(url)).dynamicCast<QQuickImageProvider>();
+ // it is safe to use get() as providerV2 does not escape and is outlived by provider
+ QQuickImageProviderWithOptions *providerV2 = QQuickImageProviderWithOptions::checkedCast(provider.get());
if (provider)
imageType = provider->imageType();
@@ -1285,7 +1311,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
: provider->requestTexture(imageId(url), &readSize, requestSize);
if (texture) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
+ return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame);
}
break;
}
@@ -1296,7 +1322,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
: provider->requestImage(imageId(url), &readSize, requestSize);
if (!image.isNull()) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame);
}
break;
}
@@ -1306,7 +1332,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
: provider->requestPixmap(imageId(url), &readSize, requestSize);
if (!pixmap.isNull()) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame);
}
break;
}
@@ -1336,7 +1362,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
QQuickTextureFactory *factory = texReader.read();
if (factory) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, factory, factory->textureSize(), requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
+ return new QQuickPixmapData(declarativePixmap, url, factory, factory->textureSize(), requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame);
} else {
errorString = QQuickPixmap::tr("Error decoding: %1").arg(url.toString());
if (f.fileName() != localFile)
@@ -1345,9 +1371,10 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
} else {
QImage image;
QQuickImageProviderOptions::AutoTransform appliedTransform = providerOptions.autoTransform();
- if (readImage(url, &f, &image, &errorString, &readSize, requestSize, providerOptions, &appliedTransform)) {
+ int frameCount;
+ if (readImage(url, &f, &image, &errorString, &readSize, &frameCount, requestSize, providerOptions, &appliedTransform, frame)) {
*ok = true;
- return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, appliedTransform);
+ return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, appliedTransform, frame, frameCount);
} else if (f.fileName() != localFile) {
errorString += QString::fromLatin1(" (%1)").arg(f.fileName());
}
@@ -1465,6 +1492,13 @@ QQuickImageProviderOptions::AutoTransform QQuickPixmap::autoTransform() const
return QQuickImageProviderOptions::UsePluginDefaultTransform;
}
+int QQuickPixmap::frameCount() const
+{
+ if (d)
+ return d->frameCount;
+ return 0;
+}
+
QQuickTextureFactory *QQuickPixmap::textureFactory() const
{
if (d)
@@ -1543,7 +1577,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
load(engine, url, requestSize, options, QQuickImageProviderOptions());
}
-void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions)
+void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame, int frameCount)
{
if (d) {
d->declarativePixmaps.remove(this);
@@ -1551,7 +1585,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
d = nullptr;
}
- QQuickPixmapKey key = { &url, &requestSize, providerOptions };
+ QQuickPixmapKey key = { &url, &requestSize, frame, providerOptions };
QQuickPixmapStore *store = pixmapStore();
QHash<QQuickPixmapKey, QQuickPixmapData *>::Iterator iter = store->m_cache.end();
@@ -1563,14 +1597,15 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
QSize dummy;
if (requestSize != dummy)
qWarning() << "Ignoring sourceSize request for image url that came from grabToImage. Use the targetSize parameter of the grabToImage() function instead.";
- const QQuickPixmapKey grabberKey = { &url, &dummy, QQuickImageProviderOptions() };
+ const QQuickPixmapKey grabberKey = { &url, &dummy, 0, QQuickImageProviderOptions() };
iter = store->m_cache.find(grabberKey);
} else if (options & QQuickPixmap::Cache)
iter = store->m_cache.find(key);
if (iter == store->m_cache.end()) {
if (url.scheme() == QLatin1String("image")) {
- if (QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)))) {
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ if (auto provider = enginePrivate->imageProvider(imageProviderId(url)).staticCast<QQuickImageProvider>()) {
const bool threadedPixmaps = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps);
if (!threadedPixmaps && provider->imageType() == QQuickImageProvider::Pixmap) {
// pixmaps can only be loaded synchronously
@@ -1584,7 +1619,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
if (!(options & QQuickPixmap::Asynchronous)) {
bool ok = false;
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
- d = createPixmapDataSync(this, engine, url, requestSize, providerOptions, &ok);
+ d = createPixmapDataSync(this, engine, url, requestSize, providerOptions, frame, &ok);
if (ok) {
PIXMAP_PROFILE(pixmapLoadingFinished(url, QSize(width(), height())));
if (options & QQuickPixmap::Cache)
@@ -1601,7 +1636,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
return;
- d = new QQuickPixmapData(this, url, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
+ d = new QQuickPixmapData(this, url, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform, frame, frameCount);
if (options & QQuickPixmap::Cache)
d->addToCache();
@@ -1635,9 +1670,9 @@ void QQuickPixmap::clear(QObject *obj)
}
}
-bool QQuickPixmap::isCached(const QUrl &url, const QSize &requestSize, const QQuickImageProviderOptions &options)
+bool QQuickPixmap::isCached(const QUrl &url, const QSize &requestSize, const int frame, const QQuickImageProviderOptions &options)
{
- QQuickPixmapKey key = { &url, &requestSize, options };
+ QQuickPixmapKey key = { &url, &requestSize, frame, options };
QQuickPixmapStore *store = pixmapStore();
return store->m_cache.contains(key);
diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h
index 91fb1ed3bb..ab5d391fa2 100644
--- a/src/quick/util/qquickpixmapcache_p.h
+++ b/src/quick/util/qquickpixmapcache_p.h
@@ -150,6 +150,7 @@ public:
const QSize &implicitSize() const;
const QSize &requestSize() const;
QQuickImageProviderOptions::AutoTransform autoTransform() const;
+ int frameCount() const;
QImage image() const;
void setImage(const QImage &);
void setPixmap(const QQuickPixmap &other);
@@ -164,7 +165,7 @@ public:
void load(QQmlEngine *, const QUrl &, QQuickPixmap::Options options);
void load(QQmlEngine *, const QUrl &, const QSize &);
void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options);
- void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions);
+ void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions, int frame = 0, int frameCount = 1);
void clear();
void clear(QObject *);
@@ -175,7 +176,7 @@ public:
bool connectDownloadProgress(QObject *, int);
static void purgeCache();
- static bool isCached(const QUrl &url, const QSize &requestSize, const QQuickImageProviderOptions &options);
+ static bool isCached(const QUrl &url, const QSize &requestSize, const int frame, const QQuickImageProviderOptions &options);
static const QLatin1String itemGrabberScheme;
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index d739c8a017..1cb30f5a8d 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -51,6 +51,7 @@
#include <private/qqmlcontext_p.h>
#include <private/qquickstate_p_p.h>
#include <private/qqmlboundsignal_p.h>
+#include <private/qv4qmlcontext_p.h>
#include <QtCore/qdebug.h>
@@ -201,14 +202,14 @@ public:
QPointer<QObject> object;
QList<const QV4::CompiledData::Binding *> bindings;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
bool decoded : 1;
bool restore : 1;
bool isExplicit : 1;
void decode();
- void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding);
+ void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding);
class ExpressionChange {
public:
@@ -236,7 +237,7 @@ public:
QQmlProperty property(const QString &);
};
-void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
error(compilationUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects."));
@@ -266,7 +267,7 @@ void QQuickPropertyChangesPrivate::decode()
decoded = true;
}
-void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
Q_Q(QQuickPropertyChanges);
@@ -314,7 +315,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
QQmlBinding::Identifier id = QQmlBinding::Invalid;
if (!binding->isTranslationBinding()) {
- expression = binding->valueAsString(compilationUnit.data());
+ expression = compilationUnit->bindingValueAsString(binding);
id = binding->value.compiledScriptIndex;
}
expressions << ExpressionChange(propertyName, binding, id, expression, url, line, column);
@@ -328,10 +329,10 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
case QV4::CompiledData::Binding::Type_TranslationById:
Q_UNREACHABLE();
case QV4::CompiledData::Binding::Type_String:
- var = binding->valueAsString(compilationUnit.data());
+ var = compilationUnit->bindingValueAsString(binding);
break;
case QV4::CompiledData::Binding::Type_Number:
- var = binding->valueAsNumber(compilationUnit->constants);
+ var = compilationUnit->bindingValueAsNumber(binding);
break;
case QV4::CompiledData::Binding::Type_Boolean:
var = binding->valueAsBoolean();
@@ -346,13 +347,13 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
properties << qMakePair(propertyName, var);
}
-void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
+void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
{
for (int ii = 0; ii < props.count(); ++ii)
verifyList(compilationUnit, props.at(ii));
}
-void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQuickPropertyChangesParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQuickPropertyChangesPrivate *p =
static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj));
@@ -539,9 +540,7 @@ bool QQuickPropertyChanges::containsValue(const QString &name) const
Q_D(const QQuickPropertyChanges);
typedef QPair<QString, QVariant> PropertyEntry;
- QListIterator<PropertyEntry> propertyIterator(d->properties);
- while (propertyIterator.hasNext()) {
- const PropertyEntry &entry = propertyIterator.next();
+ for (const PropertyEntry &entry : d->properties) {
if (entry.first == name) {
return true;
}
@@ -555,9 +554,7 @@ bool QQuickPropertyChanges::containsExpression(const QString &name) const
Q_D(const QQuickPropertyChanges);
typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
- QListIterator<ExpressionEntry> expressionIterator(d->expressions);
- while (expressionIterator.hasNext()) {
- const ExpressionEntry &entry = expressionIterator.next();
+ for (const ExpressionEntry &entry : d->expressions) {
if (entry.name == name) {
return true;
}
@@ -575,13 +572,10 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
{
Q_D(QQuickPropertyChanges);
typedef QPair<QString, QVariant> PropertyEntry;
- typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
- QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
- while (expressionIterator.hasNext()) {
- const ExpressionEntry &entry = expressionIterator.next();
- if (entry.name == name) {
- expressionIterator.remove();
+ for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) {
+ if (it->name == name) {
+ d->expressions.erase(it);
if (state() && state()->isStateActive()) {
QQmlPropertyPrivate::removeBinding(d->property(name));
d->property(name).write(value);
@@ -592,11 +586,9 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
}
}
- QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
- while (propertyIterator.hasNext()) {
- PropertyEntry &entry = propertyIterator.next();
- if (entry.first == name) {
- entry.second = value;
+ for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) {
+ if (it->first == name) {
+ it->second = value;
if (state() && state()->isStateActive())
d->property(name).write(value);
return;
@@ -611,7 +603,7 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
action.specifiedProperty = name;
action.toValue = value;
- propertyIterator.insert(PropertyEntry(name, value));
+ d->properties.append(PropertyEntry(name, value));
if (state() && state()->isStateActive()) {
state()->addEntryToRevertList(action);
QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(action.property);
@@ -624,26 +616,21 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val
void QQuickPropertyChanges::changeExpression(const QString &name, const QString &expression)
{
Q_D(QQuickPropertyChanges);
- typedef QPair<QString, QVariant> PropertyEntry;
typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
bool hadValue = false;
- QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
- while (propertyIterator.hasNext()) {
- PropertyEntry &entry = propertyIterator.next();
- if (entry.first == name) {
- propertyIterator.remove();
+ for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) {
+ if (it->first == name) {
+ d->properties.erase(it);
hadValue = true;
break;
}
}
- QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
- while (expressionIterator.hasNext()) {
- ExpressionEntry &entry = expressionIterator.next();
- if (entry.name == name) {
- entry.expression = expression;
+ for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) {
+ if (it->name == name) {
+ it->expression = expression;
if (state() && state()->isStateActive()) {
auto prop = d->property(name);
QQmlBinding *newBinding = QQmlBinding::create(
@@ -657,7 +644,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
}
// adding a new expression.
- expressionIterator.insert(ExpressionEntry(name, nullptr, QQmlBinding::Invalid, expression, QUrl(), -1, -1));
+ d->expressions.append(ExpressionEntry(name, nullptr, QQmlBinding::Invalid, expression, QUrl(), -1, -1));
if (state() && state()->isStateActive()) {
if (hadValue) {
@@ -713,17 +700,13 @@ QVariant QQuickPropertyChanges::property(const QString &name) const
typedef QPair<QString, QVariant> PropertyEntry;
typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
- QListIterator<PropertyEntry> propertyIterator(d->properties);
- while (propertyIterator.hasNext()) {
- const PropertyEntry &entry = propertyIterator.next();
+ for (const PropertyEntry &entry : d->properties) {
if (entry.first == name) {
return entry.second;
}
}
- QListIterator<ExpressionEntry> expressionIterator(d->expressions);
- while (expressionIterator.hasNext()) {
- const ExpressionEntry &entry = expressionIterator.next();
+ for (const ExpressionEntry &entry : d->expressions) {
if (entry.name == name) {
return QVariant(entry.expression);
}
@@ -735,24 +718,18 @@ QVariant QQuickPropertyChanges::property(const QString &name) const
void QQuickPropertyChanges::removeProperty(const QString &name)
{
Q_D(QQuickPropertyChanges);
- typedef QPair<QString, QVariant> PropertyEntry;
- typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
- QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
- while (expressionIterator.hasNext()) {
- const ExpressionEntry &entry = expressionIterator.next();
- if (entry.name == name) {
- expressionIterator.remove();
+ for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) {
+ if (it->name == name) {
+ d->expressions.erase(it);
state()->removeEntryFromRevertList(object(), name);
return;
}
}
- QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
- while (propertyIterator.hasNext()) {
- const PropertyEntry &entry = propertyIterator.next();
- if (entry.first == name) {
- propertyIterator.remove();
+ for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) {
+ if (it->first == name) {
+ d->properties.erase(it);
state()->removeEntryFromRevertList(object(), name);
return;
}
@@ -764,9 +741,7 @@ QVariant QQuickPropertyChanges::value(const QString &name) const
Q_D(const QQuickPropertyChanges);
typedef QPair<QString, QVariant> PropertyEntry;
- QListIterator<PropertyEntry> propertyIterator(d->properties);
- while (propertyIterator.hasNext()) {
- const PropertyEntry &entry = propertyIterator.next();
+ for (const PropertyEntry &entry : d->properties) {
if (entry.first == name) {
return entry.second;
}
@@ -780,9 +755,7 @@ QString QQuickPropertyChanges::expression(const QString &name) const
Q_D(const QQuickPropertyChanges);
typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
- QListIterator<ExpressionEntry> expressionIterator(d->expressions);
- while (expressionIterator.hasNext()) {
- const ExpressionEntry &entry = expressionIterator.next();
+ for (const ExpressionEntry &entry : d->expressions) {
if (entry.name == name) {
return entry.expression;
}
diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h
index 74fe511d6e..82a6ebffac 100644
--- a/src/quick/util/qquickpropertychanges_p.h
+++ b/src/quick/util/qquickpropertychanges_p.h
@@ -101,10 +101,10 @@ public:
QQuickPropertyChangesParser()
: QQmlCustomParser(AcceptsAttachedProperties) {}
- void verifyList(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
+ void verifyList(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
- void applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props) override;
+ void applyBindings(QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
};
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 730a14369e..5d227b4613 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -216,7 +216,7 @@ void QQuickShortcut::setSequences(const QVariantList &values)
bool changed = !remainder.isEmpty();
for (int i = 0; i < values.count(); ++i) {
- QVariant value = values.at(i);
+ const QVariant &value = values.at(i);
Shortcut& shortcut = m_shortcuts[i];
if (value == shortcut.userValue)
continue;
diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h
index c5d5501cb7..712cca7696 100644
--- a/src/quick/util/qquickshortcut_p.h
+++ b/src/quick/util/qquickshortcut_p.h
@@ -67,8 +67,8 @@ class QQuickShortcut : public QObject, public QQmlParserStatus
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QVariant sequence READ sequence WRITE setSequence NOTIFY sequenceChanged FINAL)
Q_PROPERTY(QVariantList sequences READ sequences WRITE setSequences NOTIFY sequencesChanged FINAL REVISION 9)
- Q_PROPERTY(QString nativeText READ nativeText NOTIFY sequenceChanged FINAL REVISION 1)
- Q_PROPERTY(QString portableText READ portableText NOTIFY sequenceChanged FINAL REVISION 1)
+ Q_PROPERTY(QString nativeText READ nativeText NOTIFY sequenceChanged FINAL REVISION 6)
+ Q_PROPERTY(QString portableText READ portableText NOTIFY sequenceChanged FINAL REVISION 6)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL)
Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL)
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext NOTIFY contextChanged FINAL)
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index 3ca6440784..c106528f45 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -192,7 +192,7 @@ bool QQuickState::isNamed() const
bool QQuickState::isWhenKnown() const
{
Q_D(const QQuickState);
- return d->when != nullptr;
+ return d->whenKnown;
}
/*!
@@ -219,15 +219,16 @@ bool QQuickState::isWhenKnown() const
}
\endqml
*/
-QQmlBinding *QQuickState::when() const
+bool QQuickState::when() const
{
Q_D(const QQuickState);
- return d->when.data();
+ return d->when;
}
-void QQuickState::setWhen(QQmlBinding *when)
+void QQuickState::setWhen(bool when)
{
Q_D(QQuickState);
+ d->whenKnown = true;
d->when = when;
if (d->group)
d->group->updateAutoState();
@@ -371,10 +372,7 @@ bool QQuickState::containsPropertyInRevertList(QObject *target, const QString &n
Q_D(const QQuickState);
if (isStateActive()) {
- QListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- const QQuickSimpleAction &simpleAction = revertListIterator.next();
+ for (const QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
return true;
}
@@ -388,10 +386,7 @@ bool QQuickState::changeValueInRevertList(QObject *target, const QString &name,
Q_D(QQuickState);
if (isStateActive()) {
- QMutableListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- QQuickSimpleAction &simpleAction = revertListIterator.next();
+ for (QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
simpleAction.setValue(revertValue);
return true;
@@ -407,10 +402,7 @@ bool QQuickState::changeBindingInRevertList(QObject *target, const QString &name
Q_D(QQuickState);
if (isStateActive()) {
- QMutableListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- QQuickSimpleAction &simpleAction = revertListIterator.next();
+ for (QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
simpleAction.setBinding(binding);
return true;
@@ -426,10 +418,8 @@ bool QQuickState::removeEntryFromRevertList(QObject *target, const QString &name
Q_D(QQuickState);
if (isStateActive()) {
- QMutableListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- QQuickSimpleAction &simpleAction = revertListIterator.next();
+ for (auto it = d->revertList.begin(), end = d->revertList.end(); it != end; ++it) {
+ QQuickSimpleAction &simpleAction = *it;
if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
QQmlPropertyPrivate::removeBinding(simpleAction.property());
@@ -437,7 +427,7 @@ bool QQuickState::removeEntryFromRevertList(QObject *target, const QString &name
if (simpleAction.binding())
QQmlPropertyPrivate::setBinding(simpleAction.binding());
- revertListIterator.remove();
+ d->revertList.erase(it);
return true;
}
}
@@ -460,10 +450,7 @@ void QQuickState::removeAllEntriesFromRevertList(QObject *target)
Q_D(QQuickState);
if (isStateActive()) {
- QMutableListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- QQuickSimpleAction &simpleAction = revertListIterator.next();
+ const auto actionMatchesTarget = [target](QQuickSimpleAction &simpleAction) {
if (simpleAction.property().object() == target) {
QQmlPropertyPrivate::removeBinding(simpleAction.property());
@@ -471,9 +458,14 @@ void QQuickState::removeAllEntriesFromRevertList(QObject *target)
if (simpleAction.binding())
QQmlPropertyPrivate::setBinding(simpleAction.binding());
- revertListIterator.remove();
+ return true;
}
- }
+ return false;
+ };
+
+ d->revertList.erase(std::remove_if(d->revertList.begin(), d->revertList.end(),
+ actionMatchesTarget),
+ d->revertList.end());
}
}
@@ -484,9 +476,7 @@ void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionL
QList<QQuickSimpleAction> simpleActionList;
simpleActionList.reserve(actionList.count());
- QListIterator<QQuickStateAction> actionListIterator(actionList);
- while(actionListIterator.hasNext()) {
- const QQuickStateAction &action = actionListIterator.next();
+ for (const QQuickStateAction &action : actionList) {
QQuickSimpleAction simpleAction(action);
action.property.write(action.toValue);
if (action.toBinding)
@@ -504,10 +494,7 @@ QVariant QQuickState::valueInRevertList(QObject *target, const QString &name) co
Q_D(const QQuickState);
if (isStateActive()) {
- QListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- const QQuickSimpleAction &simpleAction = revertListIterator.next();
+ for (const QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
return simpleAction.value();
}
@@ -521,10 +508,7 @@ QQmlAbstractBinding *QQuickState::bindingInRevertList(QObject *target, const QSt
Q_D(const QQuickState);
if (isStateActive()) {
- QListIterator<QQuickSimpleAction> revertListIterator(d->revertList);
-
- while (revertListIterator.hasNext()) {
- const QQuickSimpleAction &simpleAction = revertListIterator.next();
+ for (const QQuickSimpleAction &simpleAction : d->revertList) {
if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
return simpleAction.binding();
}
diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h
index 79874ee78e..576ba9834c 100644
--- a/src/quick/util/qquickstate_p.h
+++ b/src/quick/util/qquickstate_p.h
@@ -152,7 +152,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickState : public QObject
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
- Q_PROPERTY(QQmlBinding *when READ when WRITE setWhen)
+ Q_PROPERTY(bool when READ when WRITE setWhen)
Q_PROPERTY(QString extend READ extends WRITE setExtends)
Q_PROPERTY(QQmlListProperty<QQuickStateOperation> changes READ changes)
Q_CLASSINFO("DefaultProperty", "changes")
@@ -166,11 +166,9 @@ public:
void setName(const QString &);
bool isNamed() const;
- /*'when' is a QQmlBinding to limit state changes oscillation
- due to the unpredictable order of evaluation of bound expressions*/
bool isWhenKnown() const;
- QQmlBinding *when() const;
- void setWhen(QQmlBinding *);
+ bool when() const;
+ void setWhen(bool);
QString extends() const;
void setExtends(const QString &);
diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h
index 61472b4d06..2fa5321165 100644
--- a/src/quick/util/qquickstate_p_p.h
+++ b/src/quick/util/qquickstate_p_p.h
@@ -203,12 +203,13 @@ class QQuickStatePrivate : public QObjectPrivate
public:
QQuickStatePrivate()
- : named(false), inState(false), group(nullptr) {}
+ : when(false), whenKnown(false), named(false), inState(false), group(nullptr) {}
typedef QList<QQuickSimpleAction> SimpleActionList;
QString name;
- QQmlBinding::Ptr when;
+ bool when;
+ bool whenKnown;
bool named;
struct OperationGuard : public QQmlGuard<QQuickStateOperation>
@@ -231,9 +232,8 @@ public:
}
static void operations_clear(QQmlListProperty<QQuickStateOperation> *prop) {
QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
- QMutableListIterator<OperationGuard> listIterator(*list);
- while(listIterator.hasNext())
- listIterator.next()->setState(nullptr);
+ for (auto &e : *list)
+ e->setState(nullptr);
list->clear();
}
static int operations_count(QQmlListProperty<QQuickStateOperation> *prop) {
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index b53949d21c..46e7d62fc1 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -311,7 +311,7 @@ void QQuickStateGroup::componentComplete()
if (!state->isNamed())
state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount));
- const QString stateName = state->name();
+ QString stateName = state->name();
if (names.contains(stateName)) {
qmlWarning(state->parent()) << "Found duplicate state name: " << stateName;
} else {
@@ -348,10 +348,9 @@ bool QQuickStateGroupPrivate::updateAutoState()
QQuickState *state = states.at(ii);
if (state->isWhenKnown()) {
if (state->isNamed()) {
- if (state->when() && state->when()->evaluate().toBool()) {
+ if (state->when()) {
if (stateChangeDebug())
- qWarning() << "Setting auto state due to:"
- << state->when()->expression();
+ qWarning() << "Setting auto state due to expression";
if (currentState != state->name()) {
q->setState(state->name());
return true;
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index 5147ebc6f6..93b6599506 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -99,10 +99,13 @@ void QQuickUtilModule::defineModule()
qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation");
#if QT_CONFIG(validator)
- qmlRegisterType<QValidator>();
+ qmlRegisterAnonymousType<QValidator>("QtQuick", 2);
qmlRegisterType<QQuickIntValidator>("QtQuick",2,0,"IntValidator");
qmlRegisterType<QQuickDoubleValidator>("QtQuick",2,0,"DoubleValidator");
qmlRegisterType<QRegExpValidator>("QtQuick",2,0,"RegExpValidator");
+#if QT_CONFIG(regularexpression)
+ qmlRegisterType<QRegularExpressionValidator>("QtQuick", 2, 14, "RegularExpressionValidator");
+#endif
#endif
qmlRegisterUncreatableType<QQuickAnimator>("QtQuick", 2, 2, "Animator", QQuickAbstractAnimation::tr("Animator is an abstract class"));
@@ -114,7 +117,7 @@ void QQuickUtilModule::defineModule()
#if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl)
qmlRegisterType<QQuickUniformAnimator>("QtQuick", 2, 2, "UniformAnimator");
#endif
- qmlRegisterType<QQuickStateOperation>();
+ qmlRegisterAnonymousType<QQuickStateOperation>("QtQuick", 2);
qmlRegisterCustomType<QQuickPropertyChanges>("QtQuick",2,0,"PropertyChanges", new QQuickPropertyChangesParser);
@@ -128,7 +131,7 @@ void QQuickUtilModule::defineModule()
#if QT_CONFIG(shortcut)
qmlRegisterType<QQuickShortcut>("QtQuick", 2, 5, "Shortcut");
- qmlRegisterType<QQuickShortcut,1>("QtQuick", 2, 6, "Shortcut");
+ qmlRegisterType<QQuickShortcut,6>("QtQuick", 2, 6, "Shortcut");
qmlRegisterType<QQuickShortcut,9>("QtQuick", 2, 9, "Shortcut");
#endif
diff --git a/src/quick/util/qquickvalidator.cpp b/src/quick/util/qquickvalidator.cpp
index b2b773cd94..4709b3dda3 100644
--- a/src/quick/util/qquickvalidator.cpp
+++ b/src/quick/util/qquickvalidator.cpp
@@ -206,9 +206,13 @@ void QQuickDoubleValidator::resetLocaleName()
\inqmlmodule QtQuick
\ingroup qtquick-text-utility
\brief Provides a string validator.
+ \deprecated
The RegExpValidator type provides a validator, which counts as valid any string which
matches a specified regular expression.
+
+ RegExpValidator is deprecated since it is based on the deprecated \l {QRegExp}. Use
+ \l RegularExpressionValidator instead.
*/
/*!
\qmlproperty regExp QtQuick::RegExpValidator::regExp
@@ -239,6 +243,48 @@ void QQuickDoubleValidator::resetLocaleName()
\endcode
\endlist
*/
+/*!
+ \qmltype RegularExpressionValidator
+ \instantiates QRegularExpressionValidator
+ \inqmlmodule QtQuick
+ \ingroup qtquick-text-utility
+ \brief Provides a string validator.
+ \since 5.14
+
+ The RegularExpressionValidator type provides a validator, that counts as valid any string which
+ matches a specified regular expression.
+*/
+/*!
+ \qmlproperty regularExpression QtQuick::RegularExpressionValidator::regularExpression
+
+ This property holds the regular expression used for validation.
+
+ Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular
+ expression matching "a".
+
+ By default, this property contains a regular expression with the pattern \c{.*} that matches any
+ string.
+
+ Below you can find an example of a \l TextInput object with a RegularExpressionValidator
+ specified:
+
+ \snippet qml/regularexpression.qml 0
+
+ Some more examples of regular expressions:
+
+ \list
+ \li A list of numbers with one to three positions separated by a comma:
+ \badcode
+ /\d{1,3}(?:,\d{1,3})+$/
+ \endcode
+
+ \li An amount consisting of up to 3 numbers before the decimal point, and
+ 1 to 2 after the decimal point:
+ \badcode
+ /(\d{1,3})([.,]\d{1,2})?$/
+ \endcode
+ \endlist
+*/
#endif // validator
diff --git a/src/quick/util/qquickvalidator_p.h b/src/quick/util/qquickvalidator_p.h
index 812e552d8e..9212efa044 100644
--- a/src/quick/util/qquickvalidator_p.h
+++ b/src/quick/util/qquickvalidator_p.h
@@ -95,6 +95,9 @@ QML_DECLARE_TYPE(QValidator)
QML_DECLARE_TYPE(QQuickIntValidator)
QML_DECLARE_TYPE(QQuickDoubleValidator)
QML_DECLARE_TYPE(QRegExpValidator)
+#if QT_CONFIG(regularexpression)
+QML_DECLARE_TYPE(QRegularExpressionValidator)
+#endif
#endif
#endif // QQUICKVALIDATOR_P_H
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index e4a03f3b52..0af29aed1c 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -109,6 +109,11 @@ qreal QQuickColorValueType::hslLightness() const
return v.lightnessF();
}
+bool QQuickColorValueType::isValid() const
+{
+ return v.isValid();
+}
+
void QQuickColorValueType::setR(qreal r)
{
v.setRedF(r);
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index 5a9af970e8..4305006f91 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -84,6 +84,7 @@ class QQuickColorValueType
Q_PROPERTY(qreal hslHue READ hslHue WRITE setHslHue FINAL)
Q_PROPERTY(qreal hslSaturation READ hslSaturation WRITE setHslSaturation FINAL)
Q_PROPERTY(qreal hslLightness READ hslLightness WRITE setHslLightness FINAL)
+ Q_PROPERTY(bool valid READ isValid)
Q_GADGET
public:
Q_INVOKABLE QString toString() const;
@@ -98,6 +99,7 @@ public:
qreal hslHue() const;
qreal hslSaturation() const;
qreal hslLightness() const;
+ bool isValid() const;
void setR(qreal);
void setG(qreal);
void setB(qreal);
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index c51f082d03..63d995e34c 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -15,6 +15,7 @@ SOURCES += \
$$PWD/qquicktimeline.cpp \
$$PWD/qquickpixmapcache.cpp \
$$PWD/qquickbehavior.cpp \
+ $$PWD/qquickboundaryrule.cpp \
$$PWD/qquickfontloader.cpp \
$$PWD/qquickstyledtext.cpp \
$$PWD/qquickimageprovider.cpp \
@@ -50,6 +51,7 @@ HEADERS += \
$$PWD/qquicktimeline_p_p.h \
$$PWD/qquickpixmapcache_p.h \
$$PWD/qquickbehavior_p.h \
+ $$PWD/qquickboundaryrule_p.h \
$$PWD/qquickfontloader_p.h \
$$PWD/qquickstyledtext_p.h \
$$PWD/qquickimageprovider.h \