File indexing completed on 2024-05-12 16:02:07

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 2006 Sven Langkamp <sven.langkamp@gmail.com>
0003    SPDX-FileCopyrightText: 2009 Cyrille Berger <cberger@cberger.net>
0004 
0005    SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 #include "KoColorSlider.h"
0008 #include "KoColorSpace.h"
0009 
0010 #include <KoColor.h>
0011 #include <KoMixColorsOp.h>
0012 
0013 #include <QPainter>
0014 #include <QTimer>
0015 #include <QStyleOption>
0016 #include <QPointer>
0017 
0018 #define ARROWSIZE 8
0019 
0020 struct Q_DECL_HIDDEN KoColorSlider::Private
0021 {
0022     Private() : upToDate(false), displayRenderer(0) {}
0023     KoColor minColor;
0024     KoColor maxColor;
0025     QPixmap pixmap;
0026     bool upToDate;
0027     QPointer<KoColorDisplayRendererInterface> displayRenderer;
0028 };
0029 
0030 KoColorSlider::KoColorSlider(QWidget* parent, KoColorDisplayRendererInterface *displayRenderer)
0031   : KSelector(parent)
0032   , d(new Private)
0033 {
0034     setMaximum(255);
0035     d->displayRenderer = displayRenderer;
0036     connect(d->displayRenderer, SIGNAL(displayConfigurationChanged()), SLOT(update()), Qt::UniqueConnection);
0037 }
0038 
0039 KoColorSlider::KoColorSlider(Qt::Orientation o, QWidget *parent, KoColorDisplayRendererInterface *displayRenderer)
0040   : KSelector(o, parent), d(new Private)
0041 {
0042     setMaximum(255);
0043     d->displayRenderer = displayRenderer;
0044     connect(d->displayRenderer, SIGNAL(displayConfigurationChanged()), SLOT(update()), Qt::UniqueConnection);
0045 }
0046 
0047 KoColorSlider::~KoColorSlider()
0048 {
0049     delete d;
0050 }
0051 
0052 void KoColorSlider::setColors(const KoColor& mincolor, const KoColor& maxcolor)
0053 {
0054     d->minColor = mincolor;
0055     d->maxColor = maxcolor;
0056     d->upToDate = false;
0057     QTimer::singleShot(1, this, SLOT(update()));
0058 }
0059 
0060 void KoColorSlider::drawContents( QPainter *painter )
0061 {
0062     QPixmap checker(8, 8);
0063     QPainter p(&checker);
0064     p.fillRect(0, 0, 4, 4, Qt::lightGray);
0065     p.fillRect(4, 0, 4, 4, Qt::darkGray);
0066     p.fillRect(0, 4, 4, 4, Qt::darkGray);
0067     p.fillRect(4, 4, 4, 4, Qt::lightGray);
0068     p.end();
0069     QRect contentsRect_(contentsRect());
0070     painter->fillRect(contentsRect_, QBrush(checker));
0071 
0072     if( !d->upToDate || d->pixmap.isNull() || d->pixmap.width() != contentsRect_.width()
0073         || d->pixmap.height() != contentsRect_.height() )
0074     {
0075         KoColor c = d->minColor; // smart way to fetch colorspace
0076         QColor color;
0077 
0078         const quint8 *colors[2];
0079         colors[0] = d->minColor.data();
0080         colors[1] = d->maxColor.data();
0081 
0082         KoMixColorsOp * mixOp = c.colorSpace()->mixColorsOp();
0083         Q_ASSERT(mixOp);
0084         QImage image(contentsRect_.width(), contentsRect_.height(), QImage::Format_ARGB32 );
0085 
0086         if( orientation() == Qt::Horizontal ) {
0087             for (int x = 0; x < contentsRect_.width(); x++) {
0088 
0089                 qreal t = static_cast<qreal>(x) / (contentsRect_.width() - 1);
0090 
0091                 qint16 colorWeights[2];
0092                 colorWeights[0] = static_cast<quint8>((1.0 - t) * 255 + 0.5);
0093                 colorWeights[1] = 255 - colorWeights[0];
0094 
0095                 mixOp->mixColors(colors, colorWeights, 2, c.data());
0096 
0097                 if (d->displayRenderer) {
0098                     color = d->displayRenderer->toQColor(c);
0099                 }
0100                 else {
0101                     color = c.toQColor();
0102                 }
0103 
0104                 for (int y = 0; y < contentsRect_.height(); y++)
0105                 image.setPixel(x, y, color.rgba());
0106             }
0107         }
0108         else {
0109             for (int y = 0; y < contentsRect_.height(); y++) {
0110 
0111                 qreal t = static_cast<qreal>(y) / (contentsRect_.height() - 1);
0112 
0113                 qint16 colorWeights[2];
0114                 colorWeights[0] = static_cast<quint8>((t) * 255 + 0.5);
0115                 colorWeights[1] = 255 - colorWeights[0];
0116 
0117                 mixOp->mixColors(colors, colorWeights, 2, c.data());
0118 
0119                 if (d->displayRenderer) {
0120                     color = d->displayRenderer->toQColor(c);
0121                 }
0122                 else {
0123                     color = c.toQColor();
0124                 }
0125 
0126                 for (int x = 0; x < contentsRect_.width(); x++)
0127                 image.setPixel(x, y, color.rgba());
0128             }
0129         }
0130         d->pixmap = QPixmap::fromImage(image);
0131         d->upToDate = true;
0132     }
0133     painter->drawPixmap( contentsRect_, d->pixmap, QRect( 0, 0, d->pixmap.width(), d->pixmap.height()) );
0134 }
0135 
0136 KoColor KoColorSlider::currentColor() const
0137 {
0138     const quint8 *colors[2];
0139     colors[0] = d->minColor.data();
0140     colors[1] = d->maxColor.data();
0141     KoMixColorsOp * mixOp = d->minColor.colorSpace()->mixColorsOp();
0142     KoColor c(d->minColor.colorSpace());
0143     qint16 weights[2];
0144     weights[1] = (value() - minimum()) / qreal(maximum() - minimum()) * 255;
0145     weights[0] = 255 - weights[1];
0146     mixOp->mixColors(colors, weights, 2, c.data());
0147     return c;
0148 }
0149 
0150 void KoColorSlider::drawArrow(QPainter *painter, const QPoint &pos)
0151 {
0152     painter->setPen(QPen(palette().text().color(), 0));
0153     painter->setBrush(palette().text());
0154 
0155     QStyleOption o;
0156     o.initFrom(this);
0157     o.state &= ~QStyle::State_MouseOver;
0158 
0159     if ( orientation() == Qt::Vertical ) {
0160         o.rect = QRect( pos.x(), pos.y() - ARROWSIZE / 2,
0161                         ARROWSIZE, ARROWSIZE );
0162     } else {
0163         o.rect = QRect( pos.x() - ARROWSIZE / 2, pos.y(),
0164                         ARROWSIZE, ARROWSIZE );
0165     }
0166 
0167     QStyle::PrimitiveElement arrowPE;
0168     switch (arrowDirection()) {
0169     case Qt::UpArrow:
0170         arrowPE = QStyle::PE_IndicatorArrowUp;
0171         break;
0172     case Qt::DownArrow:
0173         arrowPE = QStyle::PE_IndicatorArrowDown;
0174         break;
0175     case Qt::RightArrow:
0176         arrowPE = QStyle::PE_IndicatorArrowRight;
0177         break;
0178     case Qt::LeftArrow:
0179     default:
0180         arrowPE = QStyle::PE_IndicatorArrowLeft;
0181         break;
0182     }
0183 
0184     style()->drawPrimitive(arrowPE, &o, painter, this);
0185 
0186 }