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