File indexing completed on 2024-05-19 04:29:29
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com> 0003 * SPDX-FileCopyrightText: 2022 Mathias Wein <lynx.mw+kde@gmail.com> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 #include "KisVisualColorSelector.h" 0008 0009 #include <QVector4D> 0010 #include <QList> 0011 #include <QPointer> 0012 0013 #include <KSharedConfig> 0014 #include <KConfigGroup> 0015 0016 #include "KoColorDisplayRendererInterface.h" 0017 #include <KoColorModelStandardIds.h> 0018 //#include <QPointer> 0019 #include "kis_signal_compressor.h" 0020 #include "kis_debug.h" 0021 0022 #include "KisVisualColorSelectorShape.h" 0023 #include "KisVisualDiamondSelectorShape.h" 0024 #include "KisVisualRectangleSelectorShape.h" 0025 #include "KisVisualTriangleSelectorShape.h" 0026 #include "KisVisualEllipticalSelectorShape.h" 0027 0028 struct KisVisualColorSelector::Private 0029 { 0030 QList<KisVisualColorSelectorShape*> widgetlist; 0031 bool acceptTabletEvents {false}; 0032 bool circular {false}; 0033 bool proofColors {false}; 0034 bool initialized {false}; 0035 bool useACSConfig {true}; 0036 bool autoAdjustExposure {true}; 0037 int colorChannelCount {0}; 0038 int minimumSliderWidth {16}; 0039 Qt::Edge sliderPosition {Qt::LeftEdge}; 0040 qreal stretchLimit {1.5}; 0041 QVector4D channelValues; 0042 KisVisualColorSelector::RenderMode renderMode {RenderMode::DynamicBackground}; 0043 KisColorSelectorConfiguration acs_config; 0044 KisSignalCompressor *updateTimer {0}; 0045 KisVisualColorModelSP selectorModel; 0046 QPointer<const KoColorDisplayRendererInterface> displayRenderer; 0047 KoGamutMaskSP gamutMask; 0048 }; 0049 0050 KisVisualColorSelector::KisVisualColorSelector(QWidget *parent, KisVisualColorModelSP model) 0051 : KisColorSelectorInterface(parent) 0052 , m_d(new Private) 0053 { 0054 m_d->acs_config = validatedConfiguration(KisColorSelectorConfiguration()); 0055 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0056 0057 loadACSConfig(); 0058 if (model) { 0059 setSelectorModel(model); 0060 } else { 0061 setSelectorModel(KisVisualColorModelSP(new KisVisualColorModel)); 0062 m_d->selectorModel->slotLoadACSConfig(); 0063 } 0064 0065 m_d->updateTimer = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE); 0066 connect(m_d->updateTimer, SIGNAL(timeout()), SLOT(slotReloadConfiguration()), Qt::UniqueConnection); 0067 } 0068 0069 KisVisualColorSelector::~KisVisualColorSelector() 0070 { 0071 delete m_d->updateTimer; 0072 } 0073 0074 QSize KisVisualColorSelector::minimumSizeHint() const 0075 { 0076 return QSize(75, 75); 0077 } 0078 0079 void KisVisualColorSelector::setSelectorModel(KisVisualColorModelSP model) 0080 { 0081 if (model == m_d->selectorModel) { 0082 return; 0083 } 0084 if (m_d->selectorModel) { 0085 m_d->selectorModel->disconnect(this); 0086 } 0087 connect(model.data(), SIGNAL(sigChannelValuesChanged(QVector4D,quint32)), 0088 SLOT(slotChannelValuesChanged(QVector4D,quint32))); 0089 connect(model.data(), SIGNAL(sigColorModelChanged()), SLOT(slotColorModelChanged())); 0090 connect(model.data(), SIGNAL(sigColorSpaceChanged()), SLOT(slotColorSpaceChanged())); 0091 // to keep the KisColorSelectorInterface API functional: 0092 connect(model.data(), SIGNAL(sigNewColor(KoColor)), this, SIGNAL(sigNewColor(KoColor))); 0093 m_d->selectorModel = model; 0094 m_d->initialized = false; 0095 rebuildSelector(); 0096 } 0097 0098 KisVisualColorModelSP KisVisualColorSelector::selectorModel() const 0099 { 0100 return m_d->selectorModel; 0101 } 0102 0103 void KisVisualColorSelector::setConfig(bool forceCircular, bool forceSelfUpdate) 0104 { 0105 Q_UNUSED(forceSelfUpdate); 0106 if (forceCircular != m_d->circular) { 0107 m_d->circular = forceCircular; 0108 m_d->initialized = false; 0109 rebuildSelector(); 0110 } 0111 } 0112 0113 const KisColorSelectorConfiguration &KisVisualColorSelector::configuration() const 0114 { 0115 return m_d->acs_config; 0116 } 0117 0118 void KisVisualColorSelector::setConfiguration(const KisColorSelectorConfiguration *config) 0119 { 0120 m_d->useACSConfig = !config; 0121 if (config) { 0122 // applies immediately, while signalled rebuilds from krita configuration changes 0123 // are queued, so make sure we cancel queued updates 0124 m_d->updateTimer->stop(); 0125 KisColorSelectorConfiguration configNew = validatedConfiguration(*config); 0126 if (configNew != m_d->acs_config) { 0127 m_d->acs_config = configNew; 0128 m_d->initialized = false; 0129 rebuildSelector(); 0130 } 0131 } else { 0132 m_d->initialized = false; 0133 m_d->updateTimer->start(); 0134 } 0135 } 0136 0137 void KisVisualColorSelector::setAcceptTabletEvents(bool on) 0138 { 0139 m_d->acceptTabletEvents = on; 0140 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0141 shape->setAcceptTabletEvents(on); 0142 } 0143 } 0144 0145 KoColor KisVisualColorSelector::getCurrentColor() const 0146 { 0147 if (m_d->selectorModel) { 0148 return m_d->selectorModel->currentColor(); 0149 } 0150 return KoColor(); 0151 } 0152 0153 void KisVisualColorSelector::setMinimumSliderWidth(int width) 0154 { 0155 int newWidth = qMax(5, width); 0156 if (newWidth != m_d->minimumSliderWidth) { 0157 m_d->minimumSliderWidth = width; 0158 KisVisualColorSelector::resizeEvent(0); 0159 } 0160 } 0161 0162 const KoColorDisplayRendererInterface *KisVisualColorSelector::displayRenderer() const 0163 { 0164 return m_d->displayRenderer ? m_d->displayRenderer : KoDumbColorDisplayRenderer::instance(); 0165 } 0166 0167 KisVisualColorSelector::RenderMode KisVisualColorSelector::renderMode() const 0168 { 0169 return m_d->renderMode; 0170 } 0171 0172 void KisVisualColorSelector::setRenderMode(KisVisualColorSelector::RenderMode mode) 0173 { 0174 if (mode != m_d->renderMode) { 0175 m_d->renderMode = mode; 0176 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0177 shape->forceImageUpdate(); 0178 shape->update(); 0179 } 0180 } 0181 } 0182 0183 bool KisVisualColorSelector::autoAdjustExposure() const 0184 { 0185 return m_d->autoAdjustExposure; 0186 } 0187 0188 void KisVisualColorSelector::setAutoAdjustExposure(bool enabled) 0189 { 0190 m_d->autoAdjustExposure = enabled; 0191 } 0192 0193 bool KisVisualColorSelector::proofColors() const 0194 { 0195 return m_d->proofColors; 0196 } 0197 0198 void KisVisualColorSelector::setProofColors(bool enabled) 0199 { 0200 if (enabled != m_d->proofColors) { 0201 m_d->proofColors = enabled; 0202 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0203 shape->forceImageUpdate(); 0204 shape->update(); 0205 } 0206 } 0207 } 0208 0209 void KisVisualColorSelector::setSliderPosition(Qt::Edge edge) 0210 { 0211 if (edge != Qt::TopEdge && edge != Qt::LeftEdge) { 0212 return; 0213 } 0214 0215 if (edge != m_d->sliderPosition) { 0216 m_d->sliderPosition = edge; 0217 rebuildSelector(); 0218 } 0219 } 0220 0221 KoGamutMask *KisVisualColorSelector::activeGamutMask() const 0222 { 0223 return m_d->gamutMask.data(); 0224 } 0225 0226 void KisVisualColorSelector::slotSetColor(const KoColor &c) 0227 { 0228 if (m_d->selectorModel) { 0229 m_d->selectorModel->slotSetColor(c); 0230 } 0231 } 0232 0233 void KisVisualColorSelector::slotSetColorSpace(const KoColorSpace *cs) 0234 { 0235 if (m_d->selectorModel) { 0236 m_d->selectorModel->slotSetColorSpace(cs); 0237 } 0238 } 0239 0240 void KisVisualColorSelector::slotConfigurationChanged() 0241 { 0242 if (m_d->updateTimer && m_d->useACSConfig) { 0243 // NOTE: this timer is because notifyConfigChanged() is only called 0244 // via KisConfig::setCustomColorSelectorColorSpace(), but at this point 0245 // Advanced Color Selector has not written the relevant config values yet. 0246 m_d->initialized = false; 0247 m_d->updateTimer->start(); 0248 } 0249 } 0250 0251 void KisVisualColorSelector::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) 0252 { 0253 switchDisplayRenderer(displayRenderer); 0254 0255 if (m_d->selectorModel) { 0256 slotDisplayConfigurationChanged(); 0257 } 0258 } 0259 0260 void KisVisualColorSelector::slotGamutMaskChanged(KoGamutMaskSP mask) 0261 { 0262 // Note: KisCanvasResourceProvider currently does not distinguish 0263 // between activating, switching and property changes of a gamut mask 0264 m_d->gamutMask = mask; 0265 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0266 shape->updateGamutMask(); 0267 } 0268 } 0269 0270 void KisVisualColorSelector::slotGamutMaskUnset() 0271 { 0272 m_d->gamutMask.clear(); 0273 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0274 shape->updateGamutMask(); 0275 } 0276 } 0277 0278 void KisVisualColorSelector::slotGamutMaskPreviewUpdate() 0279 { 0280 // Shapes currently always requests preview shapes if available, so more of the same... 0281 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0282 shape->updateGamutMask(); 0283 } 0284 } 0285 0286 void KisVisualColorSelector::slotChannelValuesChanged(const QVector4D &values, quint32 channelFlags) 0287 { 0288 // about to (re-)build selector, values will be fetched when done 0289 if (!m_d->initialized) { 0290 return; 0291 } 0292 m_d->channelValues = values; 0293 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0294 shape->setChannelValues(m_d->channelValues, channelFlags); 0295 } 0296 } 0297 0298 void KisVisualColorSelector::slotColorModelChanged() 0299 { 0300 // TODO: triangle <=> diamond switch only happens on HSV <=> non-HSV, but 0301 // the previous color model is not accessible right now 0302 if (!m_d->initialized || m_d->selectorModel->colorChannelCount() != m_d->colorChannelCount 0303 || m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { 0304 m_d->initialized = false; 0305 rebuildSelector(); 0306 } else { 0307 slotDisplayConfigurationChanged(); 0308 } 0309 } 0310 0311 void KisVisualColorSelector::slotColorSpaceChanged() 0312 { 0313 if (m_d->autoAdjustExposure && m_d->selectorModel && m_d->selectorModel->supportsExposure()) { 0314 m_d->selectorModel->setMaxChannelValues(calculateMaxChannelValues()); 0315 } 0316 } 0317 0318 void KisVisualColorSelector::slotCursorMoved(QPointF pos) 0319 { 0320 const KisVisualColorSelectorShape *shape = qobject_cast<KisVisualColorSelectorShape *>(sender()); 0321 KIS_SAFE_ASSERT_RECOVER_RETURN(shape); 0322 0323 m_d->channelValues[shape->channel(0)] = pos.x(); 0324 if (shape->getDimensions() == KisVisualColorSelectorShape::twodimensional) { 0325 m_d->channelValues[shape->channel(1)] = pos.y(); 0326 } 0327 0328 for (KisVisualColorSelectorShape *widget : qAsConst(m_d->widgetlist)) { 0329 if (widget != shape){ 0330 widget->setChannelValues(m_d->channelValues, shape->channelMask()); 0331 } 0332 } 0333 m_d->selectorModel->slotSetChannelValues(m_d->channelValues); 0334 } 0335 0336 void KisVisualColorSelector::slotDisplayConfigurationChanged() 0337 { 0338 if (m_d->autoAdjustExposure && m_d->selectorModel && m_d->selectorModel->supportsExposure()) { 0339 m_d->selectorModel->setMaxChannelValues(calculateMaxChannelValues()); 0340 } 0341 // TODO: can we be smarter about forced updates? 0342 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0343 shape->forceImageUpdate(); 0344 shape->update(); 0345 } 0346 } 0347 0348 void KisVisualColorSelector::slotReloadConfiguration() 0349 { 0350 if (m_d->useACSConfig) { 0351 loadACSConfig(); 0352 // this may trigger slotColorModelChanged() so check afterwards if we already rebuild 0353 m_d->selectorModel->slotLoadACSConfig(); 0354 if (!m_d->initialized) { 0355 rebuildSelector(); 0356 } 0357 } 0358 } 0359 0360 void KisVisualColorSelector::rebuildSelector() 0361 { 0362 qDeleteAll(m_d->widgetlist); 0363 m_d->widgetlist.clear(); 0364 0365 if (!m_d->selectorModel || m_d->selectorModel->colorModel() == KisVisualColorModel::None) { 0366 return; 0367 } 0368 0369 m_d->colorChannelCount = m_d->selectorModel->colorChannelCount(); 0370 0371 //recreate all the widgets. 0372 0373 if (m_d->colorChannelCount == 1) { 0374 0375 KisVisualColorSelectorShape *bar; 0376 0377 if (m_d->circular) { 0378 bar = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::onedimensional, 0379 0, 0, 20, KisVisualEllipticalSelectorShape::borderMirrored); 0380 } 0381 else { 0382 bar = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::onedimensional, 0383 0, 0, 20); 0384 } 0385 0386 connect(bar, SIGNAL(sigCursorMoved(QPointF)), SLOT(slotCursorMoved(QPointF))); 0387 m_d->widgetlist.append(bar); 0388 } 0389 else if (m_d->colorChannelCount == 3) { 0390 int channel1 = 0; 0391 int channel2 = 1; 0392 int channel3 = 2; 0393 0394 switch(m_d->acs_config.subTypeParameter) 0395 { 0396 case KisColorSelectorConfiguration::H: 0397 case KisColorSelectorConfiguration::Hluma: 0398 channel1 = 0; 0399 break; 0400 case KisColorSelectorConfiguration::hsvS: 0401 channel1 = 1; 0402 break; 0403 case KisColorSelectorConfiguration::V: 0404 channel1 = 2; 0405 break; 0406 default: 0407 Q_ASSERT_X(false, "", "Invalid acs_config.subTypeParameter"); 0408 } 0409 0410 switch(m_d->acs_config.mainTypeParameter) 0411 { 0412 case KisColorSelectorConfiguration::hsvSH: 0413 channel2 = 0; 0414 channel3 = 1; 0415 break; 0416 case KisColorSelectorConfiguration::VH: 0417 channel2 = 0; 0418 channel3 = 2; 0419 break; 0420 case KisColorSelectorConfiguration::SV: 0421 channel2 = 1; 0422 channel3 = 2; 0423 break; 0424 default: 0425 Q_ASSERT_X(false, "", "Invalid acs_config.mainTypeParameter"); 0426 } 0427 0428 KisVisualColorSelectorShape *bar; 0429 if (m_d->acs_config.subType == KisColorSelectorConfiguration::Ring) { 0430 bar = new KisVisualEllipticalSelectorShape(this, 0431 KisVisualColorSelectorShape::onedimensional, 0432 channel1, channel1, 20, 0433 KisVisualEllipticalSelectorShape::border); 0434 } 0435 else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular == false) { 0436 KisVisualRectangleSelectorShape::singelDTypes orientation = useHorizontalSlider() ? 0437 KisVisualRectangleSelectorShape::horizontal : KisVisualRectangleSelectorShape::vertical; 0438 0439 bar = new KisVisualRectangleSelectorShape(this, 0440 KisVisualColorSelectorShape::onedimensional, 0441 channel1, channel1, 20, orientation); 0442 } 0443 else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular == true) { 0444 bar = new KisVisualEllipticalSelectorShape(this, 0445 KisVisualColorSelectorShape::onedimensional, 0446 channel1, channel1, 0447 20, KisVisualEllipticalSelectorShape::borderMirrored); 0448 } else { 0449 // Accessing bar below would crash since it's not initialized. 0450 // Hopefully this can never happen. 0451 warnUI << "Invalid subType, cannot initialize KisVisualColorSelectorShape"; 0452 Q_ASSERT_X(false, "", "Invalid subType, cannot initialize KisVisualColorSelectorShape"); 0453 return; 0454 } 0455 0456 m_d->widgetlist.append(bar); 0457 0458 KisVisualColorSelectorShape *block; 0459 if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { 0460 if (m_d->selectorModel->colorModel() == KisVisualColorModel::HSV) { 0461 block = new KisVisualTriangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, 0462 channel2, channel3); 0463 } else { 0464 block = new KisVisualDiamondSelectorShape(this, KisVisualColorSelectorShape::twodimensional, 0465 channel2, channel3); 0466 } 0467 } 0468 else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Square) { 0469 block = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, 0470 channel2, channel3); 0471 } 0472 else { 0473 block = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::twodimensional, 0474 channel2, channel3); 0475 } 0476 0477 connect(bar, SIGNAL(sigCursorMoved(QPointF)), SLOT(slotCursorMoved(QPointF))); 0478 connect(block, SIGNAL(sigCursorMoved(QPointF)), SLOT(slotCursorMoved(QPointF))); 0479 m_d->widgetlist.append(block); 0480 } 0481 else if (m_d->colorChannelCount == 4) { 0482 KisVisualRectangleSelectorShape *block = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional, 0, 1); 0483 KisVisualRectangleSelectorShape *block2 = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional, 2, 3); 0484 connect(block, SIGNAL(sigCursorMoved(QPointF)), SLOT(slotCursorMoved(QPointF))); 0485 connect(block2, SIGNAL(sigCursorMoved(QPointF)), SLOT(slotCursorMoved(QPointF))); 0486 m_d->widgetlist.append(block); 0487 m_d->widgetlist.append(block2); 0488 } 0489 0490 m_d->initialized = true; 0491 // make sure we call "our" resize function 0492 KisVisualColorSelector::resizeEvent(0); 0493 0494 for (KisVisualColorSelectorShape *shape : qAsConst(m_d->widgetlist)) { 0495 shape->setAcceptTabletEvents(m_d->acceptTabletEvents); 0496 // if this widget is currently visible, new children are hidden by default 0497 shape->show(); 0498 } 0499 0500 // finally update widgets with new channel values 0501 slotChannelValuesChanged(m_d->selectorModel->channelValues(), (1u << m_d->colorChannelCount) - 1); 0502 } 0503 0504 void KisVisualColorSelector::resizeEvent(QResizeEvent *) 0505 { 0506 if (!m_d->selectorModel || !m_d->initialized) { 0507 KIS_SAFE_ASSERT_RECOVER_NOOP(m_d->widgetlist.isEmpty() || !m_d->initialized); 0508 return; 0509 } 0510 int sizeValue = qMin(width(), height()); 0511 // due to masking/antialiasing, the visible width is ~4 pixels less, so add them here 0512 const int margin = 4; 0513 const qreal sliderRatio = 0.09; 0514 int borderWidth = qMax(int(sizeValue * sliderRatio), m_d->minimumSliderWidth) + margin; 0515 QRect newrect(0,0, this->geometry().width(), this->geometry().height()); 0516 0517 if (m_d->colorChannelCount == 1) { 0518 if (m_d->circular) { 0519 m_d->widgetlist.at(0)->resize(sizeValue, sizeValue); 0520 } 0521 else { 0522 KisVisualRectangleSelectorShape *slider = qobject_cast<KisVisualRectangleSelectorShape *>(m_d->widgetlist.at(0)); 0523 KIS_SAFE_ASSERT_RECOVER_RETURN(slider); 0524 if (useHorizontalSlider()) { 0525 int sliderWidth = qMax(width()/10, m_d->minimumSliderWidth); 0526 sliderWidth = qMin(sliderWidth, height()); 0527 int y = (height() - sliderWidth)/2; 0528 slider->setOneDimensionalType(KisVisualRectangleSelectorShape::horizontal); 0529 slider->setGeometry(0, y, width(), sliderWidth); 0530 } 0531 else { 0532 // vertical slider 0533 int sliderWidth = qMax(height()/10, m_d->minimumSliderWidth); 0534 sliderWidth = qMin(sliderWidth, width()); 0535 int x = (width() - sliderWidth)/2; 0536 slider->setOneDimensionalType(KisVisualRectangleSelectorShape::vertical); 0537 slider->setGeometry(x, 0, sliderWidth, height()); 0538 } 0539 } 0540 } 0541 else if (m_d->colorChannelCount == 3) { 0542 m_d->widgetlist.at(0)->setBorderWidth(borderWidth); 0543 // Ring 0544 if (m_d->acs_config.subType == KisColorSelectorConfiguration::Ring || 0545 (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular)) { 0546 0547 m_d->widgetlist.at(0)->setGeometry((width() - sizeValue)/2, (height() - sizeValue)/2, 0548 sizeValue, sizeValue); 0549 } 0550 // Slider Bar 0551 else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider) { 0552 // limit stretch; only vertical slider currently 0553 if (useHorizontalSlider()) { 0554 newrect.setWidth(qMin(newrect.width(), qRound((newrect.height() - borderWidth) * m_d->stretchLimit))); 0555 newrect.setHeight(qMin(newrect.height(), qRound(sizeValue * m_d->stretchLimit + borderWidth))); 0556 0557 m_d->widgetlist.at(0)->setGeometry(0, 0, newrect.width(), borderWidth); 0558 } 0559 else { 0560 newrect.setWidth(qMin(newrect.width(), qRound(sizeValue * m_d->stretchLimit + borderWidth))); 0561 newrect.setHeight(qMin(newrect.height(), qRound((newrect.width() - borderWidth) * m_d->stretchLimit))); 0562 0563 m_d->widgetlist.at(0)->setGeometry(0, 0, borderWidth, newrect.height()); 0564 } 0565 0566 } 0567 0568 if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { 0569 if (m_d->selectorModel->colorModel() == KisVisualColorModel::HSV) { 0570 m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForTriangle(newrect)); 0571 } else { 0572 m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForCircle(newrect)); 0573 } 0574 } 0575 else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Square) { 0576 m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForSquare(newrect)); 0577 } 0578 else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Wheel) { 0579 m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForCircle(newrect)); 0580 } 0581 // center horizontally 0582 QRect boundRect(m_d->widgetlist.at(0)->geometry() | m_d->widgetlist.at(1)->geometry()); 0583 int offset = (width() - boundRect.width()) / 2 - boundRect.left(); 0584 m_d->widgetlist.at(0)->move(m_d->widgetlist.at(0)->pos() + QPoint(offset, 0)); 0585 m_d->widgetlist.at(1)->move(m_d->widgetlist.at(1)->pos() + QPoint(offset, 0)); 0586 } 0587 else if (m_d->colorChannelCount == 4) { 0588 int sizeBlock = qMin(width()/2 - 8, height()); 0589 m_d->widgetlist.at(0)->setGeometry(0, 0, sizeBlock, sizeBlock); 0590 m_d->widgetlist.at(1)->setGeometry(sizeBlock + 8, 0, sizeBlock, sizeBlock); 0591 } 0592 } 0593 0594 bool KisVisualColorSelector::useHorizontalSlider() 0595 { 0596 if (m_d->colorChannelCount == 1) { 0597 return width() > height(); 0598 } 0599 else { 0600 return m_d->sliderPosition == Qt::TopEdge; 0601 } 0602 } 0603 0604 void KisVisualColorSelector::switchDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) 0605 { 0606 if (displayRenderer != m_d->displayRenderer) { 0607 if (m_d->displayRenderer) { 0608 m_d->displayRenderer->disconnect(this); 0609 } 0610 if (displayRenderer) { 0611 connect(displayRenderer, SIGNAL(displayConfigurationChanged()), 0612 SLOT(slotDisplayConfigurationChanged()), Qt::UniqueConnection); 0613 } 0614 m_d->displayRenderer = displayRenderer; 0615 } 0616 } 0617 0618 QVector4D KisVisualColorSelector::calculateMaxChannelValues() 0619 { 0620 // Note: This calculation only makes sense for HDR color spaces 0621 QVector4D maxChannelValues = QVector4D(1, 1, 1, 1); 0622 const QList<KoChannelInfo *> channels = m_d->selectorModel->colorSpace()->channels(); 0623 0624 for (int i = 0; i < channels.size(); i++) { 0625 const KoChannelInfo *channel = channels.at(i); 0626 if (channel->channelType() != KoChannelInfo::ALPHA) { 0627 quint32 logical = channel->displayPosition(); 0628 if (logical > m_d->selectorModel->colorSpace()->alphaPos()) { 0629 --logical; 0630 } 0631 maxChannelValues[logical] = displayRenderer()->maxVisibleFloatValue(channel); 0632 } 0633 } 0634 0635 return maxChannelValues; 0636 } 0637 0638 void KisVisualColorSelector::loadACSConfig() 0639 { 0640 KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); 0641 KisColorSelectorConfiguration raw_config = KisColorSelectorConfiguration::fromString( 0642 cfg.readEntry("colorSelectorConfiguration", KisColorSelectorConfiguration().toString())); 0643 m_d->acs_config = validatedConfiguration(raw_config); 0644 } 0645 0646 KisColorSelectorConfiguration KisVisualColorSelector::validatedConfiguration(const KisColorSelectorConfiguration &cfg) 0647 { 0648 KisColorSelectorConfiguration validated(cfg); 0649 bool ok = true; 0650 0651 switch (validated.mainType) { 0652 case KisColorSelectorConfiguration::Triangle: 0653 case KisColorSelectorConfiguration::Square: 0654 case KisColorSelectorConfiguration::Wheel: 0655 break; 0656 default: 0657 ok = false; 0658 } 0659 0660 switch (validated.subType) { 0661 case KisColorSelectorConfiguration::Ring: 0662 case KisColorSelectorConfiguration::Slider: 0663 break; 0664 default: 0665 ok = false; 0666 } 0667 0668 switch(validated.subTypeParameter) 0669 { 0670 case KisColorSelectorConfiguration::H: 0671 case KisColorSelectorConfiguration::hsvS: 0672 case KisColorSelectorConfiguration::V: 0673 break; 0674 // translate to HSV 0675 case KisColorSelectorConfiguration::hsyS: 0676 case KisColorSelectorConfiguration::hsiS: 0677 case KisColorSelectorConfiguration::hslS: 0678 validated.subTypeParameter = KisColorSelectorConfiguration::hsvS; 0679 break; 0680 case KisColorSelectorConfiguration::L: 0681 case KisColorSelectorConfiguration::I: 0682 case KisColorSelectorConfiguration::Y: 0683 validated.subTypeParameter = KisColorSelectorConfiguration::V; 0684 break; 0685 default: 0686 ok = false; 0687 } 0688 0689 switch(validated.mainTypeParameter) 0690 { 0691 case KisColorSelectorConfiguration::SV: 0692 case KisColorSelectorConfiguration::hsvSH: 0693 case KisColorSelectorConfiguration::VH: 0694 break; 0695 // translate to HSV 0696 case KisColorSelectorConfiguration::SL: 0697 case KisColorSelectorConfiguration::SV2: 0698 case KisColorSelectorConfiguration::SI: 0699 case KisColorSelectorConfiguration::SY: 0700 validated.mainTypeParameter = KisColorSelectorConfiguration::SV; 0701 break; 0702 case KisColorSelectorConfiguration::hslSH: 0703 case KisColorSelectorConfiguration::hsiSH: 0704 case KisColorSelectorConfiguration::hsySH: 0705 validated.mainTypeParameter = KisColorSelectorConfiguration::hsvSH; 0706 break; 0707 case KisColorSelectorConfiguration::LH: 0708 case KisColorSelectorConfiguration::IH: 0709 case KisColorSelectorConfiguration::YH: 0710 validated.mainTypeParameter = KisColorSelectorConfiguration::VH; 0711 break; 0712 default: 0713 ok = false; 0714 } 0715 0716 if (ok) { 0717 return validated; 0718 } 0719 return KisColorSelectorConfiguration(KisColorSelectorConfiguration::Triangle, 0720 KisColorSelectorConfiguration::Ring, 0721 KisColorSelectorConfiguration::SV, 0722 KisColorSelectorConfiguration::H); 0723 }