diff options
Diffstat (limited to 'src/quickdialogs/quickdialogsquickimpl/qquickabstractcolorpicker.cpp')
-rw-r--r-- | src/quickdialogs/quickdialogsquickimpl/qquickabstractcolorpicker.cpp | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/src/quickdialogs/quickdialogsquickimpl/qquickabstractcolorpicker.cpp b/src/quickdialogs/quickdialogsquickimpl/qquickabstractcolorpicker.cpp new file mode 100644 index 0000000000..5b5b2abdae --- /dev/null +++ b/src/quickdialogs/quickdialogsquickimpl/qquickabstractcolorpicker.cpp @@ -0,0 +1,354 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickabstractcolorpicker_p_p.h" + +#include "qquickcolordialogutils_p.h" + +#include <QtQuickTemplates2/private/qquickcontrol_p_p.h> +#include <QtQuickTemplates2/private/qquickdeferredexecute_p_p.h> + +#include <qpa/qplatformintegration.h> +#include <private/qguiapplication_p.h> + +QQuickAbstractColorPickerPrivate::QQuickAbstractColorPickerPrivate() = default; + +bool QQuickAbstractColorPickerPrivate::handlePress(const QPointF &point, ulong timestamp) +{ + Q_Q(QQuickAbstractColorPicker); + QQuickControlPrivate::handlePress(point, timestamp); + m_pressPoint = point; + q->setPressed(true); + q->updateColor(point); + return true; +} + +bool QQuickAbstractColorPickerPrivate::handleMove(const QPointF &point, ulong timestamp) +{ + Q_Q(QQuickAbstractColorPicker); + QQuickControlPrivate::handleMove(point, timestamp); + if (point != m_pressPoint) + q->updateColor(point); + return true; +} + +bool QQuickAbstractColorPickerPrivate::handleRelease(const QPointF &point, ulong timestamp) +{ + Q_Q(QQuickAbstractColorPicker); + QQuickControlPrivate::handleRelease(point, timestamp); + m_pressPoint = QPointF(); + q->setKeepMouseGrab(false); + q->setKeepTouchGrab(false); + q->setPressed(false); + q->updateColor(point); + return true; +} + +void QQuickAbstractColorPickerPrivate::handleUngrab() +{ + Q_Q(QQuickAbstractColorPicker); + QQuickControlPrivate::handleUngrab(); + m_pressPoint = QPointF(); + q->setPressed(false); +} + +void QQuickAbstractColorPickerPrivate::cancelHandle() +{ + Q_Q(QQuickAbstractColorPicker); + quickCancelDeferred(q, handleName()); +} + +void QQuickAbstractColorPickerPrivate::executeHandle(bool complete) +{ + Q_Q(QQuickAbstractColorPicker); + if (m_handle.wasExecuted()) + return; + + if (!m_handle || complete) + quickBeginDeferred(q, handleName(), m_handle); + if (complete) + quickCompleteDeferred(q, handleName(), m_handle); +} + +void QQuickAbstractColorPickerPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickAbstractColorPicker); + QQuickControlPrivate::itemImplicitWidthChanged(item); + if (item == m_handle) + emit q->implicitHandleWidthChanged(); +} + +void QQuickAbstractColorPickerPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickAbstractColorPicker); + QQuickControlPrivate::itemImplicitHeightChanged(item); + if (item == m_handle) + emit q->implicitHandleHeightChanged(); +} + +QQuickAbstractColorPicker::QQuickAbstractColorPicker(QQuickAbstractColorPickerPrivate &dd, + QQuickItem *parent) + : QQuickControl(dd, parent) +{ + setActiveFocusOnTab(true); + setAcceptedMouseButtons(Qt::LeftButton); +} + +QColor QQuickAbstractColorPicker::color() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_hsl ? QColor::fromHslF(d->m_hsva.h, d->m_hsva.s, d->m_hsva.l, d->m_hsva.a) + : QColor::fromHsvF(d->m_hsva.h, d->m_hsva.s, d->m_hsva.v, d->m_hsva.a); +} + +void QQuickAbstractColorPicker::setColor(const QColor &c) +{ + Q_D(QQuickAbstractColorPicker); + // QColor represents a theoretical color, rather than simply an rgba value. + // Therefore, two QColor objects can be different, + // and yet translate to the same rgba value. + // Since the color picker can reuse the same rgba value for multiple pixels, + // we should not return early if the rgba() values are equal, + // but only if the QColor objects are exactly the same. + + if (color() == c) + return; + + // When called from QQuickColorDialogImpl, it might not have the same spec as the current color + // picker. + if (d->m_hsl && c.spec() == QColor::Spec::Hsv) { + const auto sl = getSaturationAndLightness(c.hsvSaturationF(), c.valueF()); + d->m_hsva.h = qBound(.0, c.hsvHueF(), 1.0); + d->m_hsva.s = qBound(.0, sl.first, 1.0); + d->m_hsva.l = qBound(.0, sl.second, 1.0); + } else if (!d->m_hsl && c.spec() == QColor::Spec::Hsl) { + const auto sv = getSaturationAndValue(c.hslSaturationF(), c.lightnessF()); + d->m_hsva.h = qBound(.0, c.hslHueF(), 1.0); + d->m_hsva.s = qBound(.0, sv.first, 1.0); + d->m_hsva.v = qBound(.0, sv.second, 1.0); + } else { + d->m_hsva.h = qBound(.0, d->m_hsl ? c.hslHueF() : c.hsvHueF(), 1.0); + d->m_hsva.s = qBound(.0, d->m_hsl ? c.hslSaturationF() : c.hsvSaturationF(), 1.0); + d->m_hsva.v = qBound(.0, d->m_hsl ? c.lightnessF() : c.valueF(), 1.0); + } + + d->m_hsva.a = qBound(.0, c.alphaF(), 1.0); + + emit colorChanged(color()); +} + +qreal QQuickAbstractColorPicker::alpha() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_hsva.a; +} + +void QQuickAbstractColorPicker::setAlpha(qreal alpha) +{ + Q_D(QQuickAbstractColorPicker); + + if (!qt_is_finite(alpha)) + return; + + alpha = qBound(.0, alpha, 1.0); + + if (qFuzzyCompare(d->m_hsva.a, alpha)) + return; + + d->m_hsva.a = alpha; + + emit colorChanged(color()); +} + +qreal QQuickAbstractColorPicker::hue() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_hsva.h; +} +void QQuickAbstractColorPicker::setHue(qreal hue) +{ + Q_D(QQuickAbstractColorPicker); + + if (!qt_is_finite(hue)) + return; + + d->m_hsva.h = hue; + + emit colorChanged(color()); +} + +qreal QQuickAbstractColorPicker::saturation() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_hsva.s; +} + +void QQuickAbstractColorPicker::setSaturation(qreal saturation) +{ + Q_D(QQuickAbstractColorPicker); + if (!qt_is_finite(saturation)) + return; + + d->m_hsva.s = saturation; + + emit colorChanged(color()); +} +qreal QQuickAbstractColorPicker::value() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_hsl ? getSaturationAndValue(d->m_hsva.s, d->m_hsva.l).second : d->m_hsva.v; +} +void QQuickAbstractColorPicker::setValue(qreal value) +{ + Q_D(QQuickAbstractColorPicker); + if (!qt_is_finite(value)) + return; + + const auto sv = d->m_hsl ? getSaturationAndValue(d->m_hsva.s, d->m_hsva.l) + : std::pair<qreal, qreal>(d->m_hsva.s, value); + d->m_hsva.s = sv.first; + d->m_hsva.v = sv.second; + + emit colorChanged(color()); +} + +qreal QQuickAbstractColorPicker::lightness() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_hsl ? d->m_hsva.l : getSaturationAndLightness(d->m_hsva.s, d->m_hsva.v).second; +} +void QQuickAbstractColorPicker::setLightness(qreal lightness) +{ + Q_D(QQuickAbstractColorPicker); + if (!qt_is_finite(lightness)) + return; + + const auto sl = !d->m_hsl ? getSaturationAndLightness(d->m_hsva.s, d->m_hsva.v) + : std::pair<qreal, qreal>(d->m_hsva.s, lightness); + d->m_hsva.s = sl.first; + d->m_hsva.l = sl.second; + + emit colorChanged(color()); +} + +/*! + \internal + + This property holds whether the slider is pressed. +*/ +bool QQuickAbstractColorPicker::isPressed() const +{ + Q_D(const QQuickAbstractColorPicker); + return d->m_pressed; +} + +void QQuickAbstractColorPicker::setPressed(bool pressed) +{ + Q_D(QQuickAbstractColorPicker); + if (pressed == d->m_pressed) + return; + + d->m_pressed = pressed; + emit pressedChanged(); +} + +/*! + \internal + + This property holds the handle item. +*/ +QQuickItem *QQuickAbstractColorPicker::handle() const +{ + QQuickAbstractColorPickerPrivate *d = const_cast<QQuickAbstractColorPickerPrivate *>(d_func()); + if (!d->m_handle) + d->executeHandle(); + return d->m_handle; +} + +void QQuickAbstractColorPicker::setHandle(QQuickItem *handle) +{ + Q_D(QQuickAbstractColorPicker); + if (handle == d->m_handle) + return; + + if (!d->m_handle.isExecuting()) + d->cancelHandle(); + + const qreal oldImplicitHandleWidth = implicitHandleWidth(); + const qreal oldImplicitHandleHeight = implicitHandleHeight(); + + d->removeImplicitSizeListener(d->m_handle); + QQuickControlPrivate::hideOldItem(d->m_handle); + d->m_handle = handle; + + if (handle) { + if (!handle->parentItem()) + handle->setParentItem(this); + d->addImplicitSizeListener(handle); + } + + if (!qFuzzyCompare(oldImplicitHandleWidth, implicitHandleWidth())) + emit implicitHandleWidthChanged(); + if (!qFuzzyCompare(oldImplicitHandleHeight, implicitHandleHeight())) + emit implicitHandleHeightChanged(); + if (!d->m_handle.isExecuting()) + emit handleChanged(); +} + +/*! + \internal + \readonly + + This property holds the implicit handle width. + + The value is equal to \c {handle ? handle.implicitWidth : 0}. + + This is typically used, together with \l {Control::}{implicitContentWidth} and + \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}. + + \sa implicitHandleHeight +*/ +qreal QQuickAbstractColorPicker::implicitHandleWidth() const +{ + Q_D(const QQuickAbstractColorPicker); + if (!d->m_handle) + return 0; + return d->m_handle->implicitWidth(); +} + +/*! + \internal + \readonly + + This property holds the implicit handle height. + + The value is equal to \c {handle ? handle.implicitHeight : 0}. + + This is typically used, together with \l {Control::}{implicitContentHeight} and + \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}. + + \sa implicitHandleWidth +*/ +qreal QQuickAbstractColorPicker::implicitHandleHeight() const +{ + Q_D(const QQuickAbstractColorPicker); + if (!d->m_handle) + return 0; + return d->m_handle->implicitHeight(); +} + +void QQuickAbstractColorPicker::componentComplete() +{ + Q_D(QQuickAbstractColorPicker); + d->executeHandle(true); + QQuickControl::componentComplete(); +} + +void QQuickAbstractColorPicker::updateColor(const QPointF &pos) +{ + QColor c = colorAt(pos); + c.setAlphaF(alpha()); + setColor(c); + + emit colorPicked(c); +} |