Krita Source Code Documentation
Loading...
Searching...
No Matches
WGColorSelectorDock.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2020 Mathias Wein <lynx.mw+kde@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
8
9#include "WGActionManager.h"
11#include "WGColorPatches.h"
13#include "WGCommonColorSet.h"
16#include "WGShadeSelector.h"
19
20#include <klocalizedstring.h>
21
22#include <kis_icon.h>
23#include <kis_canvas2.h>
25#include <kis_config_notifier.h>
28#include <KisUniqueColorSet.h>
29#include <KisGamutMaskToolbar.h>
31
32#include <QBoxLayout>
33#include <QMenu>
34#include <QToolButton>
35#include <QWidgetAction>
36
37#include <QDebug>
38#include <kis_assert.h>
39
41 : QDockWidget()
42 , m_displayConfig(new WGSelectorDisplayConfig)
43 , m_colorChangeCompressor(new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this))
44 , m_actionManager(new WGActionManager(this))
45 , m_colorTooltip(new WGColorPreviewToolTip(this))
46 , m_colorModelBG(new KisVisualColorModel)
47{
48 setWindowTitle(i18n("Wide Gamut Color Selector"));
49
50 QWidget *mainWidget = new QWidget();
51 m_mainWidgetLayout = new QVBoxLayout(mainWidget);
52 m_verticalElementsLayout = new QHBoxLayout();
53 m_selectorAreaLayout = new QBoxLayout(QBoxLayout::TopToBottom);
54
55 m_selector = new KisVisualColorSelector(mainWidget);
57 connect(m_selector, SIGNAL(sigNewColor(KoColor)), SLOT(slotColorSelected(KoColor)));
58 connect(m_selector, SIGNAL(sigInteraction(bool)), SLOT(slotColorInteraction(bool)));
59 connect(m_colorChangeCompressor, SIGNAL(timeout()), SLOT(slotSetNewColors()));
61
62 // Header
63 QWidget *headerWidget = new QWidget(mainWidget);
64 QHBoxLayout *headerLayout = new QHBoxLayout(headerWidget);
65
66 m_toggle = new KisColorSourceToggle(mainWidget);
67 connect(m_toggle, SIGNAL(toggled(bool)), SLOT(slotColorSourceToggled(bool)));
68 headerLayout->addWidget(m_toggle);
70 m_gamutToolbar->setContentsMargins(0, 0, 0, 5);
71 m_gamutToolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
72 headerLayout->addWidget(m_gamutToolbar);
73 headerLayout->addStretch();
74 headerLayout->setContentsMargins(0, 0, 0, 0);
75
76 connect(m_selector, SIGNAL(sigGamutMaskSupportChanged(bool)), SLOT(slotShowGamutMaskToolbar(bool)));
77
78 m_configButton = new QToolButton(this);
79 m_configButton->setIcon(KisIconUtils::loadIcon("view-choose"));
80 m_configButton->setAutoRaise(true);
81 m_configButton->setPopupMode(QToolButton::InstantPopup);
82 headerLayout->addWidget(m_configButton);
83
84 m_mainWidgetLayout->addWidget(headerWidget);
87
89
93 connect(m_shadeSelector, SIGNAL(sigColorInteraction(bool)), SLOT(slotColorInteraction(bool)));
94
95 // eventually it should made be a global history, not specific to any plugin
97
100 connect(m_history, SIGNAL(sigColorChanged(KoColor)), SLOT(slotColorSelected(KoColor)));
101 connect(m_history, SIGNAL(sigColorInteraction(bool)), SLOT(slotColorInteraction(bool)));
102
103 // Common Colors (Colors from Image)
105
108 connect(m_commonColors, SIGNAL(sigColorChanged(KoColor)), SLOT(slotColorSelected(KoColor)));
109 connect(m_commonColors, SIGNAL(sigColorInteraction(bool)), SLOT(slotColorInteraction(bool)));
110
111 connect(WGConfig::notifier(), SIGNAL(configChanged()), SLOT(slotConfigurationChanged()));
112
113 setWidget(mainWidget);
115 setEnabled(false);
116}
117
119{
120 // currently always return foreground model;
121 // do lazy conversion to current HSX model if required
122 if (selectingBackground() && m_colorModelBG->isHSXModel()) {
123 m_colorModelFG->setRGBColorModel(m_colorModelBG->colorModel());
124 }
125 return *(m_colorModelFG);
126}
127
129{
130 KisDisplayColorConverter *converter = nullptr;
131 if (m_canvas) {
132 converter = m_canvas->displayColorConverter();
133 }
134 return (rawPointer || converter) ? converter : KisDisplayColorConverter::dumbConverterInstance();
135}
136
138{
139 return m_toggle->isChecked();
140}
141
142void WGColorSelectorDock::setChannelValues(const QVector4D &values)
143{
144 // currently always set foreground color
145 if (!m_canvas) {
146 return;
147 }
148
149 // This could be nicer...if setting active model, this triggers slotColorSelected()
150 // and leaves timer running with NOP, otherwise the resource update is detected as
151 // external event and updates UI.
152 m_colorModelFG->slotSetChannelValues(values);
153
154 m_canvas->resourceManager()->setForegroundColor(m_colorModelFG->currentColor());
155 m_pendingFgUpdate = false;
156}
157
159{
160 Q_UNUSED(event)
161 m_colorTooltip->hide();
162}
163
165{
166 if (m_canvas.data() == canvas)
167 {
168 // not sure why setCanvas gets called 3 times for new canvas, just skip
169 return;
170 }
171 if (m_canvas) {
173 }
174 m_actionManager->setCanvas(qobject_cast<KisCanvas2*>(canvas), m_canvas);
175 m_canvas = qobject_cast<KisCanvas2*>(canvas);
176 // TODO: unset display converters if canvas is null
177 if (m_canvas) {
178 KoColorDisplayRendererInterface *dri = m_canvas->displayColorConverter()->displayRendererInterface();
179 KisCanvasResourceProvider *resourceProvider = m_canvas->imageView()->resourceProvider();
181 m_displayConfig->setDisplayConverter(m_canvas->displayColorConverter());
183 //m_toggle->setBackgroundColor(dri->toQColor(color));
184 connect(dri, SIGNAL(displayConfigurationChanged()), this, SLOT(slotDisplayConfigurationChanged()));
185 connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
186 this, SLOT(slotCanvasResourceChanged(int,QVariant)));
187 connect(resourceProvider, SIGNAL(sigFGColorUsed(KoColor)),
188 this, SLOT(slotFGColorUsed(KoColor)), Qt::UniqueConnection);
189
190 // Gamut Mask
191 connect(resourceProvider, SIGNAL(sigGamutMaskChanged(KoGamutMaskSP)),
192 m_selector, SLOT(slotGamutMaskChanged(KoGamutMaskSP)), Qt::UniqueConnection);
193
194 connect(resourceProvider, SIGNAL(sigGamutMaskPreviewUpdate()),
195 m_selector, SLOT(slotGamutMaskPreviewUpdate()), Qt::UniqueConnection);
196
197 connect(resourceProvider, SIGNAL(sigGamutMaskUnset()),
198 m_selector, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection);
199
200 connect(resourceProvider, SIGNAL(sigGamutMaskDeactivated()),
201 m_selector, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection);
202
203 m_gamutToolbar->connectMaskSignals(resourceProvider);
204
205 // quirk note: displayConfigurationChanged signal gets sent *before* the new canvas gets
206 // passed, through the display converter of the now inactive canvas! So we need to repeat...
208 }
209 setEnabled(canvas != 0);
210}
211
213{
214 setEnabled(false);
216 m_displayConfig->setDisplayConverter(0);
219 m_canvas = 0;
220}
221
226
228{
229 m_canvas->disconnectCanvasObserver(this);
230 m_canvas->displayColorConverter()->displayRendererInterface()->disconnect(this);
231 m_canvas->imageView()->resourceProvider()->disconnect(m_selector);
232 m_canvas = 0;
233}
234
236{
238
239 bool historyEnabled = cfg.get(WGConfig::colorHistoryEnabled);
240 Qt::Orientation historyOrientation = cfg.get(WGConfig::colorHistory.orientation);
241
242 m_verticalElementsLayout->removeWidget(m_history);
244 m_mainWidgetLayout->removeWidget(m_history);
245 m_mainWidgetLayout->removeWidget(m_commonColors);
246
247 if (historyEnabled) {
248 if (historyOrientation == Qt::Vertical) {
250 }
251 else {
252 m_mainWidgetLayout->addWidget(m_history);
253 }
254 m_history->show();
255 }
256 else {
257 m_history->hide();
258 }
259
260 bool commonColorsEnabled = cfg.get(WGConfig::commonColorsEnabled);
261 Qt::Orientation commonColorsOrientation = cfg.get(WGConfig::commonColors.orientation);
262
263 if (commonColorsEnabled) {
264 if (commonColorsOrientation == Qt::Vertical) {
266 }
267 else {
269 }
270 m_commonColors->show();
271 }
272 else {
273 m_commonColors->hide();
274 }
275
276 bool shadeSelectorEnabled = cfg.get(WGConfig::minimalShadeSelectorEnabled);
277 if (shadeSelectorEnabled) {
278 m_shadeSelector->show();
279 }
280 else {
281 m_shadeSelector->hide();
282 }
283
284}
285
287{
290 m_selector->selectorModel()->setRGBColorModel(cfg.get(WGConfig::rgbColorModel));
291 KisColorSelectorConfiguration selectorCfg = cfg.colorSelectorConfiguration();
292 m_selector->setConfiguration(&selectorCfg);
295 m_customCS = cfg.customSelectionColorSpace();
296 }
297 bool proofColors = cfg.get(WGConfig::proofToPaintingColors);
298 m_selector->setProofColors(proofColors);
299 m_displayConfig->setPreviewInPaintingCS(proofColors);
304 // Quick settings menu
305 if (cfg.get(WGConfig::quickSettingsEnabled)) {
306 if (!m_configButton->menu()) {
307 m_configButton->disconnect(this);
308 QMenu *configureMenu = new QMenu(this);
310 // prevents hover indicator being stuck on other menu entries
311 m_quickSettings->setMouseTracking(true);
312 m_quickSettingAction = new QWidgetAction(this);
313 m_quickSettingAction->setDefaultWidget(m_quickSettings);
314
315 configureMenu->addAction(m_quickSettingAction);
316 QAction *cfgAction = configureMenu->addAction(i18nc("Wide Gamut Color Selector", "Configure..."));
317 connect(cfgAction, SIGNAL(triggered(bool)), SLOT(slotOpenSettings()));
318 m_configButton->setMenu(configureMenu);
319 } else {
320 // WORKAROUND: force geometry update by re-adding action, all other attempts failed...
321 QMenu *menu = m_configButton->menu();
322 menu->removeAction(m_quickSettingAction);
323 menu->insertAction(menu->actions().constFirst(), m_quickSettingAction);
324 }
326 } else {
327 if (m_configButton->menu()) {
328 m_configButton->menu()->deleteLater();
329 m_configButton->setMenu(0);
332 m_quickSettings = 0;
333 }
334 connect(m_configButton, SIGNAL(clicked(bool)), SLOT(slotOpenSettings()), Qt::UniqueConnection);
335 }
336
337 updateLayout();
338
339 if (m_canvas) {
341 }
342}
343
345{
346 if (!m_canvas) {
347 return;
348 }
349
350 const KoColorSpace *selectionCS = nullptr;
351
352 // Note: displayConfigurationChanged is also emitted on image color space changes,
353 // so there's no need to handle extra signals, although it's a bit convoluted
355 selectionCS = m_canvas->image()->colorSpace();
356 } else if (m_CSSource == FixedColorSpace) {
357 selectionCS = m_customCS;
358 } else {
359 selectionCS = m_canvas->displayColorConverter()->nodeColorSpace();
360 }
361
362 // TODO: use m_viewManager->canvasResourceProvider()->fgColor();
363 KoColor fgColor = m_canvas->resourceManager()->foregroundColor();
364 KoColor bgColor = m_canvas->resourceManager()->backgroundColor();
365
366 bool proof = m_displayConfig->previewInPaintingCS();
367 m_toggle->setForegroundColor(displayColorConverter()->toQColor(fgColor, proof));
368 m_toggle->setBackgroundColor(displayColorConverter()->toQColor(bgColor, proof));
370
371 if (selectionCS && selectionCS != activeModel->colorSpace()) {
372 activeModel->slotSetColorSpace(selectionCS);
373 activeModel->slotSetColor(activeModel == m_colorModelFG ? fgColor : bgColor);
374 }
375}
376
378{
379 QColor displayCol = displayColorConverter()->toQColor(color, m_displayConfig->previewInPaintingCS());
380 m_colorTooltip->setCurrentColor(displayCol);
381 if (selectingBackground()) {
382 m_toggle->setBackgroundColor(displayCol);
383 m_pendingBgUpdate = true;
385 }
386 else {
387 m_toggle->setForegroundColor(displayCol);
388 m_pendingFgUpdate = true;
390 }
391 if (sender() != m_selector) {
392 m_selector->slotSetColor(color);
393 }
394}
395
397{
398 if (selectingBg) {
399 if (m_colorModelFG->isHSXModel()) {
400 m_colorModelBG->setRGBColorModel(m_colorModelFG->colorModel());
401 }
404 }
405 else {
406 if (m_colorModelBG->isHSXModel()) {
407 m_colorModelFG->setRGBColorModel(m_colorModelBG->colorModel());
408 }
411 }
412 // currently, only the color space of the active model is updated, so it may be outdated
413 if (m_canvas) {
415 }
416}
417
419{
420 if (active) {
421 QColor baseCol = m_displayConfig->displayConverter()->toQColor(m_selector->getCurrentColor());
424 if (sender() == m_shadeSelector) {
426 } else {
427 m_colorTooltip->show(this);
428 }
429 }
430}
431
433{
434 QColor lastCol = m_displayConfig->displayConverter()->toQColor(color);
437 m_colorHistory->addColor(color);
438}
439
441{
442 //KIS_SAFE_ASSERT_RECOVER_RETURN(m_pendingFgUpdate || m_pendingBgUpdate);
443 if (m_pendingFgUpdate) {
444 m_canvas->resourceManager()->setForegroundColor(m_colorModelFG->currentColor());
445 m_pendingFgUpdate = false;
446 }
447 if (m_pendingBgUpdate) {
448 m_canvas->resourceManager()->setBackgroundColor(m_colorModelBG->currentColor());
449 m_pendingBgUpdate = false;
450 }
451}
452
454{
455 switch (key) {
457 if (!m_pendingFgUpdate) {
458 KoColor color = value.value<KoColor>();
460 m_colorModelFG->slotSetColor(color);
461 }
462 break;
464 if (!m_pendingBgUpdate) {
465 KoColor color = value.value<KoColor>();
467 m_colorModelBG->slotSetColor(color);
468 }
469 default:
470 break;
471 }
472}
473
475{
476 if (!m_canvas) return;
477
479 if (settings.exec() == QDialog::Accepted) {
480 //WGConfig::notifier()->notifyConfigChanged();
481 }
482}
483
485{
486 m_gamutToolbar->setVisible(show);
487}
488
489namespace WGConfig {
495}
float value(const T *src, size_t ch)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void setBackgroundColor(const QColor &color)
void setForegroundColor(const QColor &color)
static KisDisplayColorConverter * dumbConverterInstance()
QColor toQColor(const KoColor &c, bool proofToPaintColors=false) const
void connectMaskSignals(KisCanvasResourceProvider *resourceProvider)
void addColor(const KoColor &color)
The KisVisualColorModel class allows manipulating a KoColor using various color models.
The KisVisualColorSelector class.
void setSelectorModel(KisVisualColorModelSP model)
void setRenderMode(RenderMode mode)
void setConfiguration(const KisColorSelectorConfiguration *config)
Explicitly set the shape configuration. Accepts all valid combinations of Advanced Color Selector,...
void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) override
void slotSetColor(const KoColor &c) override
KoColor getCurrentColor() const override
KisVisualColorModelSP selectorModel() const
void setCanvas(KisCanvas2 *canvas, KisCanvas2 *oldCanvas)
void setLastUsedColor(const KoColor &col)
void registerActions(KisViewManager *viewManager)
void setPreset(Preset preset)
void updateSettings() override
void setLastUsedColor(const QColor &color)
void show(const QWidget *focus=nullptr)
void setCurrentColor(const QColor &color)
void setPreviousColor(const QColor &color)
const KoColorSpace * m_customCS
void slotColorSelected(const KoColor &color)
void setViewManager(KisViewManager *viewManager) override
WGQuickSettingsWidget * m_quickSettings
QBoxLayout * m_selectorAreaLayout
KisGamutMaskToolbar * m_gamutToolbar
void slotShowGamutMaskToolbar(bool show)
void slotColorInteraction(bool active)
WGCommonColorSet * m_commonColorSet
WGShadeSelector * m_shadeSelector
KisVisualColorModelSP m_colorModelBG
QWidgetAction * m_quickSettingAction
KisColorSourceToggle * m_toggle
QBoxLayout * m_mainWidgetLayout
void slotColorSourceToggled(bool selectingBg)
WGColorPatches * m_history
void slotFGColorUsed(const KoColor &color)
const KisVisualColorModel & colorModel() const
WGActionManager * m_actionManager
KisSignalCompressor * m_colorChangeCompressor
void leaveEvent(QEvent *event) override
KisVisualColorModelSP m_colorModelFG
void setCanvas(KoCanvasBase *canvas) override
void slotCanvasResourceChanged(int key, const QVariant &value)
KisVisualColorSelector * m_selector
QBoxLayout * m_verticalElementsLayout
KisDisplayColorConverter * displayColorConverter(bool rawPointer=false) const
void setChannelValues(const QVector4D &values)
Set new channel values; takes effect immediately!
ColorSpaceSource m_CSSource
WGColorPatches * m_commonColors
KisUniqueColorSet * m_colorHistory
WGSelectorDisplayConfigSP m_displayConfig
QPointer< KisCanvas2 > m_canvas
WGColorPreviewToolTip * m_colorTooltip
void setAutoUpdate(bool enabled)
void setImage(KisImageSP image)
void setModel(KisVisualColorModelSP colorModel) override
void updateSettings() override
KisSharedPtr< KisImage > KisImageSP
Definition kis_types.h:69
QIcon loadIcon(const QString &name)
@ BackgroundColor
The active background color selected for this canvas.
@ ForegroundColor
The active foreground color selected for this canvas.
const GenericSetting< bool > colorHistoryEnabled
Definition WGConfig.cpp:238
const ColorPatches commonColors
Definition WGConfig.cpp:221
const GenericSetting< bool > minimalShadeSelectorEnabled
Definition WGConfig.cpp:246
const GenericSetting< bool > commonColorsEnabled
Definition WGConfig.cpp:239
const NumericSetting< KisVisualColorSelector::RenderMode > selectorRenderMode
Definition WGConfig.cpp:255
const NumericSetting< WGColorSelectorDock::ColorSpaceSource > colorSpaceSource
WGConfigNotifier * notifier()
Definition WGConfig.cpp:190
const NumericSetting< KisVisualColorModel::ColorModel > rgbColorModel
Definition WGConfig.cpp:252
class WGConfig Accessor
const GenericSetting< bool > proofToPaintingColors
Definition WGConfig.cpp:237
const GenericSetting< bool > quickSettingsEnabled
Definition WGConfig.cpp:243
const GenericSetting< bool > commonColorsAutoUpdate
Definition WGConfig.cpp:241
const ColorPatches colorHistory
Definition WGConfig.cpp:213