aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quickcontrols/basic/Dial.qml2
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicdial.cpp32
-rw-r--r--src/quickcontrols/basic/impl/qquickbasicdial_p.h10
-rw-r--r--src/quickcontrols/doc/src/qtquickcontrols-imagine.qdoc6
-rw-r--r--src/quickcontrols/ios/Dial.qml4
-rw-r--r--src/quicknativestyle/items/qquickstyleitemdial.cpp4
-rw-r--r--src/quicknativestyle/qstyle/qquickcommonstyle.cpp9
-rw-r--r--src/quicknativestyle/qstyle/qquickstylehelper.cpp9
-rw-r--r--src/quicknativestyle/qstyle/qquickstyleoption.h2
-rw-r--r--src/quicktemplates/qquickdial.cpp211
-rw-r--r--src/quicktemplates/qquickdial_p.h10
-rw-r--r--tests/auto/quickcontrols/controls/data/tst_dial.qml153
12 files changed, 407 insertions, 45 deletions
diff --git a/src/quickcontrols/basic/Dial.qml b/src/quickcontrols/basic/Dial.qml
index 3692ae22de..8648c99442 100644
--- a/src/quickcontrols/basic/Dial.qml
+++ b/src/quickcontrols/basic/Dial.qml
@@ -20,6 +20,8 @@ T.Dial {
color: control.visualFocus ? control.palette.highlight : control.palette.dark
progress: control.position
opacity: control.enabled ? 1 : 0.3
+ startAngle: control.startAngle
+ endAngle: control.endAngle
}
handle: ColorImage {
diff --git a/src/quickcontrols/basic/impl/qquickbasicdial.cpp b/src/quickcontrols/basic/impl/qquickbasicdial.cpp
index 7726bfb159..d2550b7c27 100644
--- a/src/quickcontrols/basic/impl/qquickbasicdial.cpp
+++ b/src/quickcontrols/basic/impl/qquickbasicdial.cpp
@@ -29,6 +29,34 @@ void QQuickBasicDial::setProgress(qreal progress)
update();
}
+qreal QQuickBasicDial::startAngle() const
+{
+ return m_startAngle;
+}
+
+void QQuickBasicDial::setStartAngle(qreal startAngle)
+{
+ if (startAngle == m_startAngle)
+ return;
+
+ m_startAngle = startAngle;
+ update();
+}
+
+qreal QQuickBasicDial::endAngle() const
+{
+ return m_endAngle;
+}
+
+void QQuickBasicDial::setEndAngle(qreal endAngle)
+{
+ if (endAngle == m_endAngle)
+ return;
+
+ m_endAngle = endAngle;
+ update();
+}
+
QColor QQuickBasicDial::color() const
{
return m_color;
@@ -70,8 +98,8 @@ void QQuickBasicDial::paint(QPainter *painter)
painter->setRenderHint(QPainter::Antialiasing);
- const qreal startAngle = (140 + 90);
- const qreal spanAngle = (m_progress * 280) * -1;
+ const qreal startAngle = 90. - m_startAngle;
+ const qreal spanAngle = m_progress * (m_startAngle - m_endAngle);
QPainterPath path;
path.arcMoveTo(rect, startAngle);
path.arcTo(rect, startAngle, spanAngle);
diff --git a/src/quickcontrols/basic/impl/qquickbasicdial_p.h b/src/quickcontrols/basic/impl/qquickbasicdial_p.h
index 1406bf6906..31e533fdc8 100644
--- a/src/quickcontrols/basic/impl/qquickbasicdial_p.h
+++ b/src/quickcontrols/basic/impl/qquickbasicdial_p.h
@@ -25,6 +25,8 @@ class QQuickBasicDial : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL)
+ Q_PROPERTY(qreal startAngle READ startAngle WRITE setStartAngle FINAL)
+ Q_PROPERTY(qreal endAngle READ endAngle WRITE setEndAngle FINAL)
Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
QML_NAMED_ELEMENT(DialImpl)
QML_ADDED_IN_VERSION(2, 0)
@@ -35,6 +37,12 @@ public:
qreal progress() const;
void setProgress(qreal progress);
+ qreal startAngle() const;
+ void setStartAngle(qreal startAngle);
+
+ qreal endAngle() const;
+ void setEndAngle(qreal endAngle);
+
QColor color() const;
void setColor(const QColor &color);
@@ -42,6 +50,8 @@ public:
private:
qreal m_progress = 0;
+ qreal m_startAngle = -140.;
+ qreal m_endAngle = 140.;
QColor m_color = Qt::black;
};
diff --git a/src/quickcontrols/doc/src/qtquickcontrols-imagine.qdoc b/src/quickcontrols/doc/src/qtquickcontrols-imagine.qdoc
index 2e476c3b24..3b78bec57a 100644
--- a/src/quickcontrols/doc/src/qtquickcontrols-imagine.qdoc
+++ b/src/quickcontrols/doc/src/qtquickcontrols-imagine.qdoc
@@ -129,7 +129,7 @@
\li .9.png (or .png)
\row
\li \l Dial
- \li background
+ \li background\sup{1}
\li disabled, pressed, focused, mirrored, hovered
\li .9.png (or .png)
\row
@@ -469,6 +469,10 @@
\li .9.png (or .png)
\endtable
+    \note \sup{1}) The Imagine style Dial does not yet support the
+    \l {Dial::}{startAngle} and \l {Dial::}{endAngle} properties that were
+    introduced in Qt 6.6, and instead uses a fixed background image.
+
\section2 Asset Examples
The following table lists examples of assets (taken from the
diff --git a/src/quickcontrols/ios/Dial.qml b/src/quickcontrols/ios/Dial.qml
index fe21fdccc4..3fc77035b8 100644
--- a/src/quickcontrols/ios/Dial.qml
+++ b/src/quickcontrols/ios/Dial.qml
@@ -64,8 +64,8 @@ T.Dial {
centerY: control.background.children[0].height / 2
radiusX: control.background.children[0].width / 2 - 2
radiusY: radiusX
- startAngle: -230
- sweepAngle: 140 + control.angle
+ startAngle: control.startAngle - 90
+ sweepAngle: control.angle - control.startAngle
}
}
}
diff --git a/src/quicknativestyle/items/qquickstyleitemdial.cpp b/src/quicknativestyle/items/qquickstyleitemdial.cpp
index e2407e9e81..fe36f866e4 100644
--- a/src/quicknativestyle/items/qquickstyleitemdial.cpp
+++ b/src/quicknativestyle/items/qquickstyleitemdial.cpp
@@ -19,6 +19,8 @@ void QQuickStyleItemDial::connectToControl() const
connect(dial, &QQuickDial::positionChanged, this, &QQuickStyleItem::markImageDirty);
connect(dial, &QQuickDial::valueChanged, this, &QQuickStyleItem::markImageDirty);
connect(dial, &QQuickDial::stepSizeChanged, this, &QQuickStyleItem::markImageDirty);
+ connect(dial, &QQuickDial::startAngleChanged, this, &QQuickStyleItem::markImageDirty);
+ connect(dial, &QQuickDial::endAngleChanged, this, &QQuickStyleItem::markImageDirty);
connect(dial, &QQuickDial::pressedChanged, this, &QQuickStyleItem::markImageDirty);
}
@@ -54,6 +56,8 @@ void QQuickStyleItemDial::initStyleOption(QStyleOptionSlider &styleOption) const
styleOption.tickInterval = dial->stepSize();
styleOption.dialWrapping = dial->wrap();
styleOption.upsideDown = true;
+ styleOption.startAngle = dial->startAngle();
+ styleOption.endAngle = dial->endAngle();
if (dial->isPressed())
styleOption.state |= QStyle::State_Sunken;
diff --git a/src/quicknativestyle/qstyle/qquickcommonstyle.cpp b/src/quicknativestyle/qstyle/qquickcommonstyle.cpp
index 664ca4c528..a962a5792e 100644
--- a/src/quicknativestyle/qstyle/qquickcommonstyle.cpp
+++ b/src/quicknativestyle/qstyle/qquickcommonstyle.cpp
@@ -2900,14 +2900,13 @@ static StaticPolygonF<3> calcArrow(const QStyleOptionSlider *dial, qreal &a)
int r = qMin(width, height) / 2;
int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition);
+ qreal startAngle = (90. - dial->startAngle) * Q_PI / 180.;
+ qreal spanAngle = (dial->endAngle - dial->startAngle) * Q_PI / 180.;
if (dial->maximum == dial->minimum)
a = Q_PI / 2;
- else if (dial->dialWrapping)
- a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI
- / (dial->maximum - dial->minimum);
else
- a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI
- / (dial->maximum - dial->minimum)) / 6;
+ a = (startAngle - (currentSliderPosition - dial->minimum) * spanAngle
+ / (dial->maximum - dial->minimum));
int xc = width / 2;
int yc = height / 2;
diff --git a/src/quicknativestyle/qstyle/qquickstylehelper.cpp b/src/quicknativestyle/qstyle/qquickstylehelper.cpp
index dab6b041d8..6b73a5fcf3 100644
--- a/src/quicknativestyle/qstyle/qquickstylehelper.cpp
+++ b/src/quicknativestyle/qstyle/qquickstylehelper.cpp
@@ -121,14 +121,13 @@ static QPointF calcRadialPos(const QStyleOptionSlider *dial, qreal offset)
const int r = qMin(width, height) / 2;
const int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition);
qreal a = 0;
+ qreal startAngle = (90. - dial->startAngle) * Q_PI / 180.;
+ qreal spanAngle = (dial->endAngle - dial->startAngle) * Q_PI / 180.;
if (dial->maximum == dial->minimum)
a = Q_PI / 2;
- else if (dial->dialWrapping)
- a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI
- / (dial->maximum - dial->minimum);
else
- a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI
- / (dial->maximum - dial->minimum)) / 6;
+ a = (startAngle - (currentSliderPosition - dial->minimum) * spanAngle
+ / (dial->maximum - dial->minimum));
qreal xc = width / 2.0;
qreal yc = height / 2.0;
qreal len = r - QStyleHelper::calcBigLineSize(r) - 3;
diff --git a/src/quicknativestyle/qstyle/qquickstyleoption.h b/src/quicknativestyle/qstyle/qquickstyleoption.h
index e7770cc277..02b17dc121 100644
--- a/src/quicknativestyle/qstyle/qquickstyleoption.h
+++ b/src/quicknativestyle/qstyle/qquickstyleoption.h
@@ -514,6 +514,8 @@ public:
int pageStep;
qreal notchTarget;
bool dialWrapping;
+ qreal startAngle;
+ qreal endAngle;
QStyleOptionSlider();
QStyleOptionSlider(const QStyleOptionSlider &other) : QStyleOptionComplex(Version, Type) { *this = other; }
diff --git a/src/quicktemplates/qquickdial.cpp b/src/quicktemplates/qquickdial.cpp
index c5e35c39d2..c955e519ca 100644
--- a/src/quicktemplates/qquickdial.cpp
+++ b/src/quicktemplates/qquickdial.cpp
@@ -57,10 +57,16 @@ QT_BEGIN_NAMESPACE
by the user by either touch, mouse, or keys.
*/
-static const qreal startAngleRadians = (M_PI * 2.0) * (4.0 / 6.0);
-static const qreal startAngle = -140;
-static const qreal endAngleRadians = (M_PI * 2.0) * (5.0 / 6.0);
-static const qreal endAngle = 140;
+// The user angle is the clockwise angle between the position and the vertical
+// y-axis (12 o clock position).
+// Using radians for logic (atan2(...)) and degree for user interface
+constexpr qreal toUserAngleDeg(qreal logicAngleRad) {
+ // minus to turn clockwise, add 90 deg clockwise
+ return -logicAngleRad / M_PI * 180. + 90;
+}
+
+static const qreal defaultStartAngle = -140;
+static const qreal defaultEndAngle = 140;
class QQuickDialPrivate : public QQuickControlPrivate
{
@@ -74,7 +80,7 @@ public:
qreal linearPositionAt(const QPointF &point) const;
void setPosition(qreal position);
void updatePosition();
- bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const;
+ bool isLargeChange(qreal proposedPosition) const;
bool isHorizontalOrVertical() const;
bool handlePress(const QPointF &point, ulong timestamp) override;
@@ -91,6 +97,8 @@ public:
qreal to = 1;
qreal value = 0;
qreal position = 0;
+ qreal startAngle = defaultStartAngle;
+ qreal endAngle = defaultEndAngle;
qreal angle = startAngle;
qreal stepSize = 0;
QPointF pressPoint;
@@ -140,13 +148,34 @@ qreal QQuickDialPrivate::circularPositionAt(const QPointF &point) const
{
qreal yy = height / 2.0 - point.y();
qreal xx = point.x() - width / 2.0;
- qreal angle = (xx || yy) ? std::atan2(yy, xx) : 0;
+ qreal alpha = (xx || yy) ? toUserAngleDeg(std::atan2(yy, xx)) : 0;
+
+ // Move around the circle to reach the interval.
+ if (alpha < startAngle && alpha + 360. < endAngle)
+ alpha += 360.;
+ else if (alpha >= endAngle && alpha - 360. >= startAngle)
+ alpha -= 360.;
+
+ // If wrap is on and we are out of the interval [startAngle, endAngle],
+ // we want to jump to the closest border to make it feel nice and responsive
+ if ((alpha < startAngle || alpha > endAngle) && wrap) {
+ if (abs(alpha - startAngle) > abs(endAngle - alpha - 360.))
+ alpha += 360.;
+ else if (abs(alpha - startAngle - 360.) < abs(endAngle - alpha))
+ alpha -= 360.;
+ }
- if (angle < M_PI / -2)
- angle = angle + M_PI * 2;
+ // If wrap is off,
+ // we want to stay as close as possible to the current angle.
+ // This is important to allow easy setting of boundary values (0,1)
+ if (!wrap) {
+ if (abs(angle - alpha) > abs(angle - (alpha + 360.)))
+ alpha += 360.;
+ if (abs(angle - alpha) > abs(angle - (alpha - 360.)))
+ alpha -= 360.;
+ }
- qreal normalizedAngle = (startAngleRadians - angle) / endAngleRadians;
- return normalizedAngle;
+ return (alpha - startAngle) / (endAngle - startAngle);
}
qreal QQuickDialPrivate::linearPositionAt(const QPointF &point) const
@@ -179,12 +208,13 @@ void QQuickDialPrivate::setPosition(qreal pos)
{
Q_Q(QQuickDial);
pos = qBound<qreal>(qreal(0), pos, qreal(1));
- if (qFuzzyCompare(position, pos))
+ const qreal alpha = startAngle + pos * qAbs(endAngle - startAngle);
+ if (qFuzzyCompare(position, pos) && qFuzzyCompare(angle, alpha))
return;
+ angle = alpha;
position = pos;
- angle = startAngle + position * qAbs(endAngle - startAngle);
emit q->positionChanged();
emit q->angleChanged();
@@ -198,9 +228,11 @@ void QQuickDialPrivate::updatePosition()
setPosition(pos);
}
-bool QQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPosition) const
+bool QQuickDialPrivate::isLargeChange(qreal proposedPosition) const
{
- return qAbs(proposedPosition - position) >= qreal(0.5) && eventPos.y() >= height / 2;
+ if (endAngle - startAngle < 180)
+ return false;
+ return qAbs(proposedPosition - position) > qreal(0.5);
}
bool QQuickDialPrivate::isHorizontalOrVertical() const
@@ -223,11 +255,11 @@ bool QQuickDialPrivate::handleMove(const QPointF &point, ulong timestamp)
Q_Q(QQuickDial);
QQuickControlPrivate::handleMove(point, timestamp);
const qreal oldPos = position;
- qreal pos = positionAt(point);
+ qreal pos = qBound(0.0, positionAt(point), 1.0);
if (snapMode == QQuickDial::SnapAlways)
pos = snapPosition(pos);
- if (wrap || isHorizontalOrVertical() || !isLargeChange(point, pos)) {
+ if (wrap || isHorizontalOrVertical() || !isLargeChange(pos)) {
if (live)
q->setValue(valueAt(pos));
else
@@ -248,7 +280,7 @@ bool QQuickDialPrivate::handleRelease(const QPointF &point, ulong timestamp)
if (snapMode != QQuickDial::NoSnap)
pos = snapPosition(pos);
- if (wrap || isHorizontalOrVertical() || !isLargeChange(point, pos))
+ if (wrap || isHorizontalOrVertical() || !isLargeChange(pos))
q->setValue(valueAt(pos));
if (!qFuzzyCompare(pos, oldPos))
emit q->moved();
@@ -420,11 +452,12 @@ qreal QQuickDial::position() const
\qmlproperty real QtQuick.Controls::Dial::angle
\readonly
- This property holds the angle of the handle.
+ This property holds the clockwise angle of the handle in degrees.
- The range is from \c -140 degrees to \c 140 degrees.
+ The angle is zero at the 12 o'clock position and the range is from
+ \l startAngle to \c endAngle.
- \sa position
+ \sa position, startAngle, endAngle
*/
qreal QQuickDial::angle() const
{
@@ -467,6 +500,129 @@ void QQuickDial::setStepSize(qreal step)
emit stepSizeChanged();
}
+
+/*!
+ \qmlproperty real QtQuick.Controls::Dial::startAngle
+ \since 6.6
+
+ This property holds the starting angle of the dial in degrees.
+
+ This is the \l angle the dial will have for its minimum value, i.e. \l from.
+ The \l startAngle has to be smaller than the \l endAngle, larger than -360
+ and larger or equal to the \l endAngle - 360 degrees.
+
+ \sa endAngle, angle
+*/
+qreal QQuickDial::startAngle() const
+{
+ Q_D(const QQuickDial);
+ return d->startAngle;
+}
+
+void QQuickDial::setStartAngle(qreal startAngle)
+{
+ Q_D(QQuickDial);
+ if (!d->componentComplete) {
+ // Binding evaluation order can cause warnings with certain combinations
+ // of start and end angles, so delay the actual setting until after component completion.
+ // Store the requested value in the existing member to avoid the need for an extra one.
+ d->startAngle = startAngle;
+ return;
+ }
+
+ if (qFuzzyCompare(d->startAngle, startAngle))
+ return;
+
+ // do not allow to change direction
+ if (startAngle >= d->endAngle) {
+ qmlWarning(this) << "startAngle (" << startAngle
+ << ") cannot be greater than or equal to endAngle (" << d->endAngle << ")";
+ return;
+ }
+
+ // Keep the interval around 0
+ if (startAngle <= -360.) {
+ qmlWarning(this) << "startAngle (" << startAngle << ") cannot be less than or equal to -360";
+ return;
+ }
+
+ // keep the interval [startAngle, endAngle] unique
+ if (startAngle < d->endAngle - 360.) {
+ qmlWarning(this) << "Difference between startAngle (" << startAngle
+ << ") and endAngle (" << d->endAngle << ") cannot be greater than 360."
+ << " Changing endAngle to avoid overlaps.";
+ d->endAngle = startAngle + 360.;
+ emit endAngleChanged();
+ }
+
+ d->startAngle = startAngle;
+ // changing the startAngle will change the angle
+ // if the value is kept constant
+ d->updatePosition();
+ emit startAngleChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::Dial::endAngle
+ \since 6.6
+
+ This property holds the end angle of the dial in degrees.
+
+ This is the \l angle the dial will have for its maximum value, i.e. \l to.
+ The \l endAngle has to be bigger than the \l startAngle, smaller than 720
+ and smaller or equal than the \l startAngle + 360 degrees.
+
+ \sa endAngle, angle
+*/
+qreal QQuickDial::endAngle() const
+{
+ Q_D(const QQuickDial);
+ return d->endAngle;
+
+}
+
+void QQuickDial::setEndAngle(qreal endAngle)
+{
+ Q_D(QQuickDial);
+ if (!d->componentComplete) {
+ // Binding evaluation order can cause warnings with certain combinations
+ // of start and end angles, so delay the actual setting until after component completion.
+ // Store the requested value in the existing member to avoid the need for an extra one.
+ d->endAngle = endAngle;
+ return;
+ }
+
+ if (qFuzzyCompare(d->endAngle, endAngle))
+ return;
+
+ if (endAngle <= d->startAngle) {
+ qmlWarning(this) << "endAngle (" << endAngle
+ << ") cannot be less than or equal to startAngle (" << d->startAngle << ")";
+ return;
+ }
+
+ // Keep the interval around 0
+ if (endAngle >= 720.) {
+ qmlWarning(this) << "endAngle (" << endAngle << ") cannot be greater than or equal to 720";
+ return;
+ }
+
+ // keep the interval [startAngle, endAngle] unique
+ if (endAngle > d->startAngle + 360.) {
+ qmlWarning(this) << "Difference between startAngle (" << d->startAngle
+ << ") and endAngle (" << endAngle << ") cannot be greater than 360."
+ << " Changing startAngle to avoid overlaps.";
+ d->startAngle = endAngle - 360.;
+ emit startAngleChanged();
+ }
+
+ d->endAngle = endAngle;
+ // changing the startAngle will change the angle
+ // if the value is kept constant
+ d->updatePosition();
+ emit endAngleChanged();
+}
+
/*!
\qmlproperty enumeration QtQuick.Controls::Dial::snapMode
@@ -806,6 +962,21 @@ void QQuickDial::componentComplete()
Q_D(QQuickDial);
d->executeHandle(true);
QQuickControl::componentComplete();
+
+ // Set the (delayed) start and end angles, if necessary (see the setters for more info).
+ if (!qFuzzyCompare(d->startAngle, defaultStartAngle)) {
+ const qreal startAngle = d->startAngle;
+ // Temporarily set it to something else so that it sees that it has changed.
+ d->startAngle = defaultStartAngle;
+ setStartAngle(startAngle);
+ }
+
+ if (!qFuzzyCompare(d->endAngle, defaultEndAngle)) {
+ const qreal endAngle = d->endAngle;
+ d->endAngle = defaultEndAngle;
+ setEndAngle(endAngle);
+ }
+
setValue(d->value);
d->updatePosition();
}
diff --git a/src/quicktemplates/qquickdial_p.h b/src/quicktemplates/qquickdial_p.h
index c716b9671b..b291fc673e 100644
--- a/src/quicktemplates/qquickdial_p.h
+++ b/src/quicktemplates/qquickdial_p.h
@@ -32,6 +32,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDial : public QQuickControl
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged FINAL)
Q_PROPERTY(qreal position READ position NOTIFY positionChanged FINAL)
Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged FINAL)
+ Q_PROPERTY(qreal startAngle READ startAngle WRITE setStartAngle NOTIFY startAngleChanged FINAL REVISION(6, 6))
+ Q_PROPERTY(qreal endAngle READ endAngle WRITE setEndAngle NOTIFY endAngleChanged FINAL REVISION(6, 6))
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL)
@@ -64,6 +66,12 @@ public:
qreal stepSize() const;
void setStepSize(qreal step);
+ qreal startAngle() const;
+ void setStartAngle(qreal startAngle);
+
+ qreal endAngle() const;
+ void setEndAngle(qreal endAngle);
+
enum SnapMode {
NoSnap,
SnapAlways,
@@ -118,6 +126,8 @@ Q_SIGNALS:
Q_REVISION(2, 2) void liveChanged();
// 2.5 (Qt 5.12)
Q_REVISION(2, 5) void inputModeChanged();
+ Q_REVISION(6, 6) void startAngleChanged();
+ Q_REVISION(6, 6) void endAngleChanged();
protected:
void keyPressEvent(QKeyEvent *event) override;
diff --git a/tests/auto/quickcontrols/controls/data/tst_dial.qml b/tests/auto/quickcontrols/controls/data/tst_dial.qml
index 3fcf8c7e88..1f8c1b3827 100644
--- a/tests/auto/quickcontrols/controls/data/tst_dial.qml
+++ b/tests/auto/quickcontrols/controls/data/tst_dial.qml
@@ -228,29 +228,30 @@ TestCase {
mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton);
var positionAtPress = dial.position;
mouseMove(dial, dial.width * 0.5, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseMove(dial, dial.width * 0.75, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseRelease(dial, dial.width * 0.75, yPos, Qt.LeftButton);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
// Try the same thing, but a bit higher.
yPos = dial.height * 0.6;
mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton);
positionAtPress = dial.position;
mouseMove(dial, dial.width * 0.5, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseMove(dial, dial.width * 0.75, yPos);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
mouseRelease(dial, dial.width * 0.75, yPos, Qt.LeftButton);
- compare(dial.position, positionAtPress);
+ verify(dial.position < positionAtPress);
// Going from below the center of the dial to above it should work (once it gets above the center).
mousePress(dial, dial.width * 0.25, dial.height * 0.75, Qt.LeftButton);
positionAtPress = dial.position;
mouseMove(dial, dial.width * 0.5, dial.height * 0.6);
- compare(dial.position, positionAtPress);
- mouseMove(dial, dial.width * 0.75, dial.height * 0.4);
+ verify(dial.position < positionAtPress);
+ mouseMove(dial, dial.width * 0.5, dial.height * 0.4); //move over the top
+ mouseMove(dial, dial.width * 0.75, dial.height * 0.6); //and back down again
verify(dial.position > positionAtPress);
mouseRelease(dial, dial.width * 0.75, dial.height * 0.3, Qt.LeftButton);
verify(dial.position > positionAtPress);
@@ -289,7 +290,8 @@ TestCase {
positionAtPress = dial.position;
touch.move(0, dial, dial.width * 0.5, dial.height * 0.6).commit();
compare(dial.position, positionAtPress);
- touch.move(0, dial, dial.width * 0.75, dial.height * 0.4).commit();
+ touch.move(0, dial, dial.width * 0.5, dial.height * 0.4).commit(); //move over the top
+ touch.move(0, dial, dial.width * 0.75, dial.height * 0.6).commit(); //and back down again
verify(dial.position > positionAtPress);
touch.release(0, dial, dial.width * 0.75, dial.height * 0.3).commit();
verify(dial.position > positionAtPress);
@@ -434,7 +436,7 @@ TestCase {
{ tag: "NoSnap", snapMode: Dial.NoSnap, from: 0, to: 2, values: [0, 0, 1], positions: [0, 0.5, 0.5] },
{ tag: "SnapAlways (0..2)", snapMode: Dial.SnapAlways, from: 0, to: 2, values: [0.0, 0.0, 1.0], positions: [0.0, 0.5, 0.5] },
{ tag: "SnapAlways (1..3)", snapMode: Dial.SnapAlways, from: 1, to: 3, values: [1.0, 1.0, 2.0], positions: [0.0, 0.5, 0.5] },
- { tag: "SnapAlways (-1..1)", snapMode: Dial.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, 0.0], positions: [0.5, 0.5, 0.5] },
+ { tag: "SnapAlways (-1..1)", snapMode: Dial.SnapAlways, from: -1, to: 1, values: [0.0, 0.0, 0.0], positions: [immediate ? 0.0 : 0.5, 0.5, 0.5] },
{ tag: "SnapAlways (1..-1)", snapMode: Dial.SnapAlways, from: 1, to: -1, values: [1.0, 1.0, 0.0], positions: [0.0, 0.5, 0.5] },
{ tag: "SnapOnRelease (0..2)", snapMode: Dial.SnapOnRelease, from: 0, to: 2, values: [0.0, 0.0, 1.0], positions: [0.0, 0.5, 0.5] },
{ tag: "SnapOnRelease (1..3)", snapMode: Dial.SnapOnRelease, from: 1, to: 3, values: [1.0, 1.0, 2.0], positions: [0.0, 0.5, 0.5] },
@@ -661,4 +663,135 @@ TestCase {
keyClick(Qt.Key_Right)
}
}
+
+ function test_startEndAngle_data() {
+ return [
+ {
+ tag: "Default wrap", startAngle: -140, endAngle: 140, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.5-0.32, 0.5, 0.5+0.32, 1.0, 0.0], //140/90*0.5 = 0.32
+ angles: [-140.0, -90.0, 0.0, 90.0, 140.0, -140.0]
+ },
+ {
+ tag: "-30..30 wrap", startAngle: -30, endAngle: 30, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.0, 0.5, 1.0, 1.0, 0.0],
+ angles: [-30.0, -30.0, 0.0, 30.0, 30.0, -30.0]
+ },
+ {
+ tag: "-180..180 wrap", startAngle: -180, endAngle: 180, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.25, 0.5, 0.75, 1.0, 0.0],
+ angles: [-180.0, -90.0, 0.0, 90.0, 180.0, -180.0]
+ },
+ {
+ tag: "90..360 wrap", startAngle: 90, endAngle: 360, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.33, 0.66, 1.0, 0.0, 0.33, 0.33],
+ angles: [180.0, 270.0, 360.0, 90.0, 180.0, 180.0]
+ },
+ {
+ tag: "90..450 wrap", startAngle: 90, endAngle: 450, from: 0, to: 1, wrap: true,
+ x: [0.49, 0.25, 0.5, 0.75, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.49, 0.501, 0.99, 0.99],
+ values: [0.25, 0.5, 0.75, 1.0, 0.0, 0.5, 0.5],
+ angles: [180.0, 270.0, 360.0, 450.0, 90.0, 180.0, 180.0]
+ },
+ {
+ tag: "Default nowrap", startAngle: -140, endAngle: 140, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.5-0.32, 0.5, 0.5+0.32, 1.0, 1.0], //140/90*0.5 = 0.32
+ angles: [-140.0, -90.0, 0.0, 90.0, 140.0, 140.0]
+ },
+ {
+ tag: "-30..30 nowrap", startAngle: -30, endAngle: 30, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.0, 0.5, 1.0, 1.0, 1.0],
+ angles: [-30.0, -30.0, 0.0, 30.0, 30.0, 30.0]
+ },
+ {
+ tag: "-180..180 nowrap", startAngle: -180, endAngle: 180, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.0, 0.25, 0.5, 0.75, 1.0, 1.0],
+ angles: [-180.0, -90.0, 0.0, 90.0, 180.0, 180.0]
+ },
+ {
+ tag: "90..360 nowrap", startAngle: 90, endAngle: 360, from: 0, to: 1, wrap: false,
+ x: [0.49, 0.25, 0.5, 0.75, 0.51, 0.49],
+ y: [0.99, 0.5, 0.01, 0.5, 0.99, 0.99],
+ values: [0.33, 0.66, 1.0, 1.0, 1.0, 1.0],
+ angles: [180.0, 270.0, 360.0, 360.0, 360.0, 360.0]
+ }
+ ]
+ }
+
+ function test_startEndAngle(data) {
+ let dial = createTemporaryObject(dialComponent, testCase)
+ verify(dial)
+
+ dial.startAngle = data.startAngle
+ dial.endAngle = data.endAngle
+ dial.from = data.from
+ dial.to = data.to
+ //Give a defined start in case wrap = true
+ dial.value = data.values[0]
+ dial.wrap = data.wrap
+
+ compare(dial.startAngle, data.startAngle)
+ compare(dial.endAngle, data.endAngle)
+
+
+ for (let i = 0; i < data.x.length; i++) {
+ mousePress(dial, dial.width * data.x[i], dial.height * 0.5 + dial.width * ( data.y[i] - 0.5))
+ fuzzyCompare(dial.angle, data.angles[i], 3.0)
+ fuzzyCompare(dial.value, data.values[i], 0.3)
+ }
+ }
+
+ function test_startEndAngleWarnings(data) {
+ // Fail on any warning that we don't expect.
+ failOnWarning(/.?/)
+
+ let dial = createTemporaryObject(dialComponent, testCase)
+ verify(dial)
+
+ dial.startAngle = -180.
+ dial.endAngle = 180.
+
+ //provoke warning
+ ignoreWarning(new RegExp("Changing endAngle to avoid overlaps"))
+ dial.startAngle = -270.
+ dial.endAngle = 90.
+
+ compare(dial.startAngle, -270.)
+ compare(dial.endAngle, 90.)
+
+
+ dial.startAngle = -180.
+ dial.endAngle = 180.
+
+ //provoke warning
+ ignoreWarning(new RegExp("Changing startAngle to avoid overlaps"))
+ dial.endAngle = 270.
+ dial.startAngle = -90.
+
+ compare(dial.startAngle, -90.)
+ compare(dial.endAngle, 270.)
+
+ {
+ // Should not warn since we delay the setting of start and end angles to avoid
+ // binding order evaluation conflicts.
+ let dial = createTemporaryObject(dialComponent, testCase, { startAngle: -10, endAngle: 300 })
+ verify(dial)
+ compare(dial.startAngle, -10.)
+ compare(dial.endAngle, 300.)
+ }
+ }
}