File indexing completed on 2024-05-12 04:52:51

0001 /*
0002     SPDX-FileCopyrightText: 2013 Meltytech LLC
0003     SPDX-FileCopyrightText: 2013 Dan Dennedy <dan@dennedy.org>
0004 
0005     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 
0007     Some ideas came from Qt-Plus: https://github.com/liuyanghejerry/Qt-Plus
0008     and Steinar Gunderson's Movit demo app.
0009 */
0010 
0011 #include "colorwheel.h"
0012 
0013 #include <KLocalizedString>
0014 #include <QDebug>
0015 #include <QDoubleSpinBox>
0016 #include <QFontDatabase>
0017 #include <QFrame>
0018 #include <QLabel>
0019 #include <QVBoxLayout>
0020 
0021 #include <qmath.h>
0022 #include <utility>
0023 
0024 WheelContainer::WheelContainer(QString id, QString name, NegQColor color, int unitSize, QWidget *parent)
0025     : QWidget(parent)
0026     , m_id(std::move(id))
0027     , m_isMouseDown(false)
0028     , m_margin(2)
0029     , m_color(std::move(color))
0030     , m_defaultColor(m_color)
0031     , m_sourceColor(m_color)
0032     , m_unitSize(unitSize)
0033     , m_name(std::move(name))
0034     , m_wheelClick(false)
0035     , m_sliderClick(false)
0036     , m_sliderFocus(false)
0037 {
0038     setMouseTracking(true);
0039     m_initialSize = QSize(m_unitSize * 11, m_unitSize * 11);
0040     m_sliderWidth = int(m_unitSize * 1.5);
0041     m_sliderBorder = m_unitSize * .2;
0042     resize(m_initialSize);
0043     setMinimumSize(m_initialSize * .4);
0044     setMaximumSize(m_initialSize * 1.5);
0045 }
0046 
0047 void WheelContainer::setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero)
0048 {
0049     m_sizeFactor = factor;
0050     m_defaultValue = defvalue;
0051     m_zeroShift = zero;
0052 }
0053 
0054 NegQColor WheelContainer::color() const
0055 {
0056     return m_color;
0057 }
0058 
0059 void WheelContainer::setColor(const QList<double> &values)
0060 {
0061     const NegQColor color = NegQColor::fromRgbF(values.at(0) / m_sizeFactor, values.at(1) / m_sizeFactor, values.at(2) / m_sizeFactor);
0062     m_color = color;
0063     drawSlider();
0064     update();
0065 }
0066 
0067 void WheelContainer::setRedColor(double value)
0068 {
0069     m_sourceColor = m_color;
0070     m_color.setRedF(value / m_sizeFactor);
0071     Q_EMIT colorChange(m_sourceColor, m_color, true);
0072     update();
0073 }
0074 
0075 void WheelContainer::setGreenColor(double value)
0076 {
0077     m_sourceColor = m_color;
0078     m_color.setGreenF(value / m_sizeFactor);
0079     Q_EMIT colorChange(m_sourceColor, m_color, true);
0080     update();
0081 }
0082 
0083 void WheelContainer::setBlueColor(double value)
0084 {
0085     m_sourceColor = m_color;
0086     m_color.setBlueF(value / m_sizeFactor);
0087     Q_EMIT colorChange(m_sourceColor, m_color, true);
0088     update();
0089 }
0090 
0091 int WheelContainer::wheelSize() const
0092 {
0093     return qMin(width() - m_sliderWidth, height());
0094 }
0095 
0096 int WheelContainer::sliderHeight() const
0097 {
0098     return wheelSize() - m_margin * 2 - m_sliderBorder * 2;
0099 }
0100 
0101 NegQColor WheelContainer::colorForPoint(const QPointF &point)
0102 {
0103     if (m_wheelClick) {
0104         qreal w = wheelSize();
0105         qreal xf;
0106         qreal yf;
0107         if (!m_wheelRegion.contains(point.toPoint())) {
0108             // if (xf < 0. || xf > 1. || yf < 0. || yf > 1.) {
0109             //  Cursor is outside of circle, calculate position on the circumference
0110             qreal dx = point.x() - (w / 2);
0111             qreal dy = (w / 2) - point.y();
0112             if (qFuzzyIsNull(dy)) {
0113                 yf = 0.5;
0114                 if (dx > 0.) {
0115                     xf = 1.;
0116                 } else {
0117                     xf = -1;
0118                 }
0119             } else {
0120                 // Calculate angle first
0121                 qreal angle = (M_PI / 2) - qAtan(qAbs(dx / dy));
0122                 // Calculate position on circle
0123                 xf = 0.5 + ((dx < 0. ? -1. : 1.) * qCos(angle) * 0.5);
0124                 yf = 0.5 + ((dy < 0. ? -1. : 1.) * qSin(angle) * 0.5);
0125             }
0126         } else {
0127             xf = qreal(point.x()) / w;
0128             yf = 1.0 - qreal(point.y()) / w;
0129         }
0130         qreal xp = 2.0 * xf - 1.0;
0131         qreal yp = 2.0 * yf - 1.0;
0132         qreal rad = qMin(hypot(xp, yp), 1.0);
0133         qreal theta = qAtan2(yp, xp);
0134         theta -= 105.0 / 360.0 * 2.0 * M_PI;
0135         if (theta < 0.0) {
0136             theta += 2.0 * M_PI;
0137         }
0138         qreal hue = (theta * 180.0 / M_PI) / 360.0;
0139         qreal value = m_color.valueF();
0140         if (m_zeroShift != 0. && value == 0 && hue != -1 && rad != 0) {
0141             // For lift, allow changing color if value slider is set to 0
0142             value = 0.00214;
0143         }
0144         return NegQColor::fromHsvF(hue, rad, value);
0145     }
0146     if (m_sliderClick) {
0147         qreal value = 1.0 - qreal(point.y() - m_margin) / (wheelSize() - m_margin * 2);
0148         value = qBound(0., value, 1.);
0149         if (qFuzzyIsNull(m_zeroShift)) {
0150             // Range is 0 to 1
0151             if (value < 0.001) {
0152                 value = 0.001;
0153             }
0154         } else if (m_color.hueF() != -1 && m_color.saturationF() != 0 && qAbs(value) < 0.001) {
0155             // Range is -1 to 1
0156             value = value < 0. ? -0.001 : 0.001;
0157         }
0158         return NegQColor::fromHsvF(m_color.hueF(), m_color.saturationF(), value);
0159     }
0160     return {};
0161 }
0162 
0163 QSize WheelContainer::sizeHint() const
0164 {
0165     return m_initialSize * .8;
0166 }
0167 
0168 QSize WheelContainer::minimumSizeHint() const
0169 {
0170     return m_initialSize * .4;
0171 }
0172 
0173 void WheelContainer::wheelEvent(QWheelEvent *event)
0174 {
0175     if (m_sliderRegion.contains(event->position().toPoint())) {
0176         double y = m_color.valueF();
0177         if (event->modifiers() & Qt::ShiftModifier) {
0178             y += event->angleDelta().y() > 0 ? 0.002 : -0.002;
0179         } else {
0180             y += event->angleDelta().y() > 0 ? 0.01 : -0.01;
0181         }
0182         m_sliderClick = true;
0183         m_sliderFocus = true;
0184         qreal value = qBound(-m_zeroShift, y, 1. - m_zeroShift);
0185         if (qFuzzyIsNull(m_zeroShift)) {
0186             // Range is 0 to 1
0187             if (qAbs(value) < 0.001) {
0188                 value = 0.001;
0189             }
0190         } else if (qAbs(value) < 0.001) {
0191             // Range is -1 to 1
0192             value = value < 0. ? -0.001 : 0.001;
0193         }
0194         m_sourceColor = m_color;
0195         m_color.setValueF(value);
0196         if (m_sourceColor != m_color) {
0197             changeColor(m_sourceColor, m_color, true);
0198         }
0199         event->accept();
0200     } else {
0201         QWidget::wheelEvent(event);
0202     }
0203 }
0204 
0205 void WheelContainer::mousePressEvent(QMouseEvent *event)
0206 {
0207     if (event->modifiers() & Qt::ShiftModifier) {
0208         QPoint clicked = event->pos();
0209         if (m_wheelRegion.contains(clicked)) {
0210             m_wheelClick = true;
0211             m_sliderFocus = false;
0212             QPointF current = pointForColor();
0213             QPointF diff = clicked - current;
0214             double factor = fabs(diff.x()) > fabs(diff.y()) ? fabs(diff.x()) : fabs(diff.y());
0215             diff /= factor;
0216             m_lastPoint = current + diff;
0217         } else if (m_sliderRegion.contains(clicked)) {
0218             m_sliderClick = true;
0219             m_sliderFocus = true;
0220             double y = yForColor();
0221             int offset = clicked.y() > y ? 1 : -1;
0222             m_lastPoint = QPointF(clicked.x(), y + offset);
0223             update();
0224         } else {
0225             return;
0226         }
0227     } else {
0228         m_lastPoint = event->pos();
0229     }
0230     if (m_wheelRegion.contains(m_lastPoint.toPoint())) {
0231         m_wheelClick = true;
0232         m_sliderFocus = false;
0233         if (event->button() == Qt::LeftButton) {
0234             m_sourceColor = m_color;
0235             changeColor(m_color, colorForPoint(m_lastPoint), false);
0236         } else {
0237             // reset to default on middle/right button
0238             m_sourceColor = m_color;
0239             qreal r = m_color.redF();
0240             qreal b = m_color.blueF();
0241             qreal g = m_color.greenF();
0242             qreal max = qMax(r, b);
0243             max = qMax(max, g);
0244             m_color = NegQColor::fromRgbF(max, max, max);
0245         }
0246     } else if (m_sliderRegion.contains(m_lastPoint.toPoint())) {
0247         m_sliderClick = true;
0248         m_sliderFocus = true;
0249         if (event->button() == Qt::LeftButton) {
0250             m_sourceColor = m_color;
0251             NegQColor color = colorForPoint(m_lastPoint);
0252             qreal value = color.valueF() - m_zeroShift;
0253             if (qFuzzyIsNull(m_zeroShift)) {
0254                 // Range is 0 to 1
0255                 if (qAbs(value) < 0.001) {
0256                     value = 0.001;
0257                 }
0258             } else if (qAbs(value) < 0.001) {
0259                 // Range is -1 to 1
0260                 value = value < 0. ? -0.001 : 0.001;
0261             }
0262             m_color.setValueF(value);
0263             changeColor(m_color, m_color, false);
0264         } else {
0265             m_sourceColor = m_color;
0266             m_color = NegQColor::fromHsvF(m_color.hueF(), m_color.saturationF(), m_defaultColor.valueF());
0267         }
0268         update();
0269     } else {
0270         if (m_sliderFocus) {
0271             m_sliderFocus = false;
0272             drawSlider();
0273             update();
0274         }
0275         clearFocus();
0276     }
0277     m_isMouseDown = true;
0278 }
0279 
0280 void WheelContainer::focusOutEvent(QFocusEvent *event)
0281 {
0282     if (m_sliderFocus) {
0283         m_sliderFocus = false;
0284         drawSlider();
0285         update();
0286     }
0287     QWidget::focusOutEvent(event);
0288 }
0289 
0290 void WheelContainer::mouseMoveEvent(QMouseEvent *event)
0291 {
0292     if (!m_isMouseDown) {
0293         if (m_wheelRegion.contains(event->pos()) || m_sliderRegion.contains(event->pos())) {
0294             setCursor(Qt::CrossCursor);
0295         } else {
0296             setCursor(Qt::ArrowCursor);
0297         }
0298         return;
0299     }
0300     setCursor(Qt::CrossCursor);
0301     if (event->modifiers() & Qt::ShiftModifier) {
0302         if (m_wheelClick) {
0303             QPointF diff = event->pos() - m_lastPoint;
0304             double factor = fabs(diff.x()) > fabs(diff.y()) ? fabs(diff.x()) : fabs(diff.y());
0305             diff /= factor;
0306             m_lastPoint += diff;
0307         } else if (m_sliderClick) {
0308             double y = yForColor();
0309             int offset = event->pos().y() > y ? 1 : -1;
0310             m_lastPoint = QPointF(event->pos().x(), y + offset);
0311         } else {
0312             return;
0313         }
0314     } else {
0315         m_lastPoint = event->pos();
0316     }
0317     if (m_wheelClick) {
0318         const NegQColor color = colorForPoint(m_lastPoint);
0319         changeColor(color, color, false);
0320     } else if (m_sliderClick) {
0321         const NegQColor color = colorForPoint(m_lastPoint);
0322         qreal value = color.valueF() - m_zeroShift;
0323         if (qFuzzyIsNull(m_zeroShift)) {
0324             // Range is 0 to 1
0325             if (qAbs(value) < 0.001) {
0326                 value = 0.001;
0327             }
0328         } else if (qAbs(value) < 0.001) {
0329             // Range is -1 to 1
0330             value = value < 0. ? -0.001 : 0.001;
0331         }
0332         m_color.setValueF(value);
0333         changeColor(m_color, m_color, false);
0334     }
0335 }
0336 
0337 void WheelContainer::mouseReleaseEvent(QMouseEvent *event)
0338 {
0339     Q_UNUSED(event)
0340     if ((m_sliderClick || m_wheelClick) && !(event->modifiers() & Qt::ShiftModifier)) {
0341         // Create an undo entry
0342         changeColor(m_sourceColor, m_color, true);
0343     }
0344     m_wheelClick = false;
0345     m_sliderClick = false;
0346     m_isMouseDown = false;
0347 }
0348 
0349 void WheelContainer::resizeEvent(QResizeEvent *event)
0350 {
0351     m_image = QImage(event->size(), QImage::Format_ARGB32_Premultiplied);
0352     m_image.fill(palette().window().color().rgb());
0353 
0354     drawWheel();
0355     drawSlider();
0356     update();
0357 }
0358 
0359 const QString WheelContainer::getParamValues() const
0360 {
0361     return QString::number(m_color.redF() * m_sizeFactor, 'f', 3) + QLatin1Char(',') + QString::number(m_color.greenF() * m_sizeFactor, 'f', 3) +
0362            QLatin1Char(',') + QString::number(m_color.blueF() * m_sizeFactor, 'f', 3);
0363 }
0364 
0365 const QList<double> WheelContainer::getNiceParamValues() const
0366 {
0367     return {m_color.redF() * m_sizeFactor, m_color.greenF() * m_sizeFactor, m_color.blueF() * m_sizeFactor};
0368 }
0369 
0370 void WheelContainer::paintEvent(QPaintEvent *event)
0371 {
0372     Q_UNUSED(event)
0373     QPainter painter(this);
0374     //    QStyleOption opt;
0375     //    opt.init(this);
0376     painter.setRenderHint(QPainter::Antialiasing);
0377     painter.drawImage(0, 0, m_image);
0378     // painter.drawRect(0, 0, width(), height());
0379     // painter.drawText(m_margin, wheelSize() + m_unitSize - m_margin, m_name + QLatin1Char(' ') + getParamValues());
0380     drawWheelDot(painter);
0381     drawSliderBar(painter);
0382     //    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
0383 }
0384 
0385 void WheelContainer::drawWheel()
0386 {
0387     int r = wheelSize();
0388     QPainter painter(&m_image);
0389     painter.setRenderHint(QPainter::Antialiasing);
0390     m_image.fill(0); // transparent
0391 
0392     QConicalGradient conicalGradient;
0393     conicalGradient.setColorAt(0.0, Qt::red);
0394     conicalGradient.setColorAt(60.0 / 360.0, Qt::yellow);
0395     conicalGradient.setColorAt(135.0 / 360.0, Qt::green);
0396     conicalGradient.setColorAt(180.0 / 360.0, Qt::cyan);
0397     conicalGradient.setColorAt(240.0 / 360.0, Qt::blue);
0398     conicalGradient.setColorAt(315.0 / 360.0, Qt::magenta);
0399     conicalGradient.setColorAt(1.0, Qt::red);
0400 
0401     QRadialGradient radialGradient(0.0, 0.0, r / 2);
0402     radialGradient.setColorAt(0.0, Qt::white);
0403     radialGradient.setColorAt(1.0, Qt::transparent);
0404 
0405     painter.translate(r / 2, r / 2);
0406     painter.rotate(-105);
0407 
0408     QBrush hueBrush(conicalGradient);
0409     painter.setPen(Qt::NoPen);
0410     painter.setBrush(hueBrush);
0411     painter.drawEllipse(QPointF(0, 0), r / 2 - m_margin, r / 2 - m_margin);
0412 
0413     QBrush saturationBrush(radialGradient);
0414     painter.setBrush(saturationBrush);
0415     painter.drawEllipse(QPointF(0, 0), r / 2 - m_margin, r / 2 - m_margin);
0416 
0417     painter.setBrush(Qt::gray);
0418     painter.setOpacity(0.4);
0419     painter.drawEllipse(QPointF(0, 0), r / 2 - m_unitSize * .6 - m_margin, r / 2 - m_unitSize * .6 - m_margin);
0420 
0421     m_wheelRegion = QRegion(r / 2, r / 2, r - 2 * m_margin, r - 2 * m_margin, QRegion::Ellipse);
0422     m_wheelRegion.translate(-(r - 2 * m_margin) / 2, -(r - 2 * m_margin) / 2);
0423 }
0424 
0425 void WheelContainer::drawSlider()
0426 {
0427     QPainter painter(&m_image);
0428     painter.setRenderHint(QPainter::Antialiasing);
0429     int pos = int(wheelSize() + m_unitSize * .2 + m_sliderBorder);
0430     qreal scale = qreal(pos + m_sliderWidth) / maximumWidth();
0431     int w = int(m_sliderWidth * scale - m_unitSize * .2);
0432     QLinearGradient gradient(0, 0, w, sliderHeight());
0433     NegQColor c = m_color;
0434     c.setValueF(1);
0435     gradient.setColorAt(0.0, c.qcolor);
0436     c.setValueF(-m_zeroShift);
0437     gradient.setColorAt(1.0, QColorUtils::complementary(c.qcolor));
0438     QBrush brush(gradient);
0439     QPen pen(m_sliderFocus ? QPalette().highlight().color() : Qt::NoPen);
0440     pen.setWidth(m_sliderBorder);
0441     painter.setPen(pen);
0442     painter.setBrush(brush);
0443     painter.translate(pos, m_margin + m_sliderBorder);
0444     painter.drawRoundedRect(QRect(0, 0, w, sliderHeight()), w / 3, w / 3);
0445     m_sliderRegion = QRegion(pos, m_margin + m_sliderBorder, w, sliderHeight() - m_margin);
0446 }
0447 
0448 void WheelContainer::drawWheelDot(QPainter &painter)
0449 {
0450     int r = wheelSize() / 2;
0451     QPen pen(Qt::white);
0452     pen.setWidth(2);
0453     painter.setPen(pen);
0454     painter.setBrush(Qt::black);
0455     painter.translate(r, r);
0456     painter.rotate(360.0 - m_color.hue());
0457     painter.rotate(-105);
0458     //    r -= margin;
0459     painter.drawEllipse(QPointF(m_color.saturationF() * (r - m_margin * 2), 0.0), 4, 4);
0460     painter.resetTransform();
0461 }
0462 
0463 QPointF WheelContainer::pointForColor()
0464 {
0465     int r = wheelSize() / 2;
0466     QTransform transform;
0467     transform.translate(r, r);
0468     transform.rotate(255 - m_color.hue());
0469     transform.translate(m_color.saturationF() * r, 0);
0470     return transform.map(QPointF(0, 0));
0471 }
0472 
0473 double WheelContainer::yForColor()
0474 {
0475     qreal value = 1.0 - m_color.valueF();
0476     if (m_id == QLatin1String("lift")) {
0477         value -= m_zeroShift;
0478     }
0479     int ws = wheelSize();
0480     int h = ws - m_margin * 2;
0481     return m_margin + value * h;
0482 }
0483 
0484 void WheelContainer::drawSliderBar(QPainter &painter)
0485 {
0486     qreal value = 1.0 - m_color.valueF();
0487     if (m_id == QLatin1String("lift")) {
0488         value -= m_zeroShift;
0489     }
0490     int pos = wheelSize();
0491     qreal scale = qreal(pos + m_sliderWidth) / maximumWidth();
0492     int w = int(m_sliderWidth * scale + m_sliderBorder * 2);
0493     int h = m_sliderBorder * 2;
0494     QPen pen(Qt::white);
0495     pen.setWidth(m_sliderBorder);
0496     painter.setPen(pen);
0497     painter.setBrush(Qt::black);
0498     painter.translate(pos + m_sliderBorder, m_margin + value * sliderHeight() - (h / 2) + m_sliderBorder);
0499     painter.drawRect(0, 0, w, h);
0500     painter.resetTransform();
0501 }
0502 
0503 void WheelContainer::changeColor(const NegQColor &sourceColor, const NegQColor &color, bool createUndo)
0504 {
0505     m_color = color;
0506     drawWheel();
0507     drawSlider();
0508     update();
0509     Q_EMIT colorChange(sourceColor, m_color, createUndo);
0510 }
0511 
0512 ColorWheel::ColorWheel(const QString &id, const QString &name, const NegQColor &color, QWidget *parent)
0513     : QWidget(parent)
0514 {
0515     QFontInfo info(font());
0516     int unitSize = info.pixelSize();
0517     auto *lay = new QVBoxLayout(this);
0518     m_wheelName = new QLabel(name, this);
0519     m_wheelName->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
0520     lay->addWidget(m_wheelName);
0521     m_container = new WheelContainer(id, name, color, unitSize, this);
0522     auto *hb = new QHBoxLayout;
0523     m_redEdit = new QDoubleSpinBox(this);
0524     m_redEdit->setPrefix(i18n("R: "));
0525     m_redEdit->setFrame(QFrame::NoFrame);
0526     m_redEdit->setDecimals(3);
0527     m_redEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
0528     m_redEdit->setFont(m_wheelName->font());
0529     m_redEdit->setObjectName(QStringLiteral("dragMinimal"));
0530     m_greenEdit = new QDoubleSpinBox(this);
0531     m_greenEdit->setPrefix(i18n("G: "));
0532     m_greenEdit->setObjectName(QStringLiteral("dragMinimal"));
0533     m_greenEdit->setFont(m_wheelName->font());
0534     m_greenEdit->setDecimals(3);
0535     m_greenEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
0536     m_blueEdit = new QDoubleSpinBox(this);
0537     m_blueEdit->setPrefix(i18n("B: "));
0538     m_blueEdit->setObjectName(QStringLiteral("dragMinimal"));
0539     m_blueEdit->setFont(m_wheelName->font());
0540     m_blueEdit->setDecimals(3);
0541     m_blueEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
0542     lay->setContentsMargins(0, 0, 2, 0);
0543     lay->setSpacing(0);
0544     lay->addWidget(m_container);
0545     hb->addWidget(m_redEdit);
0546     hb->addWidget(m_greenEdit);
0547     hb->addWidget(m_blueEdit);
0548     hb->setSpacing(0);
0549     hb->setContentsMargins(0, 0, 0, 0);
0550     lay->addLayout(hb);
0551     m_container->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
0552     connect(m_container, &WheelContainer::colorChange, this, [&](const NegQColor &sourceCol, const NegQColor &col, bool createUndo) {
0553         QList<double> vals = m_container->getNiceParamValues();
0554         m_redEdit->blockSignals(true);
0555         m_greenEdit->blockSignals(true);
0556         m_blueEdit->blockSignals(true);
0557         m_redEdit->setValue(vals.at(0));
0558         m_greenEdit->setValue(vals.at(1));
0559         m_blueEdit->setValue(vals.at(2));
0560         m_redEdit->blockSignals(false);
0561         m_greenEdit->blockSignals(false);
0562         m_blueEdit->blockSignals(false);
0563         Q_EMIT colorChange(sourceCol, col, createUndo);
0564     });
0565     connect(m_redEdit, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this,
0566             [&]() { m_container->setRedColor(m_redEdit->value()); });
0567     connect(m_greenEdit, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this,
0568             [&]() { m_container->setGreenColor(m_greenEdit->value()); });
0569     connect(m_blueEdit, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this,
0570             [&]() { m_container->setBlueColor(m_blueEdit->value()); });
0571     setMinimumHeight(m_wheelName->height() + m_container->minimumHeight() + m_redEdit->height());
0572     setMaximumWidth(m_container->maximumWidth());
0573     setMinimumWidth(3 * m_redEdit->sizeHint().width());
0574 }
0575 
0576 NegQColor ColorWheel::color() const
0577 {
0578     return m_container->color();
0579 }
0580 
0581 void ColorWheel::setColor(const QList<double> &values)
0582 {
0583     m_container->setColor(values);
0584     m_redEdit->blockSignals(true);
0585     m_greenEdit->blockSignals(true);
0586     m_blueEdit->blockSignals(true);
0587     m_redEdit->setValue(values.at(0));
0588     m_greenEdit->setValue(values.at(1));
0589     m_blueEdit->setValue(values.at(2));
0590     m_redEdit->blockSignals(false);
0591     m_greenEdit->blockSignals(false);
0592     m_blueEdit->blockSignals(false);
0593 }
0594 
0595 void ColorWheel::setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero)
0596 {
0597     m_container->setFactorDefaultZero(factor, defvalue, zero);
0598     if (zero > 0) {
0599         // Lift has a special range
0600         m_redEdit->setRange(-1, 1);
0601         m_greenEdit->setRange(-1, 1);
0602         m_blueEdit->setRange(-1, 1);
0603     } else {
0604         m_redEdit->setRange(0, factor);
0605         m_greenEdit->setRange(0, factor);
0606         m_blueEdit->setRange(0, factor);
0607     }
0608     m_redEdit->setSingleStep(.01);
0609     m_greenEdit->setSingleStep(.01);
0610     m_blueEdit->setSingleStep(.01);
0611 }