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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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