Bartel

customqquickdial.cpp

Mar 22nd, 2019
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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 "customqquickdial.h"
  38. #include "QtQuickTemplates2/private/qquickdeferredexecute_p_p.h"
  39.  
  40. #include <QtCore/qmath.h>
  41. #include <QtQuick/private/qquickflickable_p.h>
  42. #include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
  43.  
  44. QT_BEGIN_NAMESPACE
  45.  
  46. /*!
  47.     \qmltype Dial
  48.     \inherits Control
  49.     \instantiates CustomQQuickDial
  50.     \inqmlmodule QtQuick.Controls
  51.     \since 5.7
  52.     \ingroup qtquickcontrols2-input
  53.     \brief Circular dial that is rotated to set a value.
  54.  
  55.     The Dial is similar to a traditional dial knob that is found on devices
  56.     such as stereos or industrial equipment. It allows the user to specify a
  57.     value within a range.
  58.  
  59.     \image qtquickcontrols2-dial-no-wrap.gif
  60.  
  61.     The value of the dial is set with the \l value property. The range is
  62.     set with the \l from and \l to properties. To enable or disable wrapping,
  63.     use the \l wrap property.
  64.  
  65.     The dial can be manipulated with a keyboard. It supports the following
  66.     actions:
  67.  
  68.     \table
  69.     \header \li \b {Action} \li \b {Key}
  70.     \row \li Decrease \l value by \l stepSize \li \c Qt.Key_Left
  71.     \row \li Decrease \l value by \l stepSize \li \c Qt.Key_Down
  72.     \row \li Set \l value to \l from \li \c Qt.Key_Home
  73.     \row \li Increase \l value by \l stepSize \li \c Qt.Key_Right
  74.     \row \li Increase \l value by \l stepSize \li \c Qt.Key_Up
  75.     \row \li Set \l value to \l to \li \c Qt.Key_End
  76.     \endtable
  77.  
  78.     \include qquickdial.qdocinc inputMode
  79.  
  80.     \sa {Customizing Dial}, {Input Controls}
  81. */
  82.  
  83. /*!
  84.     \since QtQuick.Controls 2.2 (Qt 5.9)
  85.     \qmlsignal QtQuick.Controls::Dial::moved()
  86.  
  87.     This signal is emitted when the dial has been interactively moved
  88.     by the user by either touch, mouse, or keys.
  89. */
  90.  
  91. static const qreal startAngleRadians = (M_PI / 2.0); //240
  92. static const qreal startAngle = 0; //-140
  93. static const qreal endAngleRadians = (M_PI * 2.0)/* * (5.0 / 4.0)*/; //300
  94. static const qreal endAngle = 360; //140
  95.  
  96. class CustomQQuickDialPrivate : public QQuickControlPrivate
  97. {
  98.     Q_DECLARE_PUBLIC(CustomQQuickDial)
  99.  
  100. public:
  101.     qreal valueAt(qreal position) const;
  102.     qreal snapPosition(qreal position) const;
  103.     qreal positionAt(const QPointF &point) const;
  104.     qreal circularPositionAt(const QPointF &point) const;
  105.     qreal linearPositionAt(const QPointF &point) const;
  106.     void setPosition(qreal position);
  107.     void updatePosition();
  108.     bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const;
  109.     bool isHorizontalOrVertical() const;
  110.  
  111.     void handlePress(const QPointF &point) override;
  112.     void handleMove(const QPointF &point) override;
  113.     void handleRelease(const QPointF &point) override;
  114.     void handleUngrab() override;
  115.  
  116.     void cancelHandle();
  117.     void executeHandle(bool complete = false);
  118.  
  119.     qreal from = 0;
  120.     qreal to = 1;
  121.     qreal value = 0;
  122.     qreal position = 0;
  123.     qreal angle = startAngle;
  124.     qreal stepSize = 0;
  125.     bool pressed = false;
  126.     QPointF pressPoint;
  127.     qreal positionBeforePress = 0;
  128.     CustomQQuickDial::SnapMode snapMode = CustomQQuickDial::NoSnap;
  129.     CustomQQuickDial::InputMode inputMode = CustomQQuickDial::Circular;
  130.     bool wrap = false;
  131.     bool live = true;
  132.     QQuickDeferredPointer<QQuickItem> handle;
  133. };
  134.  
  135. qreal CustomQQuickDialPrivate::valueAt(qreal position) const
  136. {
  137.     return from + (to - from) * position;
  138. }
  139.  
  140. qreal CustomQQuickDialPrivate::snapPosition(qreal position) const
  141. {
  142.     const qreal range = to - from;
  143.     if (qFuzzyIsNull(range))
  144.         return position;
  145.  
  146.     const qreal effectiveStep = stepSize / range;
  147.     if (qFuzzyIsNull(effectiveStep))
  148.         return position;
  149.  
  150.     if((position + effectiveStep) > to)
  151.         return from;
  152.  
  153.     return qRound(position / effectiveStep) * effectiveStep;
  154. }
  155.  
  156. qreal CustomQQuickDialPrivate::positionAt(const QPointF &point) const
  157. {
  158.     return inputMode == CustomQQuickDial::Circular ? circularPositionAt(point) : linearPositionAt(point);
  159. }
  160.  
  161. qreal CustomQQuickDialPrivate::circularPositionAt(const QPointF &point) const
  162. {
  163.     qreal yy = height / 2.0 - point.y();
  164.     qreal xx = point.x() - width / 2.0;
  165.     qreal angle = (xx || yy) ? std::atan2(yy, xx) : 0;
  166.  
  167.     angle = -angle;
  168.     angle += M_PI/2;
  169.  
  170.     if (angle < 0)
  171.         angle = angle + M_PI * 2;
  172.  
  173.     angle /= 2.0 * M_PI;
  174.  
  175.     return angle;
  176. }
  177.  
  178. qreal CustomQQuickDialPrivate::linearPositionAt(const QPointF &point) const
  179. {
  180.     // This value determines the range (either horizontal or vertical)
  181.     // within which the dial can be dragged.
  182.     // The larger this value is, the further the drag distance
  183.     // must be to go from a position of e.g. 0.0 to 1.0.
  184.     qreal dragArea = 0;
  185.  
  186.     // The linear input mode uses a "relative" input system,
  187.     // where the distance from the press point is used to calculate
  188.     // the change in position. Moving the mouse above the press
  189.     // point increases the position (when inputMode is Vertical),
  190.     // and vice versa. This prevents the dial from jumping when clicked.
  191.     qreal dragDistance = 0;
  192.  
  193.     if (inputMode == CustomQQuickDial::Horizontal) {
  194.         dragArea = width * 2;
  195.         dragDistance = pressPoint.x() - point.x();
  196.     } else {
  197.         dragArea = height * 2;
  198.         dragDistance = point.y() - pressPoint.y();
  199.     }
  200.     const qreal normalisedDifference = dragDistance / dragArea;
  201.     return qBound(0.0, positionBeforePress - normalisedDifference, 1.0);
  202. }
  203.  
  204. void CustomQQuickDialPrivate::setPosition(qreal pos)
  205. {
  206.     Q_Q(CustomQQuickDial);
  207.     pos = qBound<qreal>(0.0, pos, 1.0);
  208.     if (qFuzzyCompare(position, pos))
  209.         return;
  210.  
  211.     position = pos;
  212.  
  213.     angle = startAngle + position * qAbs(endAngle - startAngle);
  214.  
  215.     emit q->positionChanged();
  216.     emit q->angleChanged();
  217. }
  218.  
  219. void CustomQQuickDialPrivate::updatePosition()
  220. {
  221.     qreal pos = 0;
  222.     if (!qFuzzyCompare(from, to))
  223.         pos = (value - from) / (to - from);
  224.     setPosition(pos);
  225. }
  226.  
  227. bool CustomQQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPosition) const
  228. {
  229.     return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2;
  230. }
  231.  
  232. bool CustomQQuickDialPrivate::isHorizontalOrVertical() const
  233. {
  234.     return inputMode == CustomQQuickDial::Horizontal || inputMode == CustomQQuickDial::Vertical;
  235. }
  236.  
  237. void CustomQQuickDialPrivate::handlePress(const QPointF &point)
  238. {
  239.     Q_Q(CustomQQuickDial);
  240.     QQuickControlPrivate::handlePress(point);
  241.     pressPoint = point;
  242.     positionBeforePress = position;
  243.     q->setPressed(true);
  244. }
  245.  
  246. void CustomQQuickDialPrivate::handleMove(const QPointF &point)
  247. {
  248.     Q_Q(CustomQQuickDial);
  249.     QQuickControlPrivate::handleMove(point);
  250.     const qreal oldPos = position;
  251.     qreal pos = positionAt(point);
  252.     if (snapMode == CustomQQuickDial::SnapAlways)
  253.         pos = snapPosition(pos);
  254.  
  255.     if (wrap || (!wrap && (isHorizontalOrVertical() || !isLargeChange(point, pos)))) {
  256.         if (live)
  257.             q->setValue(valueAt(pos));
  258.         else
  259.             setPosition(pos);
  260.         if (!qFuzzyCompare(pos, oldPos))
  261.             emit q->moved();
  262.     }
  263. }
  264.  
  265. void CustomQQuickDialPrivate::handleRelease(const QPointF &point)
  266. {
  267.     Q_Q(CustomQQuickDial);
  268.     QQuickControlPrivate::handleRelease(point);
  269.     if (q->keepMouseGrab() || q->keepTouchGrab()) {
  270.         const qreal oldPos = position;
  271.         qreal pos = positionAt(point);
  272.         if (snapMode != CustomQQuickDial::NoSnap)
  273.             pos = snapPosition(pos);
  274.  
  275.         if (wrap || (!wrap && (isHorizontalOrVertical() || !isLargeChange(point, pos))))
  276.             q->setValue(valueAt(pos));
  277.         if (!qFuzzyCompare(pos, oldPos))
  278.             emit q->moved();
  279.  
  280.         q->setKeepMouseGrab(false);
  281.         q->setKeepTouchGrab(false);
  282.     }
  283.  
  284.     q->setPressed(false);
  285.     pressPoint = QPointF();
  286.     positionBeforePress = 0;
  287. }
  288.  
  289. void CustomQQuickDialPrivate::handleUngrab()
  290. {
  291.     Q_Q(CustomQQuickDial);
  292.     QQuickControlPrivate::handleUngrab();
  293.     pressPoint = QPointF();
  294.     positionBeforePress = 0;
  295.     q->setPressed(false);
  296. }
  297.  
  298. static inline QString handleName() { return QStringLiteral("handle"); }
  299.  
  300. void CustomQQuickDialPrivate::cancelHandle()
  301. {
  302.     Q_Q(CustomQQuickDial);
  303.     quickCancelDeferred(q, handleName());
  304. }
  305.  
  306. void CustomQQuickDialPrivate::executeHandle(bool complete)
  307. {
  308.     Q_Q(CustomQQuickDial);
  309.     if (handle.wasExecuted())
  310.         return;
  311.  
  312.     if (!handle || complete)
  313.         quickBeginDeferred(q, handleName(), handle);
  314.     if (complete)
  315.         quickCompleteDeferred(q, handleName(), handle);
  316. }
  317.  
  318. CustomQQuickDial::CustomQQuickDial(QQuickItem *parent)
  319.     : QQuickControl(*(new CustomQQuickDialPrivate), parent)
  320. {
  321.     setActiveFocusOnTab(true);
  322.     setAcceptedMouseButtons(Qt::LeftButton);
  323. #if QT_CONFIG(cursor)
  324.     setCursor(Qt::ArrowCursor);
  325. #endif
  326. }
  327.  
  328. /*!
  329.     \qmlproperty real QtQuick.Controls::Dial::from
  330.  
  331.     This property holds the starting value for the range. The default value is \c 0.0.
  332.  
  333.     \sa to, value
  334. */
  335. qreal CustomQQuickDial::from() const
  336. {
  337.     Q_D(const CustomQQuickDial);
  338.     return d->from;
  339. }
  340.  
  341. void CustomQQuickDial::setFrom(qreal from)
  342. {
  343.     Q_D(CustomQQuickDial);
  344.     if (qFuzzyCompare(d->from, from))
  345.         return;
  346.  
  347.     d->from = from;
  348.     emit fromChanged();
  349.     if (isComponentComplete()) {
  350.         setValue(d->value);
  351.         d->updatePosition();
  352.     }
  353. }
  354.  
  355. /*!
  356.     \qmlproperty real QtQuick.Controls::Dial::to
  357.  
  358.     This property holds the end value for the range. The default value is
  359.     \c 1.0.
  360.  
  361.     \sa from, value
  362. */
  363. qreal CustomQQuickDial::to() const
  364. {
  365.     Q_D(const CustomQQuickDial);
  366.     return d->to;
  367. }
  368.  
  369. void CustomQQuickDial::setTo(qreal to)
  370. {
  371.     Q_D(CustomQQuickDial);
  372.     if (qFuzzyCompare(d->to, to))
  373.         return;
  374.  
  375.     d->to = to;
  376.     emit toChanged();
  377.     if (isComponentComplete()) {
  378.         setValue(d->value);
  379.         d->updatePosition();
  380.     }
  381. }
  382.  
  383. /*!
  384.     \qmlproperty real QtQuick.Controls::Dial::value
  385.  
  386.     This property holds the value in the range \c from - \c to. The default
  387.     value is \c 0.0.
  388.  
  389.     \sa position, live
  390. */
  391. qreal CustomQQuickDial::value() const
  392. {
  393.     Q_D(const CustomQQuickDial);
  394.     return d->value;
  395. }
  396.  
  397. void CustomQQuickDial::setValue(qreal value)
  398. {
  399.     Q_D(CustomQQuickDial);
  400.     if (isComponentComplete())
  401.         value = d->from > d->to ? qBound(d->to, value, d->from) : qBound(d->from, value, d->to);
  402.  
  403.     if (qFuzzyCompare(d->value, value))
  404.         return;
  405.  
  406.     d->value = value;
  407.     d->updatePosition();
  408.     emit valueChanged();
  409. }
  410.  
  411. /*!
  412.     \qmlproperty real QtQuick.Controls::Dial::position
  413.     \readonly
  414.  
  415.     This property holds the logical position of the handle.
  416.  
  417.     The position is expressed as a fraction of the control's angle range (the
  418.     range within which the handle can be moved) in the range \c {0.0 - 1.0}.
  419.  
  420.     \sa value, angle
  421. */
  422. qreal CustomQQuickDial::position() const
  423. {
  424.     Q_D(const CustomQQuickDial);
  425.     return d->position;
  426. }
  427.  
  428. /*!
  429.     \qmlproperty real QtQuick.Controls::Dial::angle
  430.     \readonly
  431.  
  432.     This property holds the angle of the handle.
  433.  
  434.     The range is from \c -140 degrees to \c 140 degrees.
  435.  
  436.     \sa position
  437. */
  438. qreal CustomQQuickDial::angle() const
  439. {
  440.     Q_D(const CustomQQuickDial);
  441.     return d->angle;
  442. }
  443.  
  444. /*!
  445.     \qmlproperty real QtQuick.Controls::Dial::stepSize
  446.  
  447.     This property holds the step size.
  448.  
  449.     The step size determines the amount by which the dial's value
  450.     is increased and decreased when interacted with via the keyboard.
  451.     For example, a step size of \c 0.2, will result in the dial's
  452.     value increasing and decreasing in increments of \c 0.2.
  453.  
  454.     The step size is only respected for touch and mouse interaction
  455.     when \l snapMode is set to a value other than \c Dial.NoSnap.
  456.  
  457.     The default value is \c 0.0, which results in an effective step
  458.     size of \c 0.1 for keyboard interaction.
  459.  
  460.     \sa snapMode, increase(), decrease()
  461. */
  462. qreal CustomQQuickDial::stepSize() const
  463. {
  464.     Q_D(const CustomQQuickDial);
  465.     return d->stepSize;
  466. }
  467.  
  468. void CustomQQuickDial::setStepSize(qreal step)
  469. {
  470.     Q_D(CustomQQuickDial);
  471.     if (qFuzzyCompare(d->stepSize, step))
  472.         return;
  473.  
  474.     d->stepSize = step;
  475.     emit stepSizeChanged();
  476. }
  477.  
  478. /*!
  479.     \qmlproperty enumeration QtQuick.Controls::Dial::snapMode
  480.  
  481.     This property holds the snap mode.
  482.  
  483.     The snap mode works with the \l stepSize to allow the handle to snap to
  484.     certain points along the dial.
  485.  
  486.     Possible values:
  487.     \value Dial.NoSnap The dial does not snap (default).
  488.     \value Dial.SnapAlways The dial snaps while the handle is dragged.
  489.     \value Dial.SnapOnRelease The dial does not snap while being dragged, but only after the handle is released.
  490.  
  491.     \sa stepSize
  492. */
  493. CustomQQuickDial::SnapMode CustomQQuickDial::snapMode() const
  494. {
  495.     Q_D(const CustomQQuickDial);
  496.     return d->snapMode;
  497. }
  498.  
  499. void CustomQQuickDial::setSnapMode(SnapMode mode)
  500. {
  501.     Q_D(CustomQQuickDial);
  502.     if (d->snapMode == mode)
  503.         return;
  504.  
  505.     d->snapMode = mode;
  506.     emit snapModeChanged();
  507. }
  508.  
  509. /*!
  510.     \since QtQuick.Controls 2.5 (Qt 5.12)
  511.     \qmlproperty enumeration QtQuick.Controls::Dial::inputMode
  512.  
  513.     This property holds the input mode.
  514.  
  515.     \include qquickdial.qdocinc inputMode
  516.  
  517.     The default value is \c Dial.Circular.
  518. */
  519. CustomQQuickDial::InputMode CustomQQuickDial::inputMode() const
  520. {
  521.     Q_D(const CustomQQuickDial);
  522.     return d->inputMode;
  523. }
  524.  
  525. void CustomQQuickDial::setInputMode(CustomQQuickDial::InputMode mode)
  526. {
  527.     Q_D(CustomQQuickDial);
  528.     if (d->inputMode == mode)
  529.         return;
  530.  
  531.     d->inputMode = mode;
  532.     emit inputModeChanged();
  533. }
  534.  
  535. /*!
  536.     \qmlproperty bool QtQuick.Controls::Dial::wrap
  537.  
  538.     This property holds whether the dial wraps when dragged.
  539.  
  540.     For example, when this property is set to \c true, dragging the dial past
  541.     the \l to position will result in the handle being positioned at the
  542.     \l from position, and vice versa:
  543.  
  544.     \image qtquickcontrols2-dial-wrap.gif
  545.  
  546.     When this property is \c false, it's not possible to drag the dial across
  547.     the from and to values.
  548.  
  549.     \image qtquickcontrols2-dial-no-wrap.gif
  550.  
  551.     The default value is \c false.
  552. */
  553. bool CustomQQuickDial::wrap() const
  554. {
  555.     Q_D(const CustomQQuickDial);
  556.     return d->wrap;
  557. }
  558.  
  559. void CustomQQuickDial::setWrap(bool wrap)
  560. {
  561.     Q_D(CustomQQuickDial);
  562.     if (d->wrap == wrap)
  563.         return;
  564.  
  565.     d->wrap = wrap;
  566.     emit wrapChanged();
  567. }
  568.  
  569. /*!
  570.     \qmlproperty bool QtQuick.Controls::Dial::pressed
  571.  
  572.     This property holds whether the dial is pressed.
  573.  
  574.     The dial will be pressed when either the mouse is pressed over it, or a key
  575.     such as \c Qt.Key_Left is held down. If you'd prefer not to have the dial
  576.     be pressed upon key presses (due to styling reasons, for example), you can
  577.     use the \l {Keys}{Keys attached property}:
  578.  
  579.     \code
  580.     Dial {
  581.         Keys.onLeftPressed: {}
  582.     }
  583.     \endcode
  584.  
  585.     This will result in pressed only being \c true upon mouse presses.
  586. */
  587. bool CustomQQuickDial::isPressed() const
  588. {
  589.     Q_D(const CustomQQuickDial);
  590.     return d->pressed;
  591. }
  592.  
  593. void CustomQQuickDial::setPressed(bool pressed)
  594. {
  595.     Q_D(CustomQQuickDial);
  596.     if (d->pressed == pressed)
  597.         return;
  598.  
  599.     d->pressed = pressed;
  600.     setAccessibleProperty("pressed", pressed);
  601.     emit pressedChanged();
  602. }
  603.  
  604. /*!
  605.     \qmlproperty Item QtQuick.Controls::Dial::handle
  606.  
  607.     This property holds the handle of the dial.
  608.  
  609.     The handle acts as a visual indicator of the position of the dial.
  610.  
  611.     \sa {Customizing Dial}
  612. */
  613. QQuickItem *CustomQQuickDial::handle() const
  614. {
  615.     CustomQQuickDialPrivate *d = const_cast<CustomQQuickDialPrivate *>(d_func());
  616.     if (!d->handle)
  617.         d->executeHandle();
  618.     return d->handle;
  619. }
  620.  
  621. void CustomQQuickDial::setHandle(QQuickItem *handle)
  622. {
  623.     Q_D(CustomQQuickDial);
  624.     if (handle == d->handle)
  625.         return;
  626.  
  627.     if (!d->handle.isExecuting())
  628.         d->cancelHandle();
  629.  
  630.     delete d->handle;
  631.     d->handle = handle;
  632.     if (d->handle && !d->handle->parentItem())
  633.         d->handle->setParentItem(this);
  634.     if (!d->handle.isExecuting())
  635.         emit handleChanged();
  636. }
  637.  
  638. /*!
  639.     \since QtQuick.Controls 2.2 (Qt 5.9)
  640.     \qmlproperty bool QtQuick.Controls::Dial::live
  641.  
  642.     This property holds whether the dial provides live updates for the \l value
  643.     property while the handle is dragged.
  644.  
  645.     The default value is \c true.
  646.  
  647.     \sa value
  648. */
  649. bool CustomQQuickDial::live() const
  650. {
  651.     Q_D(const CustomQQuickDial);
  652.     return d->live;
  653. }
  654.  
  655. void CustomQQuickDial::setLive(bool live)
  656. {
  657.     Q_D(CustomQQuickDial);
  658.     if (d->live == live)
  659.         return;
  660.  
  661.     d->live = live;
  662.     emit liveChanged();
  663. }
  664.  
  665. /*!
  666.     \qmlmethod void QtQuick.Controls::Dial::increase()
  667.  
  668.     Increases the value by \l stepSize, or \c 0.1 if stepSize is not defined.
  669.  
  670.     \sa stepSize
  671. */
  672. void CustomQQuickDial::increase()
  673. {
  674.     Q_D(CustomQQuickDial);
  675.     qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
  676.     setValue(d->value + step);
  677. }
  678.  
  679. /*!
  680.     \qmlmethod void QtQuick.Controls::Dial::decrease()
  681.  
  682.     Decreases the value by \l stepSize, or \c 0.1 if stepSize is not defined.
  683.  
  684.     \sa stepSize
  685. */
  686. void CustomQQuickDial::decrease()
  687. {
  688.     Q_D(CustomQQuickDial);
  689.     qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
  690.     setValue(d->value - step);
  691. }
  692.  
  693. void CustomQQuickDial::keyPressEvent(QKeyEvent *event)
  694. {
  695.     Q_D(CustomQQuickDial);
  696.     const qreal oldValue = d->value;
  697.     switch (event->key()) {
  698.     case Qt::Key_Left:
  699.     case Qt::Key_Down:
  700.         setPressed(true);
  701.         if (isMirrored())
  702.             increase();
  703.         else
  704.             decrease();
  705.         break;
  706.  
  707.     case Qt::Key_Right:
  708.     case Qt::Key_Up:
  709.         setPressed(true);
  710.         if (isMirrored())
  711.             decrease();
  712.         else
  713.             increase();
  714.         break;
  715.  
  716.     case Qt::Key_Home:
  717.         setPressed(true);
  718.         setValue(isMirrored() ? d->to : d->from);
  719.         break;
  720.  
  721.     case Qt::Key_End:
  722.         setPressed(true);
  723.         setValue(isMirrored() ? d->from : d->to);
  724.         break;
  725.  
  726.     default:
  727.         event->ignore();
  728.         QQuickControl::keyPressEvent(event);
  729.         break;
  730.     }
  731.     if (!qFuzzyCompare(d->value, oldValue))
  732.         emit moved();
  733. }
  734.  
  735. void CustomQQuickDial::keyReleaseEvent(QKeyEvent *event)
  736. {
  737.     QQuickControl::keyReleaseEvent(event);
  738.     setPressed(false);
  739. }
  740.  
  741. void CustomQQuickDial::mousePressEvent(QMouseEvent *event)
  742. {
  743.     Q_D(CustomQQuickDial);
  744.     QQuickControl::mousePressEvent(event);
  745.     d->handleMove(event->localPos());
  746.     setKeepMouseGrab(true);
  747. }
  748.  
  749. #if QT_CONFIG(quicktemplates2_multitouch)
  750. void CustomQQuickDial::touchEvent(QTouchEvent *event)
  751. {
  752.     Q_D(CustomQQuickDial);
  753.     switch (event->type()) {
  754.     case QEvent::TouchUpdate:
  755.         for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
  756.             if (!d->acceptTouch(point))
  757.                 continue;
  758.  
  759.             switch (point.state()) {
  760.             case Qt::TouchPointMoved:
  761.                 if (!keepTouchGrab()) {
  762.                     bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point);
  763.                     setKeepTouchGrab(overXDragThreshold);
  764.  
  765.                     if (!overXDragThreshold) {
  766.                         bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point);
  767.                         setKeepTouchGrab(overYDragThreshold);
  768.                     }
  769.                 }
  770.                 if (keepTouchGrab())
  771.                     d->handleMove(point.pos());
  772.                 break;
  773.  
  774.             default:
  775.                 QQuickControl::touchEvent(event);
  776.                 break;
  777.             }
  778.         }
  779.         break;
  780.  
  781.     default:
  782.         QQuickControl::touchEvent(event);
  783.         break;
  784.     }
  785. }
  786. #endif
  787.  
  788. #if QT_CONFIG(wheelevent)
  789. void CustomQQuickDial::wheelEvent(QWheelEvent *event)
  790. {
  791.     Q_D(CustomQQuickDial);
  792.     QQuickControl::wheelEvent(event);
  793.     if (d->wheelEnabled) {
  794.         const qreal oldValue = d->value;
  795.         const QPointF angle = event->angleDelta();
  796.         const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : (event->inverted() ? -angle.y() : angle.y())) / QWheelEvent::DefaultDeltasPerStep;
  797.         const qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
  798.         setValue(oldValue + step * delta);
  799.         event->setAccepted(!qFuzzyCompare(d->value, oldValue));
  800.     }
  801. }
  802. #endif
  803.  
  804. void CustomQQuickDial::mirrorChange()
  805. {
  806.     QQuickControl::mirrorChange();
  807.     emit angleChanged();
  808. }
  809.  
  810. void CustomQQuickDial::componentComplete()
  811. {
  812.     Q_D(CustomQQuickDial);
  813.     d->executeHandle(true);
  814.     QQuickControl::componentComplete();
  815.     setValue(d->value);
  816.     d->updatePosition();
  817. }
  818.  
  819. #if QT_CONFIG(accessibility)
  820. void CustomQQuickDial::accessibilityActiveChanged(bool active)
  821. {
  822.     QQuickControl::accessibilityActiveChanged(active);
  823.  
  824.     Q_D(CustomQQuickDial);
  825.     if (active)
  826.         setAccessibleProperty("pressed", d->pressed);
  827. }
  828.  
  829. QAccessible::Role CustomQQuickDial::accessibleRole() const
  830. {
  831.     return QAccessible::Dial;
  832. }
  833. #endif
  834.  
  835. QT_END_NAMESPACE
Add Comment
Please, Sign In to add comment