File indexing completed on 2024-05-19 04:29:26
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include <QList> 0008 #include <QAbstractSpinBox> 0009 #include <QSpinBox> 0010 #include <QDoubleSpinBox> 0011 #include <QPointer> 0012 #include <QCompleter> 0013 0014 #include <functional> 0015 0016 #include <KConfigGroup> 0017 #include <kstandardguiitem.h> 0018 0019 #include "KoColorSpaceRegistry.h" 0020 #include <KoColorSet.h> 0021 #include <KisPaletteModel.h> 0022 #include <KisPaletteChooser.h> 0023 #include <kis_palette_view.h> 0024 #include <KoResourceServerProvider.h> 0025 #include <KoResourceServer.h> 0026 0027 #include "kis_signal_compressor.h" 0028 #include "KoColorDisplayRendererInterface.h" 0029 0030 #include "kis_spinbox_color_selector.h" 0031 0032 #include "KisDlgInternalColorSelector.h" 0033 #include "ui_WdgDlgInternalColorSelector.h" 0034 #include "kis_config_notifier.h" 0035 #include "kis_color_input.h" 0036 #include "kis_icon_utils.h" 0037 #include "KisSqueezedComboBox.h" 0038 0039 std::function<KisScreenColorSamplerBase *(QWidget *)> KisDlgInternalColorSelector::s_screenColorSamplerFactory = 0; 0040 0041 struct KisDlgInternalColorSelector::Private 0042 { 0043 bool allowUpdates = true; 0044 KoColor currentColor; 0045 KoColor previousColor; 0046 KoColor sRGB = KoColor(KoColorSpaceRegistry::instance()->rgb8()); 0047 const KoColorSpace *currentColorSpace; 0048 bool lockUsedCS = false; 0049 bool chooseAlpha = false; 0050 KisSignalCompressor *compressColorChanges; 0051 const KoColorDisplayRendererInterface *displayRenderer; 0052 KisHexColorInput *hexColorInput = 0; 0053 KisPaletteModel *paletteModel = 0; 0054 KisPaletteChooser *paletteChooser = 0; 0055 KisScreenColorSamplerBase *screenColorSampler = 0; 0056 KisVisualColorModelSP selectorModel; 0057 }; 0058 0059 KisDlgInternalColorSelector::KisDlgInternalColorSelector(QWidget *parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer) 0060 : QDialog(parent) 0061 , m_d(new Private) 0062 { 0063 setModal(config.modal); 0064 setFocusPolicy(Qt::ClickFocus); 0065 m_ui = new Ui_WdgDlgInternalColorSelector(); 0066 m_ui->setupUi(this); 0067 0068 setWindowTitle(caption); 0069 0070 m_d->selectorModel = m_ui->visualSelector->selectorModel(); 0071 0072 m_d->currentColor = color; 0073 m_d->currentColorSpace = m_d->currentColor.colorSpace(); 0074 m_d->displayRenderer = displayRenderer; 0075 0076 m_ui->spinboxselector->slotSetColor(color); 0077 connect(m_ui->spinboxselector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); 0078 0079 m_ui->spinboxHSXSelector->setModel(m_d->selectorModel); 0080 0081 m_ui->visualSelector->setDisplayRenderer(displayRenderer); 0082 m_ui->visualSelector->setConfig(false, config.modal); 0083 if (config.visualColorSelector) { 0084 connect(m_d->selectorModel.data(), SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); 0085 connect(m_d->selectorModel.data(), SIGNAL(sigColorModelChanged()), this, SLOT(slotSelectorModelChanged())); 0086 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_ui->visualSelector, SLOT(slotConfigurationChanged())); 0087 } else { 0088 m_ui->visualSelector->hide(); 0089 } 0090 m_ui->visualSelector->slotSetColor(color); 0091 0092 m_d->paletteChooser = new KisPaletteChooser(this); 0093 m_d->paletteModel = new KisPaletteModel(this); 0094 m_ui->bnPaletteChooser->setIcon(KisIconUtils::loadIcon("palette-library")); 0095 m_ui->paletteBox->setPaletteModel(m_d->paletteModel); 0096 m_ui->paletteBox->setDisplayRenderer(displayRenderer); 0097 m_ui->cmbNameList->setCompanionView(m_ui->paletteBox); 0098 connect(m_d->paletteChooser, SIGNAL(sigPaletteSelected(KoColorSetSP)), this, SLOT(slotChangePalette(KoColorSetSP))); 0099 connect(m_ui->cmbNameList, SIGNAL(sigColorSelected(KoColor)), SLOT(slotColorUpdated(KoColor))); 0100 0101 // For some bizarre reason, the modal dialog doesn't like having the colorset set, so let's not. 0102 if (config.paletteBox) { 0103 //TODO: Add disable signal as well. Might be not necessary...? 0104 KConfigGroup cfg(KSharedConfig::openConfig()->group("")); 0105 QString paletteMd5 = cfg.readEntry("internal_selector_active_color_set_md5", QString()); 0106 QString paletteName = cfg.readEntry("internal_selector_active_color_set", QString()); 0107 KoResourceServer<KoColorSet>* rServer = KoResourceServerProvider::instance()->paletteServer(); 0108 KoColorSetSP savedPal = rServer->resource(paletteMd5, "", paletteName); 0109 if (savedPal) { 0110 this->slotChangePalette(savedPal); 0111 } else { 0112 if (rServer->resourceCount()) { 0113 savedPal = rServer->firstResource(); 0114 if (savedPal) { 0115 this->slotChangePalette(savedPal); 0116 } 0117 } 0118 } 0119 0120 connect(m_ui->paletteBox, SIGNAL(sigColorSelected(KoColor)), this, 0121 SLOT(slotColorUpdated(KoColor))); 0122 m_ui->bnPaletteChooser->setPopupWidget(m_d->paletteChooser); 0123 } else { 0124 m_ui->paletteBox->setEnabled(false); 0125 m_ui->cmbNameList->setEnabled(false); 0126 m_ui->bnPaletteChooser->setEnabled(false); 0127 } 0128 0129 if (config.prevNextButtons) { 0130 m_ui->currentColor->setColor(m_d->currentColor); 0131 m_ui->currentColor->setDisplayRenderer(displayRenderer); 0132 m_ui->previousColor->setColor(m_d->previousColor); 0133 m_ui->previousColor->setDisplayRenderer(displayRenderer); 0134 connect(m_ui->previousColor, SIGNAL(triggered(KoColorPatch*)), SLOT(slotSetColorFromPatch(KoColorPatch*))); 0135 } else { 0136 m_ui->currentColor->hide(); 0137 m_ui->previousColor->hide(); 0138 } 0139 0140 if (config.hexInput) { 0141 m_d->sRGB.fromKoColor(m_d->currentColor); 0142 m_d->hexColorInput = new KisHexColorInput(this, &m_d->sRGB); 0143 m_d->hexColorInput->update(); 0144 connect(m_d->hexColorInput, SIGNAL(updated()), SLOT(slotSetColorFromHex())); 0145 m_ui->rightPane->addWidget(m_d->hexColorInput); 0146 m_d->hexColorInput->setToolTip(i18n("This is a hexcode input, for webcolors. It can only get colors in the sRGB space.")); 0147 } 0148 0149 // KisScreenColorSampler is in the kritaui module, so dependency inversion is used to access it. 0150 m_ui->screenColorSamplerWidget->setLayout(new QHBoxLayout()); 0151 if (s_screenColorSamplerFactory) { 0152 m_d->screenColorSampler = s_screenColorSamplerFactory(m_ui->screenColorSamplerWidget); 0153 m_ui->screenColorSamplerWidget->layout()->addWidget(m_d->screenColorSampler); 0154 if (config.screenColorSampler) { 0155 connect(m_d->screenColorSampler, SIGNAL(sigNewColorSampled(KoColor)),this, SLOT(slotColorUpdated(KoColor))); 0156 } else { 0157 m_d->screenColorSampler->hide(); 0158 } 0159 } 0160 0161 m_d->compressColorChanges = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); 0162 connect(m_d->compressColorChanges, SIGNAL(timeout()), this, SLOT(endUpdateWithNewColor())); 0163 0164 KGuiItem::assign(m_ui->buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok()); 0165 KGuiItem::assign(m_ui->buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); 0166 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()), Qt::UniqueConnection); 0167 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()), Qt::UniqueConnection); 0168 0169 connect(this, SIGNAL(finished(int)), SLOT(slotFinishUp())); 0170 } 0171 0172 KisDlgInternalColorSelector::~KisDlgInternalColorSelector() 0173 { 0174 delete m_ui; 0175 } 0176 0177 void KisDlgInternalColorSelector::slotColorUpdated(KoColor newColor) 0178 { 0179 // not-so-nice solution: if someone calls this slot directly and that code was 0180 // triggered by our compressor signal, our compressor is technically the sender()! 0181 if (sender() == m_d->compressColorChanges) { 0182 return; 0183 } 0184 // Do not accept external updates while a color update emit is pending; 0185 // Note: Assumes external updates only come from parent(), a separate slot might be better 0186 if (m_d->allowUpdates || (QObject::sender() && QObject::sender() != this->parent())) { 0187 // Enforce palette colors 0188 KConfigGroup group(KSharedConfig::openConfig(), ""); 0189 if (group.readEntry("colorsettings/forcepalettecolors", false)) { 0190 newColor = m_ui->paletteBox->closestColor(newColor); 0191 } 0192 0193 if (m_d->lockUsedCS){ 0194 newColor.convertTo(m_d->currentColorSpace); 0195 } else { 0196 colorSpaceChanged(newColor.colorSpace()); 0197 } 0198 m_d->currentColor = newColor; 0199 updateAllElements(QObject::sender()); 0200 } 0201 } 0202 0203 void KisDlgInternalColorSelector::slotSetColorFromPatch(KoColorPatch *patch) 0204 { 0205 slotColorUpdated(patch->color()); 0206 } 0207 0208 void KisDlgInternalColorSelector::colorSpaceChanged(const KoColorSpace *cs) 0209 { 0210 if (cs == m_d->currentColorSpace) { 0211 return; 0212 } 0213 0214 m_d->currentColorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); 0215 m_ui->spinboxselector->slotSetColorSpace(m_d->currentColorSpace); 0216 m_ui->visualSelector->slotSetColorSpace(m_d->currentColorSpace); 0217 0218 } 0219 0220 void KisDlgInternalColorSelector::lockUsedColorSpace(const KoColorSpace *cs) 0221 { 0222 colorSpaceChanged(cs); 0223 if (m_d->currentColor.colorSpace() != m_d->currentColorSpace) { 0224 m_d->currentColor.convertTo(m_d->currentColorSpace); 0225 m_ui->spinboxselector->slotSetColor(m_d->currentColor); 0226 m_ui->visualSelector->slotSetColor(m_d->currentColor); 0227 } 0228 m_d->lockUsedCS = true; 0229 } 0230 0231 void KisDlgInternalColorSelector::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) 0232 { 0233 if (displayRenderer) { 0234 m_d->displayRenderer = displayRenderer; 0235 m_ui->visualSelector->setDisplayRenderer(displayRenderer); 0236 m_ui->currentColor->setDisplayRenderer(displayRenderer); 0237 m_ui->previousColor->setDisplayRenderer(displayRenderer); 0238 m_ui->paletteBox->setDisplayRenderer(displayRenderer); 0239 } else { 0240 m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); 0241 } 0242 } 0243 0244 KoColor KisDlgInternalColorSelector::getModalColorDialog(const KoColor color, QWidget* parent, QString caption) 0245 { 0246 Config config = Config(); 0247 KisDlgInternalColorSelector dialog(parent, color, config, caption); 0248 dialog.setPreviousColor(color); 0249 dialog.exec(); 0250 return dialog.getCurrentColor(); 0251 } 0252 0253 KoColor KisDlgInternalColorSelector::getCurrentColor() 0254 { 0255 return m_d->currentColor; 0256 } 0257 0258 void KisDlgInternalColorSelector::chooseAlpha(bool chooseAlpha) 0259 { 0260 m_d->chooseAlpha = chooseAlpha; 0261 } 0262 0263 void KisDlgInternalColorSelector::setPreviousColor(KoColor c) 0264 { 0265 m_d->previousColor = c; 0266 } 0267 0268 void KisDlgInternalColorSelector::reject() 0269 { 0270 slotColorUpdated(m_d->previousColor); 0271 QDialog::reject(); 0272 } 0273 0274 void KisDlgInternalColorSelector::updateAllElements(QObject *source) 0275 { 0276 //update everything!!! 0277 if (source != m_ui->spinboxselector) { 0278 m_ui->spinboxselector->slotSetColor(m_d->currentColor); 0279 } 0280 0281 if (source != m_ui->visualSelector) { 0282 m_ui->visualSelector->slotSetColor(m_d->currentColor); 0283 } 0284 0285 if (source != m_d->hexColorInput) { 0286 m_d->sRGB.fromKoColor(m_d->currentColor); 0287 m_d->hexColorInput->update(); 0288 } 0289 0290 if (source != m_ui->paletteBox) { 0291 m_ui->paletteBox->selectClosestColor(m_d->currentColor); 0292 } 0293 0294 m_ui->previousColor->setColor(m_d->previousColor); 0295 0296 m_ui->currentColor->setColor(m_d->currentColor); 0297 0298 if (source && source != this->parent()) { 0299 m_d->allowUpdates = false; 0300 m_d->compressColorChanges->start(); 0301 } 0302 0303 if (m_d->screenColorSampler) { 0304 m_d->screenColorSampler->updateIcons(); 0305 } 0306 } 0307 0308 void KisDlgInternalColorSelector::slotSelectorModelChanged() 0309 { 0310 if (m_d->selectorModel->isHSXModel()) { 0311 QString label; 0312 switch (m_d->selectorModel->colorModel()) { 0313 case KisVisualColorModel::HSV: 0314 label = i18n("HSV"); 0315 break; 0316 case KisVisualColorModel::HSL: 0317 label = i18n("HSL"); 0318 break; 0319 case KisVisualColorModel::HSI: 0320 label = i18n("HSI"); 0321 break; 0322 case KisVisualColorModel::HSY: 0323 label = i18n("HSY'"); 0324 break; 0325 default: 0326 label = i18n("Unknown"); 0327 } 0328 if (m_ui->tabWidget->count() == 1) { 0329 m_ui->tabWidget->addTab(m_ui->tab_hsx, label); 0330 } 0331 else { 0332 m_ui->tabWidget->setTabText(1, label); 0333 } 0334 } 0335 else { 0336 if (m_ui->tabWidget->count() == 2) { 0337 m_ui->tabWidget->removeTab(1); 0338 } 0339 } 0340 } 0341 0342 void KisDlgInternalColorSelector::endUpdateWithNewColor() 0343 { 0344 emit signalForegroundColorChosen(m_d->currentColor); 0345 m_d->allowUpdates = true; 0346 } 0347 0348 void KisDlgInternalColorSelector::focusInEvent(QFocusEvent *) 0349 { 0350 //setPreviousColor(); 0351 } 0352 0353 void KisDlgInternalColorSelector::slotFinishUp() 0354 { 0355 setPreviousColor(m_d->currentColor); 0356 KConfigGroup cfg(KSharedConfig::openConfig()->group("")); 0357 if (m_d->paletteModel) { 0358 if (m_d->paletteModel->colorSet()) { 0359 cfg.writeEntry("internal_selector_active_color_set_md5", m_d->paletteModel->colorSet()->md5Sum()); 0360 cfg.writeEntry("internal_selector_active_color_set", m_d->paletteModel->colorSet()->name()); 0361 } 0362 } 0363 } 0364 0365 void KisDlgInternalColorSelector::slotSetColorFromHex() 0366 { 0367 slotColorUpdated(m_d->sRGB); 0368 } 0369 0370 void KisDlgInternalColorSelector::slotChangePalette(KoColorSetSP set) 0371 { 0372 if (!set) { 0373 return; 0374 } 0375 m_d->paletteModel->setColorSet(set); 0376 } 0377 0378 void KisDlgInternalColorSelector::showEvent(QShowEvent *event) 0379 { 0380 updateAllElements(0); 0381 QDialog::showEvent(event); 0382 } 0383