File indexing completed on 2024-06-16 04:16:02
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Adam Celarek <kdedev at xibo dot at> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "kis_shade_selector_line.h" 0008 0009 #include <QPainter> 0010 #include <QColor> 0011 #include <QMouseEvent> 0012 0013 #include <cmath> 0014 0015 #include <ksharedconfig.h> 0016 #include <kconfig.h> 0017 #include <kconfiggroup.h> 0018 #include <klocalizedstring.h> 0019 #include <KoColorSpaceRegistry.h> 0020 0021 #include "kis_canvas2.h" 0022 0023 #include "kis_color_selector_base_proxy.h" 0024 #include "kis_display_color_converter.h" 0025 #include "kis_paint_device.h" 0026 0027 0028 KisShadeSelectorLine::KisShadeSelectorLine(KisColorSelectorBaseProxy *parentProxy, 0029 QWidget *parent) 0030 : KisShadeSelectorLineBase(parent), 0031 m_cachedColorSpace(0), 0032 m_displayHelpText(false), 0033 m_parentProxy(parentProxy) 0034 { 0035 setParam(0, 0, 0, 0, 0, 0); 0036 updateSettings(); 0037 setMouseTracking(true); 0038 m_mouseX=width()/2; 0039 m_isDown=false; 0040 } 0041 0042 KisShadeSelectorLine::KisShadeSelectorLine(qreal hueDelta, qreal satDelta, qreal valDelta, 0043 KisColorSelectorBaseProxy *parentProxy, QWidget *parent, qreal hueShift, qreal satShift, qreal valShift) : 0044 KisShadeSelectorLineBase(parent), 0045 m_cachedColorSpace(0), 0046 m_displayHelpText(false), 0047 m_parentProxy(parentProxy) 0048 { 0049 setParam(hueDelta, satDelta, valDelta, hueShift, satShift, valShift); 0050 updateSettings(); 0051 m_mouseX=width()/2; 0052 m_isDown=false; 0053 } 0054 0055 KisShadeSelectorLine::~KisShadeSelectorLine() 0056 { 0057 } 0058 0059 void KisShadeSelectorLine::setParam(qreal hueDelta, qreal satDelta, qreal valDelta, qreal hueShift, qreal satShift, qreal valShift) 0060 { 0061 m_hueDelta = hueDelta; 0062 m_saturationDelta = satDelta; 0063 m_valueDelta = valDelta; 0064 0065 m_hueShift = hueShift; 0066 m_saturationShift = satShift; 0067 m_valueShift = valShift; 0068 } 0069 0070 void KisShadeSelectorLine::setColor(const KoColor &color) 0071 { 0072 m_realColor = color; 0073 m_realColor.convertTo(m_parentProxy->colorSpace()); 0074 m_mouseX=width()/2; 0075 0076 update(); 0077 } 0078 0079 void KisShadeSelectorLine::updateSettings() 0080 { 0081 KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); 0082 0083 m_gradient = cfg.readEntry("minimalShadeSelectorAsGradient", false); 0084 m_patchCount = cfg.readEntry("minimalShadeSelectorPatchCount", 10); 0085 m_lineHeight = cfg.readEntry("minimalShadeSelectorLineHeight", 20); 0086 0087 setMaximumHeight(m_lineHeight); 0088 setMinimumHeight(m_lineHeight); 0089 } 0090 0091 QString KisShadeSelectorLine::toString() const 0092 { 0093 return QString("%1|%2|%3|%4|%5|%6|%7").arg(m_lineNumber).arg(m_hueDelta).arg(m_saturationDelta).arg(m_valueDelta).arg(m_hueShift).arg(m_saturationShift).arg(m_valueShift); 0094 } 0095 0096 void KisShadeSelectorLine::fromString(const QString& string) 0097 { 0098 QStringList strili = string.split('|'); 0099 m_lineNumber = strili.at(0).toInt(); 0100 m_hueDelta = strili.at(1).toDouble(); 0101 m_saturationDelta = strili.at(2).toDouble(); 0102 m_valueDelta = strili.at(3).toDouble(); 0103 if(strili.size()==4) return; // don't crash, if reading old config files. 0104 m_hueShift = strili.at(4).toDouble(); 0105 m_saturationShift = strili.at(5).toDouble(); 0106 m_valueShift = strili.at(6).toDouble(); 0107 } 0108 0109 void KisShadeSelectorLine::paintEvent(QPaintEvent *) 0110 { 0111 0112 if (m_cachedColorSpace != m_parentProxy->colorSpace()) { 0113 m_realPixelCache = new KisPaintDevice(m_parentProxy->colorSpace()); 0114 m_cachedColorSpace = m_parentProxy->colorSpace(); 0115 } 0116 else { 0117 m_realPixelCache->clear(); 0118 } 0119 0120 int patchCount = 0; 0121 int patchSpacing = 0; 0122 int patchWidth = 0; 0123 0124 if(m_gradient) { 0125 patchCount = width(); 0126 patchSpacing = 0; 0127 patchWidth = 1; 0128 } 0129 else { 0130 patchCount = m_patchCount; 0131 patchSpacing = 3; 0132 patchWidth = std::lround((width() - patchSpacing * patchCount) / qreal(patchCount)); 0133 } 0134 qreal hueStep; 0135 qreal saturationStep; 0136 qreal valueStep; 0137 0138 if(m_gradient){ 0139 hueStep=m_hueDelta/qreal(patchCount-10); 0140 saturationStep=m_saturationDelta/qreal(patchCount-10); 0141 valueStep=m_valueDelta/qreal(patchCount-10); 0142 } 0143 else{ 0144 hueStep=m_hueDelta/qreal(patchCount); 0145 saturationStep=m_saturationDelta/qreal(patchCount); 0146 valueStep=m_valueDelta/qreal(patchCount); 0147 } 0148 0149 qreal baseHue; 0150 qreal baseSaturation; 0151 qreal baseValue; 0152 m_parentProxy->converter()-> 0153 getHsvF(m_realColor, &baseHue, &baseSaturation, &baseValue); 0154 0155 int z=0; 0156 for(int i=-patchCount/2; i<=patchCount/2; i++) { 0157 if(i==0 && patchCount%2==0) continue; 0158 qreal hue = baseHue + (i * hueStep) + m_hueShift; 0159 while (hue < 0.0) hue += 1.0; 0160 while (hue > 1.0) hue -= 1.0; 0161 0162 qreal saturation = qBound<qreal>(0., baseSaturation + (i * saturationStep) + m_saturationShift, 1.); 0163 qreal value = qBound<qreal>(0., baseValue + (i * valueStep) + m_valueShift, 1.); 0164 0165 if (qAbs(i) <= 5 && m_gradient) { 0166 hue = baseHue; 0167 saturation=baseSaturation; 0168 value=baseValue; 0169 } 0170 0171 const QRect patchRect(z * (patchWidth + patchSpacing), 0, patchWidth, m_lineHeight); 0172 KoColor patchColor = m_parentProxy->converter()->fromHsvF(hue, saturation, value); 0173 0174 patchColor.convertTo(m_realPixelCache->colorSpace()); 0175 m_realPixelCache->fill(patchRect, patchColor); 0176 0177 z++; 0178 } 0179 0180 QPainter wpainter(this); 0181 if (!isEnabled()) { 0182 wpainter.setOpacity(0.2); 0183 } 0184 const QImage renderedImage = m_parentProxy->converter()->toQImage(m_realPixelCache).scaledToWidth(m_width); 0185 wpainter.drawImage(0, 0, renderedImage); 0186 if (m_gradient) { 0187 wpainter.setPen(QColor(175,175,175)); 0188 wpainter.drawRect(renderedImage.width()/2-5,0,10,renderedImage.height()-1); 0189 wpainter.setPen(QColor(75,75,75)); 0190 wpainter.drawRect(renderedImage.width()/2-4,0,8,renderedImage.height()-1); 0191 wpainter.setPen(QColor(175,175,175)); 0192 const int mouseX = qBound(5, m_mouseX, m_width - 5); 0193 wpainter.drawRect(mouseX-5,0,10,renderedImage.height()-1); 0194 wpainter.setPen(QColor(75,75,75)); 0195 wpainter.drawRect(mouseX-4,0,8,renderedImage.height()-1); 0196 } 0197 0198 if(m_displayHelpText) { 0199 QString helpText(i18n("delta h=%1 s=%2 v=%3 shift h=%4 s=%5 v=%6", 0200 m_hueDelta, 0201 m_saturationDelta, 0202 m_valueDelta, 0203 m_hueShift, 0204 m_saturationShift, 0205 m_valueShift)); 0206 wpainter.setPen(QColor(255,255,255)); 0207 wpainter.drawText(rect(), helpText); 0208 } 0209 } 0210 0211 void KisShadeSelectorLine::resizeEvent(QResizeEvent *e) 0212 { 0213 QSize m_old = e->oldSize(); 0214 QSize m_new = e->size(); 0215 int m_nWidth = m_new.width(); 0216 int m_oWidth = m_old.width(); 0217 m_width = width(); 0218 m_mouseX = m_mouseX * m_nWidth / m_oWidth; 0219 } 0220 void KisShadeSelectorLine::mousePressEvent(QMouseEvent* e) 0221 { 0222 if(e->button()!=Qt::LeftButton && e->button()!=Qt::RightButton) { 0223 e->setAccepted(false); 0224 return; 0225 } 0226 if (e->y() > 0 && e->y() < height()) { 0227 m_parentProxy->showColorPreview(); 0228 e->accept(); 0229 m_mouseX = e->x(); 0230 m_isDown=true; 0231 update(); 0232 } 0233 } 0234 0235 void KisShadeSelectorLine::mouseMoveEvent(QMouseEvent *e) 0236 { 0237 if ((m_isDown) && (e->buttons() & Qt::LeftButton)) { 0238 m_mouseX=e->x(); 0239 const QPoint mouseEv(qBound(5, m_mouseX, m_width - 5), 5); 0240 KoColor color(Acs::sampleColor(m_realPixelCache, mouseEv)); 0241 m_parentProxy->updateColorPreview(color); 0242 update(); 0243 } 0244 } 0245 0246 void KisShadeSelectorLine::mouseReleaseEvent(QMouseEvent * e) 0247 { 0248 if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton) { 0249 e->ignore(); 0250 return; 0251 } 0252 m_mouseX=e->x(); 0253 const QPoint mouseEv(qBound(5, m_mouseX, m_width - 5), 5); 0254 KoColor color(Acs::sampleColor(m_realPixelCache, mouseEv)); 0255 m_parentProxy->updateColorPreview(color); 0256 Acs::ColorRole role = Acs::buttonToRole(e->button()); 0257 0258 KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); 0259 0260 bool onRightClick = cfg.readEntry("shadeSelectorUpdateOnRightClick", false); 0261 bool onLeftClick = cfg.readEntry("shadeSelectorUpdateOnLeftClick", false); 0262 0263 bool explicitColorReset = 0264 (e->button() == Qt::LeftButton && onLeftClick) || 0265 (e->button() == Qt::RightButton && onRightClick); 0266 0267 m_parentProxy->updateColor(color, role, explicitColorReset); 0268 e->accept(); 0269 m_isDown=false; 0270 }