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

source code of qtquickcontrols2/src/quicktemplates2/qquickslider.cpp