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 "KisDocument.h"
10#include "WGActionManager.h"
12#include "WGColorPatches.h"
14#include "WGCommonColorSet.h"
17#include "WGShadeSelector.h"
20
21#include <klocalizedstring.h>
22
23#include <kis_icon.h>
24#include <kis_canvas2.h>
26#include <kis_config_notifier.h>
29#include <KisUniqueColorSet.h>
30#include <KisGamutMaskToolbar.h>
32
33#include <QBoxLayout>
34#include <QMenu>
35#include <QToolButton>
36#include <QWidgetAction>
37
38#include <QDebug>
39#include <kis_assert.h>
40
42 : QDockWidget()
43 , m_displayConfig(new WGSelectorDisplayConfig)
44 , m_colorChangeCompressor(new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this))
45 , m_actionManager(new WGActionManager(this))
46 , m_colorTooltip(new WGColorPreviewToolTip(this))
47 , m_colorModelBG(new KisVisualColorModel)
48{
49 setWindowTitle(i18n("Wide Gamut Color Selector"));
50
51 QWidget *mainWidget = new QWidget();
52 m_mainWidgetLayout = new QVBoxLayout(mainWidget);
53 m_verticalElementsLayout = new QHBoxLayout();
54 m_selectorAreaLayout = new QBoxLayout(QBoxLayout::TopToBottom);
55
56 m_selector = new KisVisualColorSelector(mainWidget);
58 connect(m_selector, SIGNAL(sigNewColor(KoColor)), SLOT(slotColorSelected(KoColor)));
59 connect(m_selector, SIGNAL(sigInteraction(bool)), SLOT(slotColorInteraction(bool)));
60 connect(m_colorChangeCompressor, SIGNAL(timeout()), SLOT(slotSetNewColors()));
62
63 // Header
64 QWidget *headerWidget = new QWidget(mainWidget);
65 QHBoxLayout *headerLayout = new QHBoxLayout(headerWidget);
66
67 m_toggle = new KisColorSourceToggle(mainWidget);
68 connect(m_toggle, SIGNAL(toggled(bool)), SLOT(slotColorSourceToggled(bool)));
69 headerLayout->addWidget(m_toggle);
71 m_gamutToolbar->setContentsMargins(0, 0, 0, 5);
72 m_gamutToolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
73 headerLayout->addWidget(m_gamutToolbar);
74 headerLayout->addStretch();
75 headerLayout->setContentsMargins(0, 0, 0, 0);
76
77 connect(m_selector, SIGNAL(sigGamutMaskSupportChanged(bool)), SLOT(slotShowGamutMaskToolbar(bool)));
78
79 m_configButton = new QToolButton(this);
80 m_configButton->setIcon(KisIconUtils::loadIcon("view-choose"));
81 m_configButton->setAutoRaise(true);
82 m_configButton->setPopupMode(QToolButton::InstantPopup);
83 headerLayout->addWidget(m_configButton);
84
85 m_mainWidgetLayout->addWidget(headerWidget);
88
90
94 connect(m_shadeSelector, SIGNAL(sigColorInteraction(bool)), SLOT(slotColorInteraction(bool)));
95
96 // eventually it should made be a global history, not specific to any plugin
100
103 connect(m_history, SIGNAL(sigColorChanged(KoColor)), SLOT(slotColorSelected(KoColor)));
104 connect(m_history, SIGNAL(sigColorInteraction(bool)), SLOT(slotColorInteraction(bool)));
105
106 // Common Colors (Colors from Image)
108
111 connect(m_commonColors, SIGNAL(sigColorChanged(KoColor)), SLOT(slotColorSelected(KoColor)));
112 connect(m_commonColors, SIGNAL(sigColorInteraction(bool)), SLOT(slotColorInteraction(bool)));
113
114 connect(WGConfig::notifier(), SIGNAL(configChanged()), SLOT(slotConfigurationChanged()));
115
116 setWidget(mainWidget);
118 setEnabled(false);
119}
120
122{
123 // currently always return foreground model;
124 // do lazy conversion to current HSX model if required
125 if (selectingBackground() && m_colorModelBG->isHSXModel()) {
126 m_colorModelFG->setRGBColorModel(m_colorModelBG->colorModel());
127 }
128 return *(m_colorModelFG);
129}
130
132{
133 KisDisplayColorConverter *converter = nullptr;
134 if (m_canvas) {
135 converter = m_canvas->displayColorConverter();
136 }
137 return (rawPointer || converter) ? converter : KisDisplayColorConverter::dumbConverterInstance();
138}
139
141{
142 return m_toggle->isChecked();
143}
144
145void WGColorSelectorDock::setChannelValues(const QVector4D &values)
146{
147 // currently always set foreground color
148 if (!m_canvas) {
149 return;
150 }
151
152 // This could be nicer...if setting active model, this triggers slotColorSelected()
153 // and leaves timer running with NOP, otherwise the resource update is detected as
154 // external event and updates UI.
155 m_colorModelFG->slotSetChannelValues(values);
156
157 m_canvas->resourceManager()->setForegroundColor(m_colorModelFG->currentColor());
158 m_pendingFgUpdate = false;
159}
160
162{
163 Q_UNUSED(event)
164 m_colorTooltip->hide();
165}
166
172
174{
175 if (m_canvas.data() == canvas)
176 {
177 // not sure why setCanvas gets called 3 times for new canvas, just skip
178 return;
179 }
180 if (m_canvas) {
182 }
183 m_actionManager->setCanvas(qobject_cast<KisCanvas2*>(canvas), m_canvas);
184 m_canvas = qobject_cast<KisCanvas2*>(canvas);
185 // TODO: unset display converters if canvas is null
186 if (m_canvas) {
187 KoColorDisplayRendererInterface *dri = m_canvas->displayColorConverter()->displayRendererInterface();
188 KisCanvasResourceProvider *resourceProvider = m_canvas->imageView()->resourceProvider();
189
190 m_globalColorHistoryModel = resourceProvider->colorHistoryModel();
191 m_documentColorHistoryModel = m_canvas->imageView()->document()->colorHistoryModel();
192
195
197 m_displayConfig->setDisplayConverter(m_canvas->displayColorConverter());
199 //m_toggle->setBackgroundColor(dri->toQColor(color));
200 connect(dri, SIGNAL(displayConfigurationChanged()), this, SLOT(slotDisplayConfigurationChanged()));
201 connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
202 this, SLOT(slotCanvasResourceChanged(int,QVariant)));
203 connect(resourceProvider, SIGNAL(sigFGColorUsed(KoColor)),
204 this, SLOT(slotFGColorUsed(KoColor)), Qt::UniqueConnection);
205
206 // Gamut Mask
207 connect(resourceProvider, SIGNAL(sigGamutMaskChanged(KoGamutMaskSP)),
208 m_selector, SLOT(slotGamutMaskChanged(KoGamutMaskSP)), Qt::UniqueConnection);
209
210 connect(resourceProvider, SIGNAL(sigGamutMaskPreviewUpdate()),
211 m_selector, SLOT(slotGamutMaskPreviewUpdate()), Qt::UniqueConnection);
212
213 connect(resourceProvider, SIGNAL(sigGamutMaskUnset()),
214 m_selector, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection);
215
216 connect(resourceProvider, SIGNAL(sigGamutMaskDeactivated()),
217 m_selector, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection);
218
219 m_gamutToolbar->connectMaskSignals(resourceProvider);
220
221 // quirk note: displayConfigurationChanged signal gets sent *before* the new canvas gets
222 // passed, through the display converter of the now inactive canvas! So we need to repeat...
224 }
225 setEnabled(canvas != 0);
226}
227
240
245
247{
248 m_canvas->disconnectCanvasObserver(this);
249 m_canvas->displayColorConverter()->displayRendererInterface()->disconnect(this);
250 m_canvas->imageView()->resourceProvider()->disconnect(m_selector);
251 m_canvas = 0;
252}
253
255{
257
258 bool historyEnabled = cfg.get(WGConfig::colorHistoryEnabled);
259 Qt::Orientation historyOrientation = cfg.get(WGConfig::colorHistory.orientation);
260
261 m_verticalElementsLayout->removeWidget(m_history);
263 m_mainWidgetLayout->removeWidget(m_history);
264 m_mainWidgetLayout->removeWidget(m_commonColors);
265
266 if (historyEnabled) {
267 if (historyOrientation == Qt::Vertical) {
269 }
270 else {
271 m_mainWidgetLayout->addWidget(m_history);
272 }
273 m_history->show();
274 }
275 else {
276 m_history->hide();
277 }
278
279 bool commonColorsEnabled = cfg.get(WGConfig::commonColorsEnabled);
280 Qt::Orientation commonColorsOrientation = cfg.get(WGConfig::commonColors.orientation);
281
282 if (commonColorsEnabled) {
283 if (commonColorsOrientation == Qt::Vertical) {
285 }
286 else {
288 }
289 m_commonColors->show();
290 }
291 else {
292 m_commonColors->hide();
293 }
294
295 bool shadeSelectorEnabled = cfg.get(WGConfig::minimalShadeSelectorEnabled);
296 if (shadeSelectorEnabled) {
297 m_shadeSelector->show();
298 }
299 else {
300 m_shadeSelector->hide();
301 }
302
303}
304
306{
309 m_selector->selectorModel()->setRGBColorModel(cfg.get(WGConfig::rgbColorModel));
310 KisColorSelectorConfiguration selectorCfg = cfg.colorSelectorConfiguration();
311 m_selector->setConfiguration(&selectorCfg);
314 m_customCS = cfg.customSelectionColorSpace();
315 }
316 bool proofColors = cfg.get(WGConfig::proofToPaintingColors);
317 m_selector->setProofColors(proofColors);
318 m_displayConfig->setPreviewInPaintingCS(proofColors);
320
325
328 // Quick settings menu
329 if (cfg.get(WGConfig::quickSettingsEnabled)) {
330 if (!m_configButton->menu()) {
331 m_configButton->disconnect(this);
332 QMenu *configureMenu = new QMenu(this);
334 // prevents hover indicator being stuck on other menu entries
335 m_quickSettings->setMouseTracking(true);
336 m_quickSettingAction = new QWidgetAction(this);
337 m_quickSettingAction->setDefaultWidget(m_quickSettings);
338
339 configureMenu->addAction(m_quickSettingAction);
340 QAction *cfgAction = configureMenu->addAction(i18nc("Wide Gamut Color Selector", "Configure..."));
341 connect(cfgAction, SIGNAL(triggered(bool)), SLOT(slotOpenSettings()));
342 m_configButton->setMenu(configureMenu);
343 } else {
344 // WORKAROUND: force geometry update by re-adding action, all other attempts failed...
345 QMenu *menu = m_configButton->menu();
346 menu->removeAction(m_quickSettingAction);
347 menu->insertAction(menu->actions().constFirst(), m_quickSettingAction);
348 }
350 } else {
351 if (m_configButton->menu()) {
352 m_configButton->menu()->deleteLater();
353 m_configButton->setMenu(0);
356 m_quickSettings = 0;
357 }
358 connect(m_configButton, SIGNAL(clicked(bool)), SLOT(slotOpenSettings()), Qt::UniqueConnection);
359 }
360
361 updateLayout();
362
363 if (m_canvas) {
365 }
366}
367
369{
370 if (!m_canvas) {
371 return;
372 }
373
374 const KoColorSpace *selectionCS = nullptr;
375
376 // Note: displayConfigurationChanged is also emitted on image color space changes,
377 // so there's no need to handle extra signals, although it's a bit convoluted
379 selectionCS = m_canvas->image()->colorSpace();
380 } else if (m_CSSource == FixedColorSpace) {
381 selectionCS = m_customCS;
382 } else {
383 selectionCS = m_canvas->displayColorConverter()->nodeColorSpace();
384 }
385
386 // TODO: use m_viewManager->canvasResourceProvider()->fgColor();
387 KoColor fgColor = m_canvas->resourceManager()->foregroundColor();
388 KoColor bgColor = m_canvas->resourceManager()->backgroundColor();
389
390 bool proof = m_displayConfig->previewInPaintingCS();
391 m_toggle->setForegroundColor(displayColorConverter()->toQColor(fgColor, proof));
392 m_toggle->setBackgroundColor(displayColorConverter()->toQColor(bgColor, proof));
394
395 if (selectionCS && selectionCS != activeModel->colorSpace()) {
396 activeModel->slotSetColorSpace(selectionCS);
397 activeModel->slotSetColor(activeModel == m_colorModelFG ? fgColor : bgColor);
398 }
399}
400
402{
403 QColor displayCol = displayColorConverter()->toQColor(color, m_displayConfig->previewInPaintingCS());
404 m_colorTooltip->setCurrentColor(displayCol);
405 if (selectingBackground()) {
406 m_toggle->setBackgroundColor(displayCol);
407 m_pendingBgUpdate = true;
409 }
410 else {
411 m_toggle->setForegroundColor(displayCol);
412 m_pendingFgUpdate = true;
414 }
415 if (sender() != m_selector) {
416 m_selector->slotSetColor(color);
417 }
418}
419
421{
422 if (selectingBg) {
423 if (m_colorModelFG->isHSXModel()) {
424 m_colorModelBG->setRGBColorModel(m_colorModelFG->colorModel());
425 }
428 }
429 else {
430 if (m_colorModelBG->isHSXModel()) {
431 m_colorModelFG->setRGBColorModel(m_colorModelBG->colorModel());
432 }
435 }
436 // currently, only the color space of the active model is updated, so it may be outdated
437 if (m_canvas) {
439 }
440}
441
443{
444 if (active) {
445 QColor baseCol = m_displayConfig->displayConverter()->toQColor(m_selector->getCurrentColor());
448 if (sender() == m_shadeSelector) {
450 } else {
451 m_colorTooltip->show(this);
452 }
453 }
454}
455
457{
458 QColor lastCol = m_displayConfig->displayConverter()->toQColor(color);
463 } else {
465 }
466}
467
469{
470 //KIS_SAFE_ASSERT_RECOVER_RETURN(m_pendingFgUpdate || m_pendingBgUpdate);
471 if (m_pendingFgUpdate) {
472 m_canvas->resourceManager()->setForegroundColor(m_colorModelFG->currentColor());
473 m_pendingFgUpdate = false;
474 }
475 if (m_pendingBgUpdate) {
476 m_canvas->resourceManager()->setBackgroundColor(m_colorModelBG->currentColor());
477 m_pendingBgUpdate = false;
478 }
479}
480
482{
483 switch (key) {
485 if (!m_pendingFgUpdate) {
486 KoColor color = value.value<KoColor>();
488 m_colorModelFG->slotSetColor(color);
489 }
490 break;
492 if (!m_pendingBgUpdate) {
493 KoColor color = value.value<KoColor>();
495 m_colorModelBG->slotSetColor(color);
496 }
497 default:
498 break;
499 }
500}
501
503{
504 if (!m_canvas) return;
505
507 if (settings.exec() == QDialog::Accepted) {
508 //WGConfig::notifier()->notifyConfigChanged();
509 }
510}
511
513{
514 m_gamutToolbar->setVisible(show);
515}
516
517namespace WGConfig {
523}
float value(const T *src, size_t ch)
KisUniqueColorSet * colorHistoryModel() const
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 setColorHistoryModel(KisUniqueColorSet *history)
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
KisUniqueColorSet * colorHistoryModel() const
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
KisUniqueColorSet * m_documentColorHistoryModel
void slotCanvasResourceChanged(int key, const QVariant &value)
std::unique_ptr< KisUniqueColorSet > m_fallbackColorHistoryModel
KisVisualColorSelector * m_selector
QBoxLayout * m_verticalElementsLayout
KisDisplayColorConverter * displayColorConverter(bool rawPointer=false) const
KisUniqueColorSet * m_globalColorHistoryModel
void setChannelValues(const QVector4D &values)
Set new channel values; takes effect immediately!
ColorSpaceSource m_CSSource
WGColorPatches * m_commonColors
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 > colorHistoryFromDocument
Definition WGConfig.cpp:239
const GenericSetting< bool > minimalShadeSelectorEnabled
Definition WGConfig.cpp:247
const GenericSetting< bool > commonColorsEnabled
Definition WGConfig.cpp:240
const NumericSetting< KisVisualColorSelector::RenderMode > selectorRenderMode
Definition WGConfig.cpp:256
const NumericSetting< WGColorSelectorDock::ColorSpaceSource > colorSpaceSource
WGConfigNotifier * notifier()
Definition WGConfig.cpp:190
const NumericSetting< KisVisualColorModel::ColorModel > rgbColorModel
Definition WGConfig.cpp:253
class WGConfig Accessor
const GenericSetting< bool > proofToPaintingColors
Definition WGConfig.cpp:237
const GenericSetting< bool > quickSettingsEnabled
Definition WGConfig.cpp:244
const GenericSetting< bool > commonColorsAutoUpdate
Definition WGConfig.cpp:242
const ColorPatches colorHistory
Definition WGConfig.cpp:213