Revision control

++ // Copyright (C) 2016 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
++ // Qt-Security score:significant reason:default
++
++ #include "qtcolorline_p.h"
++ #include "qdrawutil.h"
++
++ #include <QtWidgets/qstyleoption.h>
++
++ #include <QtGui/qevent.h>
++ #include <QtGui/qpainter.h>
++ #include <QtGui/qregion.h>
++
++ QT_BEGIN_NAMESPACE
++
++ class QtColorLinePrivate
++ {
++ QtColorLine *q_ptr = nullptr;
++ Q_DECLARE_PUBLIC(QtColorLine)
++ public:
++ QtColorLinePrivate();
++
++ QColor color() const;
++ void setColor(QColor color);
++
++ QtColorLine::ColorComponent colorComponent() const;
++ void setColorComponent(QtColorLine::ColorComponent component);
++
++ void setIndicatorSize(int size);
++ int indicatorSize() const;
++
++ void setIndicatorSpace(int space);
++ int indicatorSpace() const;
++
++ void setFlip(bool flip);
++ bool flip() const;
++
++ void setBackgroundCheckered(bool checkered);
++ bool isBackgroundCheckered() const;
++
++ void setOrientation(Qt::Orientation orientation);
++ Qt::Orientation orientation() const;
++
++ void resizeEvent(QResizeEvent *event);
++ void paintEvent(QPaintEvent *event);
++ void mousePressEvent(QMouseEvent *event);
++ void mouseMoveEvent(QMouseEvent *event);
++ void mouseReleaseEvent(QMouseEvent *event);
++ void mouseDoubleClickEvent(QMouseEvent *event);
++ private:
++ void checkColor();
++ bool isMainPixmapValid() const;
++ void validate();
++ void recreateMainPixmap();
++ QSize pixmapSizeFromGeometrySize(QSize geometrySize) const;
++ QPixmap gradientPixmap(int size, Qt::Orientation orientation,
++ QColor begin, QColor end, bool flipped = false) const;
++ QPixmap gradientPixmap(Qt::Orientation orientation,
++ QColor begin, QColor end, bool flipped = false) const;
++ QPixmap hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped = false,
++ int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const;
++ QPixmap hueGradientPixmap(Qt::Orientation orientation, bool flipped = false,
++ int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const;
++
++ QList<QRect> rects(QPointF point) const;
++
++ QColor colorFromPoint(QPointF point) const;
++ QPointF pointFromColor(QColor color) const;
++
++ QColor m_color = Qt::black;
++ QtColorLine::ColorComponent m_component = QtColorLine::Value;
++ bool m_flipped = false;
++ bool m_backgroundCheckered = true;
++ Qt::Orientation m_orientation = Qt::Horizontal;
++ bool m_dragging = false;
++ bool m_combiningAlpha = false;
++ int m_indicatorSize = 22;
++ int m_indicatorSpace = 0;
++ QPointF m_point;
++ QPoint m_clickOffset;
++
++ QPixmap m_mainPixmap;
++ QPixmap m_alphalessPixmap;
++ QPixmap m_semiAlphaPixmap;
++ QSize m_pixmapSize{0, 0};
++
++ struct PixData {
++ QSize size;
++ QColor color;
++ QtColorLine::ColorComponent component;
++ bool flipped;
++ Qt::Orientation orientation;
++ };
++
++ PixData m_lastValidMainPixmapData;
++ };
++
++ QtColorLinePrivate::QtColorLinePrivate()
++ : m_point(pointFromColor(m_color))
++ {
++ }
++
++ void QtColorLinePrivate::setColor(QColor color)
++ {
++ if (m_color == color)
++ return;
++ if (!color.isValid())
++ return;
++ if (m_dragging) // Warning perhaps here, recursive call
++ return;
++ m_color = color;
++ checkColor();
++ m_point = pointFromColor(m_color);
++ q_ptr->update();
++ }
++
++ QColor QtColorLinePrivate::color() const
++ {
++ return m_color;
++ }
++
++ void QtColorLinePrivate::setColorComponent(QtColorLine::ColorComponent component)
++ {
++ if (m_component == component)
++ return;
++ if (m_dragging) // Warning perhaps here, recursive call
++ return;
++ m_component = component;
++ checkColor();
++ m_point = pointFromColor(m_color);
++ q_ptr->update();
++ }
++
++ QtColorLine::ColorComponent QtColorLinePrivate::colorComponent() const
++ {
++ return m_component;
++ }
++
++ void QtColorLinePrivate::setIndicatorSize(int size)
++ {
++ if (size <= 0)
++ return;
++ if (m_dragging) // Warning perhaps here, recursive call
++ return;
++ if (m_indicatorSize == size)
++ return;
++ m_indicatorSize = size;
++ m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size());
++ q_ptr->update();
++ q_ptr->updateGeometry();
++ }
++
++ int QtColorLinePrivate::indicatorSize() const
++ {
++ return m_indicatorSize;
++ }
++
++ void QtColorLinePrivate::setIndicatorSpace(int space)
++ {
++ if (space < 0)
++ return;
++ if (m_dragging) // Warning perhaps here, recursive call
++ return;
++ if (m_indicatorSpace == space)
++ return;
++ m_indicatorSpace = space;
++ m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size());
++ q_ptr->update();
++ }
++
++ int QtColorLinePrivate::indicatorSpace() const
++ {
++ return m_indicatorSpace;
++ }
++
++ void QtColorLinePrivate::setFlip(bool flip)
++ {
++ if (m_dragging) // Warning perhaps here, recursive call
++ return;
++ if (m_flipped == flip)
++ return;
++ m_flipped = flip;
++ m_point = pointFromColor(m_color);
++ q_ptr->update();
++ }
++
++ bool QtColorLinePrivate::flip() const
++ {
++ return m_flipped;
++ }
++
++ void QtColorLinePrivate::setBackgroundCheckered(bool checkered)
++ {
++ if (m_backgroundCheckered == checkered)
++ return;
++ m_backgroundCheckered = checkered;
++ q_ptr->update();
++ }
++
++ bool QtColorLinePrivate::isBackgroundCheckered() const
++ {
++ return m_backgroundCheckered;
++ }
++
++ void QtColorLinePrivate::setOrientation(Qt::Orientation orientation)
++ {
++ if (m_dragging) // Warning perhaps here, recursive call
++ return;
++ if (m_orientation == orientation)
++ return;
++
++ m_orientation = orientation;
++ if (!q_ptr->testAttribute(Qt::WA_WState_OwnSizePolicy)) {
++ QSizePolicy sp = q_ptr->sizePolicy();
++ sp.transpose();
++ q_ptr->setSizePolicy(sp);
++ q_ptr->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
++ }
++ m_point = pointFromColor(m_color);
++ q_ptr->update();
++ q_ptr->updateGeometry();
++ }
++
++ Qt::Orientation QtColorLinePrivate::orientation() const
++ {
++ return m_orientation;
++ }
++
++ void QtColorLinePrivate::checkColor()
++ {
++ switch (m_component) {
++ case QtColorLine::Red:
++ case QtColorLine::Green:
++ case QtColorLine::Blue:
++ if (m_color.spec() != QColor::Rgb)
++ m_color = m_color.toRgb();
++ break;
++ case QtColorLine::Hue:
++ case QtColorLine::Saturation:
++ case QtColorLine::Value:
++ if (m_color.spec() != QColor::Hsv)
++ m_color = m_color.toHsv();
++ break;
++ default:
++ break;
++ }
++ if (m_color.spec() == QColor::Hsv) {
++ if (m_color.hue() == 360 || m_color.hue() == -1) {
++ m_color.setHsvF(0.0, m_color.saturationF(), m_color.valueF(), m_color.alphaF());
++ }
++ }
++ }
++
++ bool QtColorLinePrivate::isMainPixmapValid() const
++ {
++ if (m_mainPixmap.isNull()) {
++ if (m_pixmapSize.isEmpty())
++ return true;
++ else
++ return false;
++ }
++ if (m_lastValidMainPixmapData.component != m_component)
++ return false;
++ if (m_lastValidMainPixmapData.size != m_pixmapSize)
++ return false;
++ if (m_lastValidMainPixmapData.flipped != m_flipped)
++ return false;
++ if (m_lastValidMainPixmapData.orientation != m_orientation)
++ return false;
++ if (m_lastValidMainPixmapData.color == m_color)
++ return true;
++ switch (m_component) {
++ case QtColorLine::Red:
++ if (m_color.green() == m_lastValidMainPixmapData.color.green() &&
++ m_color.blue() == m_lastValidMainPixmapData.color.blue() &&
++ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
++ return true;
++ break;
++ case QtColorLine::Green:
++ if (m_color.red() == m_lastValidMainPixmapData.color.red() &&
++ m_color.blue() == m_lastValidMainPixmapData.color.blue() &&
++ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
++ return true;
++ break;
++ case QtColorLine::Blue:
++ if (m_color.red() == m_lastValidMainPixmapData.color.red() &&
++ m_color.green() == m_lastValidMainPixmapData.color.green() &&
++ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
++ return true;
++ break;
++ case QtColorLine::Hue:
++ if (m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
++ m_color.value() == m_lastValidMainPixmapData.color.value() &&
++ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
++ return true;
++ break;
++ case QtColorLine::Saturation:
++ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
++ m_color.value() == m_lastValidMainPixmapData.color.value() &&
++ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
++ return true;
++ break;
++ case QtColorLine::Value:
++ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
++ m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
++ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
++ return true;
++ break;
++ case QtColorLine::Alpha:
++ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
++ m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
++ m_color.value() == m_lastValidMainPixmapData.color.value())
++ return true;
++ }
++ return false;
++ }
++
++ void QtColorLinePrivate::validate()
++ {
++ if (isMainPixmapValid())
++ return;
++
++ recreateMainPixmap();
++ }
++
++ QPixmap QtColorLinePrivate::gradientPixmap(Qt::Orientation orientation,
++ QColor begin, QColor end, bool flipped) const
++ {
++ int size = m_pixmapSize.width();
++ if (orientation == Qt::Vertical)
++ size = m_pixmapSize.height();
++ return gradientPixmap(size, orientation, begin, end, flipped);
++ }
++
++ QPixmap QtColorLinePrivate::gradientPixmap(int size, Qt::Orientation orientation,
++ QColor begin, QColor end, bool flipped) const
++ {
++ int gradW = size;
++ int gradH = size;
++ int w = size;
++ int h = size;
++ if (orientation == Qt::Horizontal) {
++ gradH = 0;
++ h = 1;
++ } else {
++ gradW = 0;
++ w = 1;
++ }
++ QColor c1 = begin;
++ QColor c2 = end;
++ if (flipped) {
++ c1 = end;
++ c2 = begin;
++ }
++ QLinearGradient lg(0, 0, gradW, gradH);
++ lg.setColorAt(0, c1);
++ lg.setColorAt(1, c2);
++ QImage img(w, h, QImage::Format_ARGB32);
++ QPainter p(&img);
++ p.setCompositionMode(QPainter::CompositionMode_Source);
++ p.fillRect(QRect(0, 0, w, h), lg);
++ return QPixmap::fromImage(img);
++ }
++
++ QPixmap QtColorLinePrivate::hueGradientPixmap(Qt::Orientation orientation, bool flipped,
++ int saturation, int value, int alpha) const
++ {
++ int size = m_pixmapSize.width();
++ if (orientation == Qt::Vertical)
++ size = m_pixmapSize.height();
++ return hueGradientPixmap(size, orientation, flipped, saturation, value, alpha);
++ }
++
++ QPixmap QtColorLinePrivate::hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped,
++ int saturation, int value, int alpha) const
++ {
++ int gradW = size + 1;
++ int gradH = size + 1;
++ int w = size;
++ int h = size;
++ if (orientation == Qt::Horizontal) {
++ gradH = 0;
++ h = 1;
++ } else {
++ gradW = 0;
++ w = 1;
++ }
++ QList<QColor> colorList;
++ colorList << QColor::fromHsv(0, saturation, value, alpha);
++ colorList << QColor::fromHsv(60, saturation, value, alpha);
++ colorList << QColor::fromHsv(120, saturation, value, alpha);
++ colorList << QColor::fromHsv(180, saturation, value, alpha);
++ colorList << QColor::fromHsv(240, saturation, value, alpha);
++ colorList << QColor::fromHsv(300, saturation, value, alpha);
++ colorList << QColor::fromHsv(0, saturation, value, alpha);
++ QLinearGradient lg(0, 0, gradW, gradH);
++ for (int i = 0; i <= 6; i++)
++ lg.setColorAt(double(i) / 6.0, flipped ? colorList.at(6 - i) : colorList.at(i));
++ QImage img(w, h, QImage::Format_ARGB32);
++ QPainter p(&img);
++ p.setCompositionMode(QPainter::CompositionMode_Source);
++ p.fillRect(QRect(0, 0, w, h), lg);
++ return QPixmap::fromImage(img);
++ }
++
++ void QtColorLinePrivate::recreateMainPixmap()
++ {
++ m_lastValidMainPixmapData.size = m_pixmapSize;
++ m_lastValidMainPixmapData.component = m_component;
++ m_lastValidMainPixmapData.color = m_color;
++ m_lastValidMainPixmapData.flipped = m_flipped;
++ m_lastValidMainPixmapData.orientation = m_orientation;
++
++ if (m_pixmapSize.isEmpty()) {
++ m_mainPixmap = QPixmap();
++ m_alphalessPixmap = QPixmap();
++ m_semiAlphaPixmap = QPixmap();
++ return;
++ }
++
++ if (m_mainPixmap.size() != m_pixmapSize) {
++ m_mainPixmap = QPixmap(m_pixmapSize);
++ m_alphalessPixmap = QPixmap(m_pixmapSize);
++ m_semiAlphaPixmap = QPixmap(m_pixmapSize);
++ }
++
++ Qt::Orientation orient = m_orientation;
++ const bool flip = m_flipped;
++
++ const int r = m_color.red();
++ const int g = m_color.green();
++ const int b = m_color.blue();
++ const int h = m_color.hue();
++ const int s = m_color.saturation();
++ const int v = m_color.value();
++ const int a = m_color.alpha();
++ const double coef = 0.5;
++ const int semi = qRound(a * coef + 0xFF * (1.0 - coef));
++
++ if (m_component == QtColorLine::Hue) {
++ m_alphalessPixmap = hueGradientPixmap(orient, flip, s, v, 0xFF);
++ if (m_combiningAlpha) {
++ m_mainPixmap = hueGradientPixmap(orient, flip, s, v, a);
++ m_semiAlphaPixmap = hueGradientPixmap(orient, flip, s, v, semi);
++ }
++ } else if (m_component == QtColorLine::Saturation) {
++ m_alphalessPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, 0xFF), QColor::fromHsv(h, 0xFF, v, 0xFF), flip);
++ if (m_combiningAlpha) {
++ m_mainPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, a), QColor::fromHsv(h, 0xFF, v, a), flip);
++ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, semi), QColor::fromHsv(h, 0xFF, v, semi), flip);
++ }
++ } else if (m_component == QtColorLine::Value) {
++ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, 0xFF), QColor::fromHsv(h, s, 0xFF, 0xFF), flip);
++ if (m_combiningAlpha) {
++ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, a), QColor::fromHsv(h, s, 0xFF, a), flip);
++ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, semi), QColor::fromHsv(h, s, 0xFF, semi), flip);
++ }
++ } else if (m_component == QtColorLine::Red) {
++ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, 0xFF), QColor::fromRgb(0xFF, g, b, 0xFF), flip);
++ if (m_combiningAlpha) {
++ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, a), QColor::fromRgb(0xFF, g, b, a), flip);
++ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, semi), QColor::fromRgb(0xFF, g, b, semi), flip);
++ }
++ } else if (m_component == QtColorLine::Green) {
++ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, 0xFF), QColor::fromRgb(r, 0xFF, b, 0xFF), flip);
++ if (m_combiningAlpha) {
++ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, a), QColor::fromRgb(r, 0xFF, b, a), flip);
++ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, semi), QColor::fromRgb(r, 0xFF, b, semi), flip);
++ }
++ } else if (m_component == QtColorLine::Blue) {
++ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, 0xFF), QColor::fromRgb(r, g, 0xFF, 0xFF), flip);
++ if (m_combiningAlpha) {
++ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, a), QColor::fromRgb(r, g, 0xFF, a), flip);
++ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, semi), QColor::fromRgb(r, g, 0xFF, semi), flip);
++ }
++ } else if (m_component == QtColorLine::Alpha) {
++ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0), QColor::fromRgb(r, g, b, 0xFF), flip);
++
++ // m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0xFF), QColor::fromRgb(r, g, b, 0xFF), flip);
++ // m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, semi), QColor::fromRgb(r, g, b, semi), flip);
++ }
++ if (!m_combiningAlpha && m_component != QtColorLine::Alpha)
++ m_mainPixmap = m_alphalessPixmap;
++ }
++
++ QSize QtColorLinePrivate::pixmapSizeFromGeometrySize(QSize geometrySize) const
++ {
++ QSize size(m_indicatorSize + 2 * m_indicatorSpace - 1,
++ m_indicatorSize + 2 * m_indicatorSpace - 1);
++ if (m_orientation == Qt::Horizontal)
++ size.setHeight(0);
++ else
++ size.setWidth(0);
++ return geometrySize - size;
++ }
++
++ QColor QtColorLinePrivate::colorFromPoint(QPointF point) const
++ {
++ QPointF p = point;
++ if (p.x() < 0)
++ p.setX(0.0);
++ else if (p.x() > 1)
++ p.setX(1.0);
++ if (p.y() < 0)
++ p.setY(0.0);
++ else if (p.y() > 1)
++ p.setY(1.0);
++
++ double pos = p.x();
++ if (m_orientation == Qt::Vertical)
++ pos = p.y();
++ if (m_flipped)
++ pos = 1.0 - pos;
++ QColor c;
++ qreal hue;
++ switch (m_component) {
++ case QtColorLine::Red:
++ c.setRgbF(pos, m_color.greenF(), m_color.blueF(), m_color.alphaF());
++ break;
++ case QtColorLine::Green:
++ c.setRgbF(m_color.redF(), pos, m_color.blueF(), m_color.alphaF());
++ break;
++ case QtColorLine::Blue:
++ c.setRgbF(m_color.redF(), m_color.greenF(), pos, m_color.alphaF());
++ break;
++ case QtColorLine::Hue:
++ hue = pos;
++ hue *= 35999.0 / 36000.0;
++ c.setHsvF(hue, m_color.saturationF(), m_color.valueF(), m_color.alphaF());
++ break;
++ case QtColorLine::Saturation:
++ c.setHsvF(m_color.hueF(), pos, m_color.valueF(), m_color.alphaF());
++ break;
++ case QtColorLine::Value:
++ c.setHsvF(m_color.hueF(), m_color.saturationF(), pos, m_color.alphaF());
++ break;
++ case QtColorLine::Alpha:
++ c.setHsvF(m_color.hueF(), m_color.saturationF(), m_color.valueF(), pos);
++ break;
++ }
++ return c;
++ }
++
++ QPointF QtColorLinePrivate::pointFromColor(QColor color) const
++ {
++ qreal hue = color.hueF();
++ if (color.hue() == 360)
++ hue = 0.0;
++ else
++ hue *= 36000.0 / 35999.0;
++
++ double pos = 0.0;
++ switch (m_component) {
++ case QtColorLine::Red:
++ pos = color.redF();
++ break;
++ case QtColorLine::Green:
++ pos = color.greenF();
++ break;
++ case QtColorLine::Blue:
++ pos = color.blueF();
++ break;
++ case QtColorLine::Hue:
++ pos = hue;
++ break;
++ case QtColorLine::Saturation:
++ pos = color.saturationF();
++ break;
++ case QtColorLine::Value:
++ pos = color.valueF();
++ break;
++ case QtColorLine::Alpha:
++ pos = color.alphaF();
++ break;
++ }
++ if (m_flipped)
++ pos = 1.0 - pos;
++ QPointF p(pos, pos);
++ if (m_orientation == Qt::Horizontal)
++ p.setY(0);
++ else
++ p.setX(0);
++ return p;
++ }
++
++ QList<QRect> QtColorLinePrivate::rects(QPointF point) const
++ {
++ QRect r = q_ptr->geometry();
++ r.moveTo(0, 0);
++
++ int x1 = (int)((r.width() - m_indicatorSize - 2 * m_indicatorSpace) * point.x() + 0.5);
++ int x2 = x1 + m_indicatorSize + 2 * m_indicatorSpace;
++ int y1 = (int)((r.height() - m_indicatorSize - 2 * m_indicatorSpace) * point.y() + 0.5);
++ int y2 = y1 + m_indicatorSize + 2 * m_indicatorSpace;
++
++ QList<QRect> rects;
++ if (m_orientation == Qt::Horizontal) {
++ // r0 r1 r2
++ QRect r0(0, 0, x1, r.height());
++ QRect r1(x1 + m_indicatorSpace, 0, m_indicatorSize, r.height());
++ QRect r2(x2, 0, r.width() - x2, r.height());
++
++ rects << r0 << r1 << r2;
++ } else {
++ // r0
++ // r1
++ // r2
++ QRect r0(0, 0, r.width(), y1);
++ QRect r1(0, y1 + m_indicatorSpace, r.width(), m_indicatorSize);
++ QRect r2(0, y2, r.width(), r.height() - y2);
++
++ rects << r0 << r1 << r2;
++ }
++ return rects;
++ }
++
++ void QtColorLinePrivate::resizeEvent(QResizeEvent *event)
++ {
++ m_pixmapSize = pixmapSizeFromGeometrySize(event->size());
++ }
++
++ void QtColorLinePrivate::paintEvent(QPaintEvent *)
++ {
++ QRect rect = q_ptr->rect();
++
++ QList<QRect> r = rects(m_point);
++
++ QColor c = colorFromPoint(m_point);
++ if (!m_combiningAlpha && m_component != QtColorLine::Alpha)
++ c.setAlpha(0xFF);
++
++ QPainter p(q_ptr);
++ if (q_ptr->isEnabled()) {
++ if (m_backgroundCheckered) {
++ int pixSize = 20;
++ QPixmap pm(2 * pixSize, 2 * pixSize);
++ QPainter pmp(&pm);
++ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
++ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
++ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
++ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
++ pmp.end();
++
++ p.setBrushOrigin((rect.width() % pixSize + pixSize) / 2, (rect.height() % pixSize + pixSize) / 2);
++
++ QRegion region(r[1].adjusted(4, 4, -4, -4));
++ region += QRect(rect.topLeft(), QPoint(r[1].left() + 0, rect.bottom()));
++ region += QRect(QPoint(r[1].right() - 0, rect.top()), rect.bottomRight());
++ region += QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 0));
++ region += QRect(QPoint(rect.left(), r[1].bottom() - 0), rect.bottomRight());
++ p.setClipRegion(region);
++ p.fillRect(rect, pm);
++ p.setBrushOrigin(0, 0);
++ p.setClipping(false);
++ }
++
++ validate();
++
++ QSize fieldSize = pixmapSizeFromGeometrySize(q_ptr->geometry().size());
++
++ QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace);
++ int x = posOnField.x();
++ int y = posOnField.y();
++ int w = fieldSize.width();
++ int h = fieldSize.height();
++
++ QRect r0, r2;
++ if (m_orientation == Qt::Horizontal) {
++ r0 = QRect(0, 0, x, m_pixmapSize.height());
++ r2 = QRect(x + 1, 0, w - x - 1, m_pixmapSize.height());
++ } else {
++ r0 = QRect(0, 0, m_pixmapSize.width(), y);
++ r2 = QRect(0, y + 1, m_pixmapSize.width(), h - y - 1);
++ }
++
++ p.setBrush(m_mainPixmap);
++ p.setPen(Qt::NoPen);
++ if (r[0].isValid()) {
++ p.drawRect(r[0]);
++ }
++ if (r[2].isValid()) {
++ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
++ p.drawRect(r[2]);
++ }
++ if (m_indicatorSpace) {
++ p.setBrush(c);
++ if (m_orientation == Qt::Horizontal) {
++ p.drawRect(r[1].adjusted(-m_indicatorSpace, 0, -r[1].width(), 0));
++ p.drawRect(r[1].adjusted(r[1].width(), 0, m_indicatorSpace, 0));
++ } else {
++ p.drawRect(r[1].adjusted(0, -m_indicatorSpace, 0, -r[1].height()));
++ p.drawRect(r[1].adjusted(0, r[1].height(), 0, m_indicatorSpace));
++ }
++ }
++
++ QPen pen(c);
++ p.setPen(pen);
++ p.setBrush(Qt::NoBrush);
++ if (r[1].isValid()) {
++ p.drawRect(r[1].adjusted(0, 0, -1, -1));
++ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
++ }
++ double coef = 9.0 / 10;
++ p.setPen(Qt::NoPen);
++ if (m_component != QtColorLine::Alpha && m_combiningAlpha) {
++ p.setBrush(m_alphalessPixmap);
++ if (r[0].isValid()) {
++ p.setBrushOrigin(QPoint(0, 0));
++ QRect thinRect1 = r[0];
++ QRect thinRect2 = r[0];
++ QRect thinRect = r[0];
++ if (m_orientation == Qt::Horizontal) {
++ thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0);
++ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef));
++ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
++ } else {
++ thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0);
++ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0);
++ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
++ }
++ p.drawRect(thinRect1);
++ p.drawRect(thinRect2);
++ //p.drawRect(thinRect);
++ }
++ if (r[2].isValid()) {
++ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
++ QRect thinRect1 = r[2];
++ QRect thinRect2 = r[2];
++ QRect thinRect = r[2];
++ if (m_orientation == Qt::Horizontal) {
++ thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0);
++ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef));
++ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
++ } else {
++ thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0);
++ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0);
++ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
++ }
++ p.drawRect(thinRect1);
++ p.drawRect(thinRect2);
++ //p.drawRect(thinRect);
++ }
++ /*
++
++ */
++
++
++
++
++
++ p.setPen(Qt::NoPen);
++
++ p.setBrush(m_semiAlphaPixmap);
++ if (r[0].isValid()) {
++ p.setBrushOrigin(QPoint(0, 0));
++ QRect thinRect1 = r[0];
++ QRect thinRect2 = r[0];
++ QRect thinRect = r[0];
++ if (m_orientation == Qt::Horizontal) {
++ thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0);
++ thinRect1.setBottom(thinRect1.top());
++ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1);
++ thinRect2.setTop(thinRect2.bottom());
++ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
++ } else {
++ thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0);
++ thinRect1.setRight(thinRect1.left());
++ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0);
++ thinRect2.setLeft(thinRect2.right());
++ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
++ }
++ p.drawRect(thinRect1);
++ p.drawRect(thinRect2);
++ //p.drawRect(thinRect);
++ }
++ if (r[2].isValid()) {
++ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
++ QRect thinRect1 = r[2];
++ QRect thinRect2 = r[2];
++ QRect thinRect = r[2];
++ if (m_orientation == Qt::Horizontal) {
++ thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0);
++ thinRect1.setBottom(thinRect1.top());
++ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1);
++ thinRect2.setTop(thinRect2.bottom());
++ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
++ } else {
++ thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0);
++ thinRect1.setRight(thinRect1.left());
++ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0);
++ thinRect2.setLeft(thinRect2.right());
++ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
++ }
++ p.drawRect(thinRect1);
++ p.drawRect(thinRect2);
++ //p.drawRect(thinRect);
++ }
++ p.setBrush(m_alphalessPixmap);
++ QRegion region;
++ if (m_orientation == Qt::Horizontal) {
++ region += r[1].adjusted(0, qRound(r[1].height() * coef), 0, 0);
++ region += r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef));
++ p.setClipRegion(region);
++ } else {
++ region += r[1].adjusted(qRound(r[1].width() * coef), 0, 0, 0);
++ region += r[1].adjusted(0, 0, -qRound(r[1].width() * coef), 0);
++ p.setClipRegion(region);
++ }
++ p.setClipRegion(region);
++ p.setBrush(Qt::NoBrush);
++ p.setPen(QPen(QColor(c.rgb())));
++
++ p.drawRect(r[1].adjusted(0, 0, -1, -1));
++ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
++ /*
++ p.setBrush(m_semiAlphaPixmap);
++ if (m_orientation == Qt::Horizontal) {
++ QRect top = r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef) + 1);
++ top.setTop(top.bottom());
++ QRect bottom = r[1].adjusted(0, qRound(r[1].height() * coef) - 1, 0, 0);
++ top.setBottom(bottom.top());
++ p.setClipRect(top);
++ p.setClipRect(bottom, Qt::UniteClip);
++ } else {
++
++ }
++ QColor semiColor(c.rgb());
++ semiColor.setAlpha((c.alpha() + 0xFF) / 2);
++ p.setPen(QPen(semiColor));
++ p.drawRect(r[1].adjusted(0, 0, -1, -1));
++ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
++ */
++ p.setClipping(false);
++ }
++ }
++
++ p.setBrush(Qt::NoBrush);
++ int lw = 4;
++ //int br = 1;
++ int br = 0;
++ r[1].adjust(br, br, -br, -br);
++ if (r[1].adjusted(lw, lw, -lw, -lw).isValid()) {
++ QStyleOptionFrame opt;
++ opt.initFrom(q_ptr);
++ opt.rect = r[1];
++ opt.lineWidth = 2;
++ opt.midLineWidth = 1;
++ if (m_dragging)
++ opt.state |= QStyle::State_Sunken;
++ else
++ opt.state |= QStyle::State_Raised;
++ q_ptr->style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, q_ptr);
++ QRect colorRect = r[1].adjusted(lw, lw, -lw, -lw);
++ if (q_ptr->isEnabled()) {
++ p.fillRect(colorRect, c);
++ const QColor frameColor(0, 0, 0, 38);
++ p.setPen(frameColor);
++ p.drawRect(colorRect.adjusted(0, 0, -1, -1));
++ /*
++ p.fillRect(colorRect.width() / 4 + colorRect.left(),
++ colorRect.height() / 4 + colorRect.top(),
++ colorRect.width() / 2,
++ colorRect.height() / 2,
++ QColor(c.rgb()));
++ */
++ /*
++ if (m_component != QtColorLine::Alpha) {
++ p.fillRect(colorRect.adjusted(0, colorRect.height() * 4 / 5, 0, 0), QColor(c.rgb()));
++ p.fillRect(colorRect.adjusted(0, 0, 0, -colorRect.height() * 4 / 5), QColor(c.rgb()));
++ }
++ */
++ }
++ }
++ }
++
++ void QtColorLinePrivate::mousePressEvent(QMouseEvent *event)
++ {
++ if (event->button() != Qt::LeftButton)
++ return;
++
++ QList<QRect> r = rects(m_point);
++ QPoint clickPos = event->position().toPoint();
++
++ QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace);
++ m_clickOffset = posOnField - clickPos;
++
++ if (!r[1].contains(clickPos))
++ return;
++ m_dragging = true;
++ q_ptr->update();
++ }
++
++ void QtColorLinePrivate::mouseMoveEvent(QMouseEvent *event)
++ {
++ if (!m_dragging)
++ return;
++ QPoint newPos = event->position().toPoint();
++
++ QSize fieldSize = q_ptr->geometry().size() -
++ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
++ QPoint newPosOnField = newPos + m_clickOffset;
++ if (newPosOnField.x() < 0)
++ newPosOnField.setX(0);
++ else if (newPosOnField.x() > fieldSize.width())
++ newPosOnField.setX(fieldSize.width());
++ if (newPosOnField.y() < 0)
++ newPosOnField.setY(0);
++ else if (newPosOnField.y() > fieldSize.height())
++ newPosOnField.setY(fieldSize.height());
++
++ const double x = double(newPosOnField.x()) / fieldSize.width();
++ const double y = double(newPosOnField.y()) / fieldSize.height();
++ m_point = QPointF(x, y);
++ QColor color = colorFromPoint(m_point);
++ if (m_color == color)
++ return;
++ m_color = color;
++ emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above
++ q_ptr->update();
++ }
++
++ void QtColorLinePrivate::mouseReleaseEvent(QMouseEvent *event)
++ {
++ if (event->button() != Qt::LeftButton)
++ return;
++ m_dragging = false;
++ q_ptr->update();
++ }
++
++ void QtColorLinePrivate::mouseDoubleClickEvent(QMouseEvent *event)
++ {
++ if (event->button() != Qt::LeftButton)
++ return;
++
++ QList<QRect> r = rects(m_point);
++ QPoint clickPos = event->position().toPoint();
++ if (!r[0].contains(clickPos) && !r[2].contains(clickPos))
++ return;
++ QPoint newPosOnField = clickPos;
++ if (r[2].contains(clickPos))
++ newPosOnField -= QPoint(m_indicatorSize + 2 * m_indicatorSpace - 2, m_indicatorSize + 2 * m_indicatorSpace - 2);
++ QSize fieldSize = q_ptr->geometry().size() -
++ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
++
++ const double x = double(newPosOnField.x()) / fieldSize.width();
++ const double y = double(newPosOnField.y()) / fieldSize.height();
++ m_point = QPointF(x, y);
++ QColor color = colorFromPoint(m_point);
++ if (m_color == color)
++ return;
++ m_color = color;
++ emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above
++ q_ptr->update();
++ }
++
++ ////////////////////////////////////////////////////
++
++ QtColorLine::QtColorLine(QWidget *parent)
++ : QWidget(parent), d_ptr(new QtColorLinePrivate)
++ {
++ d_ptr->q_ptr = this;
++
++ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
++ }
++
++ QtColorLine::~QtColorLine()
++ {
++ }
++
++ QSize QtColorLine::minimumSizeHint() const
++ {
++ return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize);
++ }
++
++ QSize QtColorLine::sizeHint() const
++ {
++ return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize);
++ }
++
++ void QtColorLine::setColor(QColor color)
++ {
++ d_ptr->setColor(color);
++ }
++
++ QColor QtColorLine::color() const
++ {
++ return d_ptr->color();
++ }
++
++ void QtColorLine::setColorComponent(QtColorLine::ColorComponent component)
++ {
++ d_ptr->setColorComponent(component);
++ }
++
++ QtColorLine::ColorComponent QtColorLine::colorComponent() const
++ {
++ return d_ptr->colorComponent();
++ }
++
++ void QtColorLine::setIndicatorSize(int size)
++ {
++ d_ptr->setIndicatorSize(size);
++ }
++
++ int QtColorLine::indicatorSize() const
++ {
++ return d_ptr->indicatorSize();
++ }
++
++ void QtColorLine::setIndicatorSpace(int space)
++ {
++ d_ptr->setIndicatorSpace(space);
++ }
++
++ int QtColorLine::indicatorSpace() const
++ {
++ return d_ptr->indicatorSpace();
++ }
++
++ void QtColorLine::setFlip(bool flip)
++ {
++ d_ptr->setFlip(flip);
++ }
++
++ bool QtColorLine::flip() const
++ {
++ return d_ptr->flip();
++ }
++
++ void QtColorLine::setBackgroundCheckered(bool checkered)
++ {
++ d_ptr->setBackgroundCheckered(checkered);
++ }
++
++ bool QtColorLine::isBackgroundCheckered() const
++ {
++ return d_ptr->isBackgroundCheckered();
++ }
++
++ void QtColorLine::setOrientation(Qt::Orientation orientation)
++ {
++ d_ptr->setOrientation(orientation);
++ }
++
++ Qt::Orientation QtColorLine::orientation() const
++ {
++ return d_ptr->orientation();
++ }
++ void QtColorLine::resizeEvent(QResizeEvent *event)
++ {
++ d_ptr->resizeEvent(event);
++ }
++
++ void QtColorLine::paintEvent(QPaintEvent *event)
++ {
++ d_ptr->paintEvent(event);
++ }
++
++ void QtColorLine::mousePressEvent(QMouseEvent *event)
++ {
++ d_ptr->mousePressEvent(event);
++ }
++
++ void QtColorLine::mouseMoveEvent(QMouseEvent *event)
++ {
++ d_ptr->mouseMoveEvent(event);
++ }
++
++ void QtColorLine::mouseReleaseEvent(QMouseEvent *event)
++ {
++ d_ptr->mouseReleaseEvent(event);
++ }
++
++ void QtColorLine::mouseDoubleClickEvent(QMouseEvent *event)
++ {
++ d_ptr->mouseDoubleClickEvent(event);
++ }
++
++ QT_END_NAMESPACE