Krita Source Code Documentation
Loading...
Searching...
No Matches
KisDlgInternalColorSelector.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include <QAbstractSpinBox>
8#include <QSpinBox>
9#include <QDoubleSpinBox>
10#include <QCompleter>
11
12#include <functional>
13
14#include <KConfigGroup>
15#include <KSharedConfig>
16#include <kstandardguiitem.h>
17
19#include <KoColorSet.h>
20#include <KisPaletteModel.h>
21#include <KisPaletteChooser.h>
22#include <kis_palette_view.h>
23#include <KisResourceModel.h>
25
28
30
32#include "ui_WdgDlgInternalColorSelector.h"
33#include "kis_config_notifier.h"
34#include "kis_color_input.h"
35#include "kis_icon_utils.h"
36#include "KisSqueezedComboBox.h"
37
39
57
58KisDlgInternalColorSelector::KisDlgInternalColorSelector(QWidget *parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer)
59 : QDialog(parent)
60 , m_d(new Private)
61{
62 setModal(config.modal);
63 setFocusPolicy(Qt::ClickFocus);
64 m_ui = new Ui_WdgDlgInternalColorSelector();
65 m_ui->setupUi(this);
66
67 setWindowTitle(caption);
68
69 m_d->selectorModel = m_ui->visualSelector->selectorModel();
70
71 m_d->currentColor = color;
72 m_d->currentColorSpace = m_d->currentColor.colorSpace();
73 m_d->displayRenderer = displayRenderer;
74
75 m_ui->spinboxselector->slotSetColor(color);
76 connect(m_ui->spinboxselector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor)));
77
78 m_ui->spinboxHSXSelector->setModel(m_d->selectorModel);
79
80 m_ui->visualSelector->setDisplayRenderer(displayRenderer);
81 m_ui->visualSelector->setConfig(false, config.modal);
82 if (config.visualColorSelector) {
83 connect(m_d->selectorModel.data(), SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor)));
84 connect(m_d->selectorModel.data(), SIGNAL(sigColorModelChanged()), this, SLOT(slotSelectorModelChanged()));
85 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_ui->visualSelector, SLOT(slotConfigurationChanged()));
86 } else {
87 m_ui->visualSelector->hide();
88 }
89 m_ui->visualSelector->slotSetColor(color);
90
91 m_d->paletteChooser = new KisPaletteChooser(this);
92 m_d->paletteModel = new KisPaletteModel(this);
93 m_ui->bnPaletteChooser->setIcon(KisIconUtils::loadIcon("palette-library"));
94 m_ui->bnPaletteChooser->setToolTip(i18n("Load a palette"));
95 m_ui->paletteBox->setPaletteModel(m_d->paletteModel);
96 m_ui->paletteBox->setDisplayRenderer(displayRenderer);
97 m_ui->cmbNameList->setCompanionView(m_ui->paletteBox);
98 connect(m_d->paletteChooser, SIGNAL(sigPaletteSelected(KoColorSetSP)), this, SLOT(slotChangePalette(KoColorSetSP)));
99 connect(m_ui->cmbNameList, SIGNAL(sigColorSelected(KoColor)), SLOT(slotColorUpdated(KoColor)));
100
101 // For some bizarre reason, the modal dialog doesn't like having the colorset set, so let's not.
102 if (config.paletteBox) {
103 //TODO: Add disable signal as well. Might be not necessary...?
104 KConfigGroup cfg(KSharedConfig::openConfig()->group(""));
105 QString paletteMd5 = cfg.readEntry("internal_selector_active_color_set_md5", QString());
106 QString paletteName = cfg.readEntry("internal_selector_active_color_set", QString());
107
108 KoColorSetSP savedPal;
109
110 if (!paletteMd5.isEmpty() || !paletteName.isEmpty()) {
112 savedPal = source.bestMatch(paletteMd5, "", paletteName);
113 }
114
115 if (!savedPal) {
122 auto foundResources = model.resourcesForName("Default");
123 if (!foundResources.isEmpty()) {
124 savedPal = foundResources.first().dynamicCast<KoColorSet>();
125 }
126 }
127
128 if (!savedPal) {
130 savedPal = source.fallbackResource();
131 }
132
133 if (savedPal) {
134 m_d->paletteChooser->setCurrentItem(savedPal);
135 // slotChangePalette() will be automatically called by the connection
136 // of m_d->paletteChooser
137 }
138
139 connect(m_ui->paletteBox, SIGNAL(sigColorSelected(KoColor)), this,
141 m_ui->bnPaletteChooser->setPopupWidget(m_d->paletteChooser);
142 } else {
143 m_ui->paletteBox->setEnabled(false);
144 m_ui->cmbNameList->setEnabled(false);
145 m_ui->bnPaletteChooser->setEnabled(false);
146 }
147
148 if (config.prevNextButtons) {
149 m_ui->currentColor->setColor(m_d->currentColor);
150 m_ui->currentColor->setDisplayRenderer(displayRenderer);
151 m_ui->previousColor->setColor(m_d->previousColor);
152 m_ui->previousColor->setDisplayRenderer(displayRenderer);
153 connect(m_ui->previousColor, SIGNAL(triggered(KoColorPatch*)), SLOT(slotSetColorFromPatch(KoColorPatch*)));
154 } else {
155 m_ui->currentColor->hide();
156 m_ui->previousColor->hide();
157 }
158
159 if (config.hexInput) {
160 m_d->sRGB.fromKoColor(m_d->currentColor);
161 m_d->hexColorInput = new KisHexColorInput(this, &m_d->sRGB);
162 m_d->hexColorInput->update();
163 connect(m_d->hexColorInput, SIGNAL(updated()), SLOT(slotSetColorFromHex()));
164 m_ui->rightPane->addWidget(m_d->hexColorInput);
165 m_d->hexColorInput->setToolTip(i18n("This is a hexcode input, for webcolors. It can only get colors in the sRGB space."));
166 }
167
168 // KisScreenColorSampler is in the kritaui module, so dependency inversion is used to access it.
169 m_ui->screenColorSamplerWidget->setLayout(new QHBoxLayout());
171 m_d->screenColorSampler = s_screenColorSamplerFactory(m_ui->screenColorSamplerWidget);
172 m_ui->screenColorSamplerWidget->layout()->addWidget(m_d->screenColorSampler);
173 if (config.screenColorSampler) {
174 connect(m_d->screenColorSampler, SIGNAL(sigNewColorSampled(KoColor)),this, SLOT(slotColorUpdated(KoColor)));
175 } else {
176 m_d->screenColorSampler->hide();
177 }
178 }
179
180 m_d->compressColorChanges = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this);
181 connect(m_d->compressColorChanges, SIGNAL(timeout()), this, SLOT(endUpdateWithNewColor()));
182
183 KGuiItem::assign(m_ui->buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
184 KGuiItem::assign(m_ui->buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
185 connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()), Qt::UniqueConnection);
186 connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()), Qt::UniqueConnection);
187
188 connect(this, SIGNAL(finished(int)), SLOT(slotFinishUp()));
189}
190
195
197{
198 // not-so-nice solution: if someone calls this slot directly and that code was
199 // triggered by our compressor signal, our compressor is technically the sender()!
200 if (sender() == m_d->compressColorChanges) {
201 return;
202 }
203 // Do not accept external updates while a color update Q_EMIT is pending;
204 // Note: Assumes external updates only come from parent(), a separate slot might be better
205 if (m_d->allowUpdates || (QObject::sender() && QObject::sender() != this->parent())) {
206 // Enforce palette colors
207 KConfigGroup group(KSharedConfig::openConfig(), "");
208 if (group.readEntry("colorsettings/forcepalettecolors", false)) {
209 newColor = m_ui->paletteBox->closestColor(newColor);
210 }
211
212 if (m_d->lockUsedCS){
213 newColor.convertTo(m_d->currentColorSpace);
214 } else {
215 colorSpaceChanged(newColor.colorSpace());
216 }
217 m_d->currentColor = newColor;
218 updateAllElements(QObject::sender());
219 }
220}
221
226
228{
229 if (cs == m_d->currentColorSpace) {
230 return;
231 }
232
233 m_d->currentColorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile());
234 m_ui->spinboxselector->slotSetColorSpace(m_d->currentColorSpace);
235 m_ui->visualSelector->slotSetColorSpace(m_d->currentColorSpace);
236
237}
238
240{
242 if (m_d->currentColor.colorSpace() != m_d->currentColorSpace) {
243 m_d->currentColor.convertTo(m_d->currentColorSpace);
244 m_ui->spinboxselector->slotSetColor(m_d->currentColor);
245 m_ui->visualSelector->slotSetColor(m_d->currentColor);
246 }
247 m_d->lockUsedCS = true;
248}
249
251{
252 if (displayRenderer) {
253 m_d->displayRenderer = displayRenderer;
254 m_ui->visualSelector->setDisplayRenderer(displayRenderer);
255 m_ui->currentColor->setDisplayRenderer(displayRenderer);
256 m_ui->previousColor->setDisplayRenderer(displayRenderer);
257 m_ui->paletteBox->setDisplayRenderer(displayRenderer);
258 } else {
259 m_d->displayRenderer = KoDumbColorDisplayRenderer::instance();
260 }
261}
262
264{
265 return m_d->currentColor;
266}
267
269{
270 m_d->chooseAlpha = chooseAlpha;
271}
272
274{
275 m_d->previousColor = c;
276}
277
279{
280 slotColorUpdated(m_d->previousColor);
281 QDialog::reject();
282}
283
285{
286 //update everything!!!
287 if (source != m_ui->spinboxselector) {
288 m_ui->spinboxselector->slotSetColor(m_d->currentColor);
289 }
290
291 if (source != m_ui->visualSelector) {
292 m_ui->visualSelector->slotSetColor(m_d->currentColor);
293 }
294
295 if (source != m_d->hexColorInput) {
296 m_d->sRGB.fromKoColor(m_d->currentColor);
297 m_d->hexColorInput->update();
298 }
299
300 if (source != m_ui->paletteBox) {
301 m_ui->paletteBox->selectClosestColor(m_d->currentColor);
302 }
303
304 m_ui->previousColor->setColor(m_d->previousColor);
305
306 m_ui->currentColor->setColor(m_d->currentColor);
307
308 if (source && source != this->parent()) {
309 m_d->allowUpdates = false;
310 m_d->compressColorChanges->start();
311 }
312
313 if (m_d->screenColorSampler) {
314 m_d->screenColorSampler->updateIcons();
315 }
316}
317
319{
320 if (m_d->selectorModel->isHSXModel()) {
321 QString label;
322 switch (m_d->selectorModel->colorModel()) {
324 label = i18n("HSV");
325 break;
327 label = i18n("HSL");
328 break;
330 label = i18n("HSI");
331 break;
333 label = i18n("HSY'");
334 break;
335 default:
336 label = i18n("Unknown");
337 }
338 if (m_ui->tabWidget->count() == 1) {
339 m_ui->tabWidget->addTab(m_ui->tab_hsx, label);
340 }
341 else {
342 m_ui->tabWidget->setTabText(1, label);
343 }
344 }
345 else {
346 if (m_ui->tabWidget->count() == 2) {
347 m_ui->tabWidget->removeTab(1);
348 }
349 }
350}
351
353{
354 Q_EMIT signalForegroundColorChosen(m_d->currentColor);
355 m_d->allowUpdates = true;
356}
357
359{
360 //setPreviousColor();
361}
362
364{
365 setPreviousColor(m_d->currentColor);
366 KConfigGroup cfg(KSharedConfig::openConfig()->group(""));
367 if (m_d->paletteModel) {
368 if (m_d->paletteModel->colorSet()) {
369 cfg.writeEntry("internal_selector_active_color_set_md5", m_d->paletteModel->colorSet()->md5Sum());
370 cfg.writeEntry("internal_selector_active_color_set", m_d->paletteModel->colorSet()->name());
371 }
372 }
373}
374
379
381{
382 if (!set) {
383 return;
384 }
385 m_d->paletteModel->setColorSet(set);
386}
387
389{
391 QDialog::showEvent(event);
392}
393
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
static KisConfigNotifier * instance()
static std::function< KisScreenColorSamplerBase *(QWidget *) s_screenColorSamplerFactory)
void setPreviousColor(KoColor c)
setPreviousColor set the previous color.
void colorSpaceChanged(const KoColorSpace *cs)
slotColorSpaceChanged Color space has changed, use this dialog to change the colorspace.
void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer)
setDisplayRenderer Set the display renderer. This is necessary for HDR color manage support.
void signalForegroundColorChosen(KoColor color)
signalForegroundColorChosen The most important signal. This will sent out when a color has been chose...
void lockUsedColorSpace(const KoColorSpace *cs)
lockUsedColorSpace Lock the used colorspace of this selector.
void showEvent(QShowEvent *event) override
void slotColorUpdated(KoColor newColor)
slotColorUpdated Very important slot. Is connected to krita's resources to make sure it has the curre...
void slotFinishUp()
slotFinishUp This is called when the selector is closed, for saving the current palette.
void slotSetColorFromPatch(KoColorPatch *patch)
slotSetColorFromPatch update current color from kocolorpatch.
void focusInEvent(QFocusEvent *) override
void slotSetColorFromHex()
slotSetColorFromHex Update from the hex color input.
KisDlgInternalColorSelector(QWidget *parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer=KoDumbColorDisplayRenderer::instance())
void updateAllElements(QObject *source)
updateAllElements Updates each widget with the new element, and if it's responsible for the update se...
const QScopedPointer< Private > m_d
Ui_WdgDlgInternalColorSelector * m_ui
static KisResourcesInterfaceSP instance()
The KisPaletteModel class This, together with KisPaletteView and KisPaletteDelegate forms a mvc way t...
The KisResourceModel class provides the main access to resources. It is possible to filter the resour...
QVector< KoResourceSP > resourcesForName(QString name) const
KoColor color() const
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
static KoColorDisplayRendererInterface * instance()
QString id() const
Definition KoID.cpp:63
QIcon loadIcon(const QString &name)
const QString Palettes
const KoColorDisplayRendererInterface * displayRenderer
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()