1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickslider_p.h"
5#include "qquickcontrol_p_p.h"
6#include "qquickdeferredexecute_p_p.h"
7
8#include <QtQuick/private/qquickwindow_p.h>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \qmltype Slider
14 \inherits Control
15//! \instantiates QQuickSlider
16 \inqmlmodule QtQuick.Controls
17 \since 5.7
18 \ingroup qtquickcontrols-input
19 \brief Used to select a value by sliding a handle along a track.
20
21 \image qtquickcontrols-slider.gif
22
23 Slider is used to select a value by sliding a handle along a track.
24
25 In the example below, custom \l from, \l value, and \l to values are set:
26
27 \code
28 Slider {
29 from: 1
30 value: 25
31 to: 100
32 }
33 \endcode
34
35 The \l position property is expressed as a fraction of the control's size,
36 in the range \c {0.0 - 1.0}. The \l visualPosition property is
37 the same, except that it is reversed in a
38 \l {Right-to-left User Interfaces}{right-to-left} application. The
39 visualPosition is useful for positioning the handle when styling Slider.
40 In the example above, \l visualPosition will be \c 0.24 in a left-to-right
41 application, and \c 0.76 in a right-to-left application.
42
43 For a slider that allows the user to select a range by providing two
44 handles, see \l RangeSlider.
45
46 \sa {Customizing Slider}, {Input Controls}
47*/
48
49/*!
50 \since QtQuick.Controls 2.2 (Qt 5.9)
51 \qmlsignal QtQuick.Controls::Slider::moved()
52
53 This signal is emitted when the slider has been interactively moved
54 by the user by either touch, mouse, wheel, or keys.
55*/
56
57class QQuickSliderPrivate : public QQuickControlPrivate
58{
59 Q_DECLARE_PUBLIC(QQuickSlider)
60
61public:
62 qreal snapPosition(qreal position) const;
63 qreal positionAt(const QPointF &point) const;
64 void setPosition(qreal position);
65 void updatePosition();
66
67 bool handlePress(const QPointF &point, ulong timestamp) override;
68 bool handleMove(const QPointF &point, ulong timestamp) override;
69 bool handleRelease(const QPointF &point, ulong timestamp) override;
70 void handleUngrab() override;
71
72 void cancelHandle();
73 void executeHandle(bool complete = false);
74
75 void itemImplicitWidthChanged(QQuickItem *item) override;
76 void itemImplicitHeightChanged(QQuickItem *item) override;
77
78 qreal from = 0;
79 qreal to = 1;
80 qreal value = 0;
81 qreal position = 0;
82 qreal stepSize = 0;
83 qreal touchDragThreshold = -1; // in QQuickWindowPrivate::dragOverThreshold, '-1' implies using styleHints::startDragDistance()
84 bool live = true;
85 bool pressed = false;
86 QPointF pressPoint;
87 Qt::Orientation orientation = Qt::Horizontal;
88 QQuickSlider::SnapMode snapMode = QQuickSlider::NoSnap;
89 QQuickDeferredPointer<QQuickItem> handle;
90};
91
92qreal QQuickSliderPrivate::snapPosition(qreal position) const
93{
94 const qreal range = to - from;
95 if (qFuzzyIsNull(d: range))
96 return position;
97
98 const qreal effectiveStep = stepSize / range;
99 if (qFuzzyIsNull(d: effectiveStep))
100 return position;
101
102 return qRound(d: position / effectiveStep) * effectiveStep;
103}
104
105qreal QQuickSliderPrivate::positionAt(const QPointF &point) const
106{
107 Q_Q(const QQuickSlider);
108 qreal pos = 0.0;
109 if (orientation == Qt::Horizontal) {
110 const qreal hw = handle ? handle->width() : 0;
111 const qreal offset = hw / 2;
112 const qreal extent = q->availableWidth() - hw;
113 if (!qFuzzyIsNull(d: extent)) {
114 if (q->isMirrored())
115 pos = (q->width() - point.x() - q->rightPadding() - offset) / extent;
116 else
117 pos = (point.x() - q->leftPadding() - offset) / extent;
118 }
119 } else {
120 const qreal hh = handle ? handle->height() : 0;
121 const qreal offset = hh / 2;
122 const qreal extent = q->availableHeight() - hh;
123 if (!qFuzzyIsNull(d: extent))
124 pos = (q->height() - point.y() - q->bottomPadding() - offset) / extent;
125 }
126 return qBound<qreal>(min: 0.0, val: pos, max: 1.0);
127}
128
129void QQuickSliderPrivate::setPosition(qreal pos)
130{
131 Q_Q(QQuickSlider);
132 pos = qBound<qreal>(min: 0.0, val: pos, max: 1.0);
133 if (qFuzzyCompare(p1: position, p2: pos))
134 return;
135
136 position = pos;
137 emit q->positionChanged();
138 emit q->visualPositionChanged();
139}
140
141void QQuickSliderPrivate::updatePosition()
142{
143 qreal pos = 0;
144 if (!qFuzzyCompare(p1: from, p2: to))
145 pos = (value - from) / (to - from);
146 setPosition(pos);
147}
148
149bool QQuickSliderPrivate::handlePress(const QPointF &point, ulong timestamp)
150{
151 Q_Q(QQuickSlider);
152 QQuickControlPrivate::handlePress(point, timestamp);
153 pressPoint = point;
154 q->setPressed(true);
155 return true;
156}
157
158bool QQuickSliderPrivate::handleMove(const QPointF &point, ulong timestamp)
159{
160 Q_Q(QQuickSlider);
161 QQuickControlPrivate::handleMove(point, timestamp);
162 const qreal oldPos = position;
163 qreal pos = positionAt(point);
164 if (snapMode == QQuickSlider::SnapAlways)
165 pos = snapPosition(position: pos);
166 if (live)
167 q->setValue(q->valueAt(position: pos));
168 if (!live || snapMode == QQuickSlider::NoSnap || snapMode == QQuickSlider::SnapOnRelease)
169 setPosition(pos);
170 if (!qFuzzyCompare(p1: pos, p2: oldPos))
171 emit q->moved();
172 return true;
173}
174
175bool QQuickSliderPrivate::handleRelease(const QPointF &point, ulong timestamp)
176{
177 Q_Q(QQuickSlider);
178 QQuickControlPrivate::handleRelease(point, timestamp);
179 pressPoint = QPointF();
180 const qreal oldPos = position;
181 qreal pos = positionAt(point);
182 if (snapMode != QQuickSlider::NoSnap)
183 pos = snapPosition(position: pos);
184 qreal val = q->valueAt(position: pos);
185 if (!qFuzzyCompare(p1: val, p2: value))
186 q->setValue(val);
187 else if (snapMode != QQuickSlider::NoSnap)
188 setPosition(pos);
189 if (!qFuzzyCompare(p1: pos, p2: oldPos))
190 emit q->moved();
191 q->setKeepMouseGrab(false);
192 q->setKeepTouchGrab(false);
193 q->setPressed(false);
194 return true;
195}
196
197void QQuickSliderPrivate::handleUngrab()
198{
199 Q_Q(QQuickSlider);
200 QQuickControlPrivate::handleUngrab();
201 pressPoint = QPointF();
202 q->setPressed(false);
203}
204
205void QQuickSliderPrivate::cancelHandle()
206{
207 Q_Q(QQuickSlider);
208 quickCancelDeferred(object: q, property: handleName());
209}
210
211void QQuickSliderPrivate::executeHandle(bool complete)
212{
213 Q_Q(QQuickSlider);
214 if (handle.wasExecuted())
215 return;
216
217 if (!handle || complete)
218 quickBeginDeferred(object: q, property: handleName(), delegate&: handle);
219 if (complete)
220 quickCompleteDeferred(object: q, property: handleName(), delegate&: handle);
221}
222
223void QQuickSliderPrivate::itemImplicitWidthChanged(QQuickItem *item)
224{
225 Q_Q(QQuickSlider);
226 QQuickControlPrivate::itemImplicitWidthChanged(item);
227 if (item == handle)
228 emit q->implicitHandleWidthChanged();
229}
230
231void QQuickSliderPrivate::itemImplicitHeightChanged(QQuickItem *item)
232{
233 Q_Q(QQuickSlider);
234 QQuickControlPrivate::itemImplicitHeightChanged(item);
235 if (item == handle)
236 emit q->implicitHandleHeightChanged();
237}
238
239QQuickSlider::QQuickSlider(QQuickItem *parent)
240 : QQuickControl(*(new QQuickSliderPrivate), parent)
241{
242 setActiveFocusOnTab(true);
243#ifdef Q_OS_MACOS
244 setFocusPolicy(Qt::TabFocus);
245#else
246 setFocusPolicy(Qt::StrongFocus);
247#endif
248 setAcceptedMouseButtons(Qt::LeftButton);
249#if QT_CONFIG(quicktemplates2_multitouch)
250 setAcceptTouchEvents(true);
251#endif
252#if QT_CONFIG(cursor)
253 setCursor(Qt::ArrowCursor);
254#endif
255}
256
257QQuickSlider::~QQuickSlider()
258{
259 Q_D(QQuickSlider);
260 d->removeImplicitSizeListener(item: d->handle);
261}
262
263/*!
264 \qmlproperty real QtQuick.Controls::Slider::from
265
266 This property holds the starting value for the range. The default value is \c 0.0.
267
268 \sa to, value
269*/
270qreal QQuickSlider::from() const
271{
272 Q_D(const QQuickSlider);
273 return d->from;
274}
275
276void QQuickSlider::setFrom(qreal from)
277{
278 Q_D(QQuickSlider);
279 if (qFuzzyCompare(p1: d->from, p2: from))
280 return;
281
282 d->from = from;
283 emit fromChanged();
284 if (isComponentComplete()) {
285 setValue(d->value);
286 d->updatePosition();
287 }
288}
289
290/*!
291 \qmlproperty real QtQuick.Controls::Slider::to
292
293 This property holds the end value for the range. The default value is \c 1.0.
294
295 \sa from, value
296*/
297qreal QQuickSlider::to() const
298{
299 Q_D(const QQuickSlider);
300 return d->to;
301}
302
303void QQuickSlider::setTo(qreal to)
304{
305 Q_D(QQuickSlider);
306 if (qFuzzyCompare(p1: d->to, p2: to))
307 return;
308
309 d->to = to;
310 emit toChanged();
311 if (isComponentComplete()) {
312 setValue(d->value);
313 d->updatePosition();
314 }
315}
316
317/*!
318 \qmlproperty real QtQuick.Controls::Slider::value
319
320 This property holds the value in the range \c from - \c to. The default value is \c 0.0.
321
322 \sa position
323*/
324qreal QQuickSlider::value() const
325{
326 Q_D(const QQuickSlider);
327 return d->value;
328}
329
330void QQuickSlider::setValue(qreal value)
331{
332 Q_D(QQuickSlider);
333 if (isComponentComplete())
334 value = d->from > d->to ? qBound(min: d->to, val: value, max: d->from) : qBound(min: d->from, val: value, max: d->to);
335
336 if (qFuzzyCompare(p1: d->value, p2: value))
337 return;
338
339 d->value = value;
340 d->updatePosition();
341 emit valueChanged();
342}
343
344/*!
345 \qmlproperty real QtQuick.Controls::Slider::position
346 \readonly
347
348 This property holds the logical position of the handle.
349
350 The position is expressed as a fraction of the control's size, in the range
351 \c {0.0 - 1.0}. For visualizing a slider, the right-to-left aware
352 \l visualPosition should be used instead.
353
354 \sa value, visualPosition, valueAt()
355*/
356qreal QQuickSlider::position() const
357{
358 Q_D(const QQuickSlider);
359 return d->position;
360}
361
362/*!
363 \qmlproperty real QtQuick.Controls::Slider::visualPosition
364 \readonly
365
366 This property holds the visual position of the handle.
367
368 The position is expressed as a fraction of the control's size, in the range
369 \c {0.0 - 1.0}. When the control is \l {Control::mirrored}{mirrored}, the
370 value is equal to \c {1.0 - position}. This makes the value suitable for
371 visualizing the slider, taking right-to-left support into account.
372
373 \sa position
374*/
375qreal QQuickSlider::visualPosition() const
376{
377 Q_D(const QQuickSlider);
378 if (d->orientation == Qt::Vertical || isMirrored())
379 return 1.0 - d->position;
380 return d->position;
381}
382
383/*!
384 \qmlproperty real QtQuick.Controls::Slider::stepSize
385
386 This property holds the step size. The default value is \c 0.0.
387
388 \sa snapMode, increase(), decrease()
389*/
390qreal QQuickSlider::stepSize() const
391{
392 Q_D(const QQuickSlider);
393 return d->stepSize;
394}
395
396void QQuickSlider::setStepSize(qreal step)
397{
398 Q_D(QQuickSlider);
399 if (qFuzzyCompare(p1: d->stepSize, p2: step))
400 return;
401
402 d->stepSize = step;
403 emit stepSizeChanged();
404}
405
406/*!
407 \qmlproperty enumeration QtQuick.Controls::Slider::snapMode
408
409 This property holds the snap mode.
410
411 The snap mode determines how the slider handle behaves with
412 regards to the \l stepSize.
413
414 Possible values:
415 \value Slider.NoSnap The slider does not snap (default).
416 \value Slider.SnapAlways The slider snaps while the handle is dragged.
417 \value Slider.SnapOnRelease The slider does not snap while being dragged, but only after the handle is released.
418
419 In the following table, the various modes are illustrated with animations.
420 The movement of the mouse cursor and the \l stepSize (\c 0.2) are identical
421 in each animation.
422
423 \table
424 \header
425 \row \li \b Value \li \b Example
426 \row \li \c Slider.NoSnap \li \image qtquickcontrols-slider-nosnap.gif
427 \row \li \c Slider.SnapAlways \li \image qtquickcontrols-slider-snapalways.gif
428 \row \li \c Slider.SnapOnRelease \li \image qtquickcontrols-slider-snaponrelease.gif
429 \endtable
430
431 \sa stepSize
432*/
433QQuickSlider::SnapMode QQuickSlider::snapMode() const
434{
435 Q_D(const QQuickSlider);
436 return d->snapMode;
437}
438
439void QQuickSlider::setSnapMode(SnapMode mode)
440{
441 Q_D(QQuickSlider);
442 if (d->snapMode == mode)
443 return;
444
445 d->snapMode = mode;
446 emit snapModeChanged();
447}
448
449/*!
450 \qmlproperty bool QtQuick.Controls::Slider::pressed
451
452 This property holds whether the slider is pressed by either touch, mouse,
453 or keys.
454*/
455bool QQuickSlider::isPressed() const
456{
457 Q_D(const QQuickSlider);
458 return d->pressed;
459}
460
461void QQuickSlider::setPressed(bool pressed)
462{
463 Q_D(QQuickSlider);
464 if (d->pressed == pressed)
465 return;
466
467 d->pressed = pressed;
468 setAccessibleProperty(propertyName: "pressed", value: pressed);
469 emit pressedChanged();
470}
471
472/*!
473 \since QtQuick.Controls 2.3 (Qt 5.10)
474 \qmlproperty bool QtQuick.Controls::Slider::horizontal
475 \readonly
476
477 This property holds whether the slider is horizontal.
478
479 \sa orientation
480*/
481bool QQuickSlider::isHorizontal() const
482{
483 Q_D(const QQuickSlider);
484 return d->orientation == Qt::Horizontal;
485}
486
487/*!
488 \since QtQuick.Controls 2.3 (Qt 5.10)
489 \qmlproperty bool QtQuick.Controls::Slider::vertical
490 \readonly
491
492 This property holds whether the slider is vertical.
493
494 \sa orientation
495*/
496bool QQuickSlider::isVertical() const
497{
498 Q_D(const QQuickSlider);
499 return d->orientation == Qt::Vertical;
500}
501
502/*!
503 \qmlproperty enumeration QtQuick.Controls::Slider::orientation
504
505 This property holds the orientation.
506
507 Possible values:
508 \value Qt.Horizontal Horizontal (default)
509 \value Qt.Vertical Vertical
510
511 \sa horizontal, vertical
512*/
513Qt::Orientation QQuickSlider::orientation() const
514{
515 Q_D(const QQuickSlider);
516 return d->orientation;
517}
518
519void QQuickSlider::setOrientation(Qt::Orientation orientation)
520{
521 Q_D(QQuickSlider);
522 if (d->orientation == orientation)
523 return;
524
525 d->orientation = orientation;
526 emit orientationChanged();
527}
528
529/*!
530 \qmlproperty Item QtQuick.Controls::Slider::handle
531
532 This property holds the handle item.
533
534 \sa {Customizing Slider}
535*/
536QQuickItem *QQuickSlider::handle() const
537{
538 QQuickSliderPrivate *d = const_cast<QQuickSliderPrivate *>(d_func());
539 if (!d->handle)
540 d->executeHandle();
541 return d->handle;
542}
543
544void QQuickSlider::setHandle(QQuickItem *handle)
545{
546 Q_D(QQuickSlider);
547 if (d->handle == handle)
548 return;
549
550 QQuickControlPrivate::warnIfCustomizationNotSupported(control: this, item: handle, QStringLiteral("handle"));
551
552 if (!d->handle.isExecuting())
553 d->cancelHandle();
554
555 const qreal oldImplicitHandleWidth = implicitHandleWidth();
556 const qreal oldImplicitHandleHeight = implicitHandleHeight();
557
558 d->removeImplicitSizeListener(item: d->handle);
559 QQuickControlPrivate::hideOldItem(item: d->handle);
560 d->handle = handle;
561
562 if (handle) {
563 if (!handle->parentItem())
564 handle->setParentItem(this);
565 d->addImplicitSizeListener(item: handle);
566 }
567
568 if (!qFuzzyCompare(p1: oldImplicitHandleWidth, p2: implicitHandleWidth()))
569 emit implicitHandleWidthChanged();
570 if (!qFuzzyCompare(p1: oldImplicitHandleHeight, p2: implicitHandleHeight()))
571 emit implicitHandleHeightChanged();
572 if (!d->handle.isExecuting())
573 emit handleChanged();
574}
575
576/*!
577 \since QtQuick.Controls 2.1 (Qt 5.8)
578 \qmlmethod real QtQuick.Controls::Slider::valueAt(real position)
579
580 Returns the value for the given \a position.
581
582 \sa value, position
583*/
584qreal QQuickSlider::valueAt(qreal position) const
585{
586 Q_D(const QQuickSlider);
587 const qreal value = (d->to - d->from) * position;
588 if (qFuzzyIsNull(d: d->stepSize))
589 return d->from + value;
590 return d->from + qRound(d: value / d->stepSize) * d->stepSize;
591}
592
593/*!
594 \since QtQuick.Controls 2.2 (Qt 5.9)
595 \qmlproperty bool QtQuick.Controls::Slider::live
596
597 This property holds whether the slider provides live updates for the \l value
598 property while the handle is dragged.
599
600 The default value is \c true.
601
602 \sa value, valueAt()
603*/
604bool QQuickSlider::live() const
605{
606 Q_D(const QQuickSlider);
607 return d->live;
608}
609
610void QQuickSlider::setLive(bool live)
611{
612 Q_D(QQuickSlider);
613 if (d->live == live)
614 return;
615
616 d->live = live;
617 emit liveChanged();
618}
619
620/*!
621 \qmlmethod void QtQuick.Controls::Slider::increase()
622
623 Increases the value by \l stepSize or \c 0.1 if stepSize is not defined.
624
625 \sa stepSize
626*/
627void QQuickSlider::increase()
628{
629 Q_D(QQuickSlider);
630 qreal step = qFuzzyIsNull(d: d->stepSize) ? 0.1 : d->stepSize;
631 setValue(d->value + step);
632}
633
634/*!
635 \qmlmethod void QtQuick.Controls::Slider::decrease()
636
637 Decreases the value by \l stepSize or \c 0.1 if stepSize is not defined.
638
639 \sa stepSize
640*/
641void QQuickSlider::decrease()
642{
643 Q_D(QQuickSlider);
644 qreal step = qFuzzyIsNull(d: d->stepSize) ? 0.1 : d->stepSize;
645 setValue(d->value - step);
646}
647
648/*!
649 \since QtQuick.Controls 2.5 (Qt 5.12)
650 \qmlproperty qreal QtQuick.Controls::Slider::touchDragThreshold
651
652 This property holds the threshold (in logical pixels) at which a touch drag event will be initiated.
653 The mouse drag threshold won't be affected.
654 The default value is \c Qt.styleHints.startDragDistance.
655
656 \sa QStyleHints
657*/
658qreal QQuickSlider::touchDragThreshold() const
659{
660 Q_D(const QQuickSlider);
661 return d->touchDragThreshold;
662}
663
664void QQuickSlider::setTouchDragThreshold(qreal touchDragThreshold)
665{
666 Q_D(QQuickSlider);
667 if (d->touchDragThreshold == touchDragThreshold)
668 return;
669
670 d->touchDragThreshold = touchDragThreshold;
671 emit touchDragThresholdChanged();
672}
673
674void QQuickSlider::resetTouchDragThreshold()
675{
676 setTouchDragThreshold(-1);
677}
678
679/*!
680 \since QtQuick.Controls 2.5 (Qt 5.12)
681 \qmlproperty real QtQuick.Controls::Slider::implicitHandleWidth
682 \readonly
683
684 This property holds the implicit handle width.
685
686 The value is equal to \c {handle ? handle.implicitWidth : 0}.
687
688 This is typically used, together with \l {Control::}{implicitContentWidth} and
689 \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}.
690
691 \sa implicitHandleHeight
692*/
693qreal QQuickSlider::implicitHandleWidth() const
694{
695 Q_D(const QQuickSlider);
696 if (!d->handle)
697 return 0;
698 return d->handle->implicitWidth();
699}
700
701/*!
702 \since QtQuick.Controls 2.5 (Qt 5.12)
703 \qmlproperty real QtQuick.Controls::Slider::implicitHandleHeight
704 \readonly
705
706 This property holds the implicit handle height.
707
708 The value is equal to \c {handle ? handle.implicitHeight : 0}.
709
710 This is typically used, together with \l {Control::}{implicitContentHeight} and
711 \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}.
712
713 \sa implicitHandleWidth
714*/
715qreal QQuickSlider::implicitHandleHeight() const
716{
717 Q_D(const QQuickSlider);
718 if (!d->handle)
719 return 0;
720 return d->handle->implicitHeight();
721}
722
723void QQuickSlider::keyPressEvent(QKeyEvent *event)
724{
725 Q_D(QQuickSlider);
726 QQuickControl::keyPressEvent(event);
727
728 const qreal oldValue = d->value;
729 if (d->orientation == Qt::Horizontal) {
730 if (event->key() == Qt::Key_Left) {
731 setPressed(true);
732 if (isMirrored())
733 increase();
734 else
735 decrease();
736 event->accept();
737 } else if (event->key() == Qt::Key_Right) {
738 setPressed(true);
739 if (isMirrored())
740 decrease();
741 else
742 increase();
743 event->accept();
744 }
745 } else {
746 if (event->key() == Qt::Key_Up) {
747 setPressed(true);
748 increase();
749 event->accept();
750 } else if (event->key() == Qt::Key_Down) {
751 setPressed(true);
752 decrease();
753 event->accept();
754 }
755 }
756 if (!qFuzzyCompare(p1: d->value, p2: oldValue))
757 emit moved();
758}
759
760void QQuickSlider::keyReleaseEvent(QKeyEvent *event)
761{
762 QQuickControl::keyReleaseEvent(event);
763 setPressed(false);
764}
765
766void QQuickSlider::mousePressEvent(QMouseEvent *event)
767{
768 Q_D(QQuickSlider);
769 QQuickControl::mousePressEvent(event);
770 d->handleMove(point: event->position(), timestamp: event->timestamp());
771 setKeepMouseGrab(true);
772}
773
774#if QT_CONFIG(quicktemplates2_multitouch)
775void QQuickSlider::touchEvent(QTouchEvent *event)
776{
777 Q_D(QQuickSlider);
778 switch (event->type()) {
779 case QEvent::TouchUpdate:
780 for (const QTouchEvent::TouchPoint &point : event->points()) {
781 if (!d->acceptTouch(point))
782 continue;
783
784 switch (point.state()) {
785 case QEventPoint::Pressed:
786 d->handlePress(point: point.position(), timestamp: event->timestamp());
787 break;
788 case QEventPoint::Updated:
789 if (!keepTouchGrab()) {
790 if (d->orientation == Qt::Horizontal)
791 setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(d: point.position().x() - d->pressPoint.x(), axis: Qt::XAxis, tp: &point, startDragThreshold: qRound(d: d->touchDragThreshold)));
792 else
793 setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(d: point.position().y() - d->pressPoint.y(), axis: Qt::YAxis, tp: &point, startDragThreshold: qRound(d: d->touchDragThreshold)));
794 }
795 if (keepTouchGrab())
796 d->handleMove(point: point.position(), timestamp: event->timestamp());
797 break;
798 case QEventPoint::Released:
799 d->handleRelease(point: point.position(), timestamp: event->timestamp());
800 break;
801 default:
802 break;
803 }
804 }
805 break;
806
807 default:
808 QQuickControl::touchEvent(event);
809 break;
810 }
811}
812#endif
813
814#if QT_CONFIG(wheelevent)
815void QQuickSlider::wheelEvent(QWheelEvent *event)
816{
817 Q_D(QQuickSlider);
818 QQuickControl::wheelEvent(event);
819 if (d->wheelEnabled) {
820 const qreal oldValue = d->value;
821 const QPointF angle = event->angleDelta();
822 const qreal delta = (qFuzzyIsNull(d: angle.y()) ? angle.x() : (event->inverted() ? -angle.y() : angle.y())) / int(QWheelEvent::DefaultDeltasPerStep);
823 const qreal step = qFuzzyIsNull(d: d->stepSize) ? 0.1 : d->stepSize;
824 setValue(oldValue + step * delta);
825 const bool wasMoved = !qFuzzyCompare(p1: d->value, p2: oldValue);
826 if (wasMoved)
827 emit moved();
828 }
829}
830#endif
831
832void QQuickSlider::mirrorChange()
833{
834 QQuickControl::mirrorChange();
835 emit visualPositionChanged();
836}
837
838void QQuickSlider::componentComplete()
839{
840 Q_D(QQuickSlider);
841 d->executeHandle(complete: true);
842 QQuickControl::componentComplete();
843 setValue(d->value);
844 d->updatePosition();
845}
846
847#if QT_CONFIG(accessibility)
848void QQuickSlider::accessibilityActiveChanged(bool active)
849{
850 QQuickControl::accessibilityActiveChanged(active);
851
852 Q_D(QQuickSlider);
853 if (active)
854 setAccessibleProperty(propertyName: "pressed", value: d->pressed);
855}
856
857QAccessible::Role QQuickSlider::accessibleRole() const
858{
859 return QAccessible::Slider;
860}
861#endif
862
863QT_END_NAMESPACE
864
865#include "moc_qquickslider_p.cpp"
866

source code of qtdeclarative/src/quicktemplates/qquickslider.cpp