Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tool_colorsampler.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 1999 Matthias Elter <me@kde.org>
3 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
4 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
5 * SPDX-FileCopyrightText: 2018 Emmet & Eoin O'Neill <emmetoneill.pdx@gmail.com>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
11
12#include <kis_cursor.h>
13#include <kis_canvas2.h>
14#include <KoCanvasBase.h>
19#include <KisResourceTypes.h>
20#include <KisViewManager.h>
22#include "kis_tool_utils.h"
23
24#include <kis_config.h>
25#include <kis_config_notifier.h>
27#include <QSignalBlocker>
28
29namespace
30{
31// GUI ComboBox index constants
32const int SAMPLE_MERGED = 0;
33}
34
36 : KisTool(canvas, KisCursor::samplerCursor()),
37 m_config(new KisToolUtils::ColorSamplerConfig),
38 m_helper(dynamic_cast<KisCanvas2*>(canvas))
39{
40 setObjectName("tool_colorsampler");
41 connect(&m_helper, SIGNAL(sigRequestCursor(QCursor)), this, SLOT(slotColorPickerRequestedCursor(QCursor)));
42 connect(&m_helper, SIGNAL(sigRequestCursorReset()), this, SLOT(slotColorPickerRequestedCursorReset()));
43 connect(&m_helper, SIGNAL(sigRequestUpdateOutline()), this, SLOT(slotColorPickerRequestedOutlineUpdate()));
44 connect(&m_helper, SIGNAL(sigRawColorSelected(KoColor)), this, SLOT(slotColorPickerSelectedColor(KoColor)));
45 connect(&m_helper, SIGNAL(sigFinalColorSelected(KoColor)), this, SLOT(slotColorPickerSelectionFinished(KoColor)));
46}
47
54
59
65
70
80
82{
83 Q_UNUSED(color);
84
85 if (m_config->addColorToCurrentPalette) {
86 KisSwatch swatch;
87 swatch.setColor(color);
88 // We don't ask for a name, too intrusive here
89
90 QModelIndex idx = m_tagFilterProxyModel->index(m_optionsWidget->cmbPalette->currentIndex(), 0);
91 KoColorSetSP palette = qSharedPointerDynamicCast<KoColorSet>(m_tagFilterProxyModel->resourceForIndex(idx));
92
93 if (palette) {
94 KisSwatchGroup::SwatchInfo info =
95 palette->getClosestSwatchInfo(color);
96
97 if (info.swatch.color() != color) {
98 palette->addSwatch(swatch);
99 }
100 }
101 }
102}
103
105{
106 if (m_optionsWidget) {
107 QSignalBlocker blocker(m_optionsWidget->cmbPreviewStyle);
109 KisConfig(true).colorSamplerPreviewStyle());
110 }
111}
112
121
122void KisToolColorSampler::paint(QPainter &gc, const KoViewConverter &converter)
123{
124 m_helper.paint(gc, converter);
125}
126
127void KisToolColorSampler::activate(const QSet<KoShape*> &shapes)
128{
129
130 m_isActivated = true;
131 m_config->load();
132
134
135 KisTool::activate(shapes);
136}
137
139{
140 m_config->save();
141
142 m_isActivated = false;
144}
145
147{
149
150 bool useOtherColor = canvas()->resourceManager()->boolResource(KoCanvasResource::UsingOtherColor);
151 // if useOtherColor is true, apply to the other color than that configured in the tool options
152 m_helper.activate(!m_config->sampleMerged, m_config->toForegroundColor != useOtherColor);
153 m_helper.startAction(event->point, m_config->radius, m_config->blend);
154 requestUpdateOutline(event->point, event);
155
157}
158
162
170
181{
186 bool useOtherColor = canvas()->resourceManager()->boolResource(KoCanvasResource::UsingOtherColor);
187 // if useOtherColor is true, apply to the other color than that configured in the tool options
188 m_helper.updateCursor(!m_config->sampleMerged, m_config->toForegroundColor != useOtherColor);
189}
190
198
199void KisToolColorSampler::requestUpdateOutline(const QPointF &outlineDocPoint, const KoPointerEvent *event)
200{
201 Q_UNUSED(event);
202
203 KisConfig cfg(true);
204
205 QRectF colorPreviewDocUpdateRect;
206
207 qreal zoomX;
208 qreal zoomY;
209 canvas()->viewConverter()->zoom(&zoomX, &zoomY);
210 qreal xoffset = 2.0/zoomX;
211 qreal yoffset = 2.0/zoomY;
212
213 m_outlineDocPoint = outlineDocPoint;
214
215 colorPreviewDocUpdateRect = m_helper.colorPreviewDocRect(m_outlineDocPoint);
216
217 if (!colorPreviewDocUpdateRect.isEmpty()) {
218 colorPreviewDocUpdateRect = colorPreviewDocUpdateRect.adjusted(-xoffset,-yoffset,xoffset,yoffset);
219 }
220
221 if (!m_oldColorPreviewUpdateRect.isEmpty()){
223 }
224
225 if (!colorPreviewDocUpdateRect.isEmpty()){
226 canvas()->updateCanvas(colorPreviewDocUpdateRect);
227 }
228
229 m_oldColorPreviewUpdateRect = colorPreviewDocUpdateRect;
230}
231
232
234 QString name;
235 QString valueText;
236};
237
239{
240 if (color.data() && m_optionsWidget) {
241
242 const QList<KoChannelInfo *> channels = color.colorSpace()->channels();
243 m_optionsWidget->listViewChannels->clear();
244
245 QVector<SampledChannel> sampledChannels;
246 for (int i = 0; i < channels.count(); ++i) {
247 sampledChannels.append(SampledChannel());
248 }
249
250 for (int i = 0; i < channels.count(); ++i) {
251
253 pc.name = channels[i]->name();
254
255 if (m_config->normaliseValues) {
256 pc.valueText = color.colorSpace()->normalisedChannelValueText(color.data(), i);
257 } else {
258 pc.valueText = color.colorSpace()->channelValueText(color.data(), i);
259 }
260
261 sampledChannels[channels[i]->displayPosition()] = pc;
262
263 }
264
265 Q_FOREACH (const SampledChannel &pc, sampledChannels) {
266 QTreeWidgetItem *item = new QTreeWidgetItem(m_optionsWidget->listViewChannels);
267 item->setText(0, pc.name);
268 item->setText(1, pc.valueText);
269 }
270
271
272 if (qEnvironmentVariableIsSet("KRITA_DEBUG_DISPLAY_COLOR")) {
273 KisCanvas2 *kritaCanvas = dynamic_cast<KisCanvas2*>(canvas());
274 KIS_ASSERT(kritaCanvas);
277
278 QVector<float> values(4);
279 newColor.colorSpace()->normalisedChannelsValue(newColor.data(), values);
280
281 for (int i = 0; i < values.size(); i++) {
282 QTreeWidgetItem *item = new QTreeWidgetItem(m_optionsWidget->listViewChannels);
283 item->setText(0, QString("DisplayCh%1").arg(i));
284 item->setText(1, QString::number(values[i]));
285 }
286 }
287 }
288}
289
291{
293 m_optionsWidget->setObjectName(toolId() + " option widget");
294 m_optionsWidget->listViewChannels->setSortingEnabled(false);
295
296 // See https://bugs.kde.org/show_bug.cgi?id=316896
297 QWidget *specialSpacer = new QWidget(m_optionsWidget);
298 specialSpacer->setObjectName("SpecialSpacer");
299 specialSpacer->setFixedSize(0, 0);
300 m_optionsWidget->layout()->addWidget(specialSpacer);
301
305 this,
307 connect(m_optionsWidget->cmbPreviewStyle,
308 QOverload<int>::of(&QComboBox::activated),
309 this,
311
312 // Initialize blend KisSliderSpinBox
313 m_optionsWidget->blend->setRange(0,100);
315 i18nc("{n} is the number value, % is the percent sign", "{n}%"));
316
318
319 connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool)));
320 connect(m_optionsWidget->cbNormaliseValues, SIGNAL(toggled(bool)), SLOT(slotSetNormaliseValues(bool)));
321 connect(m_optionsWidget->cbPalette, SIGNAL(toggled(bool)),
322 SLOT(slotSetAddPalette(bool)));
323 connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)),
324 SLOT(slotChangeRadius(int)));
325 connect(m_optionsWidget->blend, SIGNAL(valueChanged(int)),
326 SLOT(slotChangeBlend(int)));
327 connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)),
328 SLOT(slotSetColorSource(int)));
329
331 m_optionsWidget->cmbPalette->setModel(m_tagFilterProxyModel);
332 m_optionsWidget->cmbPalette->setModelColumn(KisAbstractResourceModel::Name);
333 m_tagFilterProxyModel->sort(Qt::DisplayRole);
334
335
336 KConfigGroup config = KSharedConfig::openConfig()->group(toolId());
337 QString paletteName = config.readEntry("ColorSamplerPalette", "");
338 if (!paletteName.isEmpty()) {
339 for (int i = 0; i < m_tagFilterProxyModel->rowCount(); i++) {
340 QModelIndex idx = m_tagFilterProxyModel->index(i, 0);
341 QString name = m_tagFilterProxyModel->data(idx, Qt::UserRole + KisAbstractResourceModel::Name).toString();
342 if (name == paletteName) {
343 m_optionsWidget->cmbPalette->setCurrentIndex(i);
344 break;
345 }
346 }
347 }
348
349 connect(m_optionsWidget->cmbPalette, SIGNAL(currentIndexChanged(int)), SLOT(slotChangePalette(int)));
350
351 return m_optionsWidget;
352}
353
355{
356 if (!m_optionsWidget) return;
357
358 m_optionsWidget->cbNormaliseValues->setChecked(m_config->normaliseValues);
359 m_optionsWidget->cbUpdateCurrentColor->setChecked(m_config->updateColor);
360 m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged);
361 m_optionsWidget->cbPalette->setChecked(m_config->addColorToCurrentPalette);
362 m_optionsWidget->radius->setValue(m_config->radius);
363 m_optionsWidget->blend->setValue(m_config->blend);
364
366}
367
369{
370 m_config->updateColor = state;
371}
372
374{
375 m_config->normaliseValues = state;
377}
378
380{
381 m_config->addColorToCurrentPalette = state;
382}
383
388
393
395{
396 m_config->sampleMerged = value == SAMPLE_MERGED;
397}
398
400{
401 QString paletteName = m_optionsWidget->cmbPalette->currentData(Qt::UserRole + KisAbstractResourceModel::Name).toString();
402 KConfigGroup config = KSharedConfig::openConfig()->group(toolId());
403 config.writeEntry("ColorSamplerPalette", paletteName);
404}
float value(const T *src, size_t ch)
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
static KisConfig::ColorSamplerPreviewStyle getColorSamplerPreviewStyleValue(const QComboBox *cmb)
static void setColorSamplerPreviewStyleItems(QComboBox *cmb)
static void setColorSamplerPreviewStyleIndexByValue(QComboBox *cmb, KisConfig::ColorSamplerPreviewStyle style)
void activate(bool sampleCurrentLayer, bool pickFgColor)
void paint(QPainter &gc, const KoViewConverter &converter)
void updateCursor(bool sampleCurrentLayer, bool pickFgColor)
void continueAction(const QPointF &docPoint)
void startAction(const QPointF &docPoint, int radius, int blend)
QRectF colorPreviewDocRect(const QPointF &docPoint)
KisDisplayColorConverter displayColorConverter
void updateCanvas(const QRectF &rc) override
const KoViewConverter * viewConverter() const override
static KisConfigNotifier * instance()
void sigColorSamplerPreviewStyleChanged()
ColorSamplerPreviewStyle
Definition kis_config.h:138
void setColorSamplerPreviewStyle(ColorSamplerPreviewStyle style)
KoColor applyDisplayFiltering(const KoColor &srcColor, const KoID &bitDepthId) const
void setColor(const KoColor &color)
Definition KisSwatch.cpp:32
The KisTagFilterResourceProxyModel class filters the resources by tag or resource name.
KoResourceSP resourceForIndex(QModelIndex index=QModelIndex()) const override
resourceForIndex returns a properly versioned and id'ed resource object
void slotSetColorSource(int value)
KisTagFilterResourceProxyModel * m_tagFilterProxyModel
void slotColorPickerRequestedCursor(const QCursor &cursor)
void paint(QPainter &gc, const KoViewConverter &converter) override
QWidget * createOptionWidget() override
void displaySampledColor(const KoColor &color)
void slotColorPickerSelectedColor(const KoColor &color)
void endPrimaryAction(KoPointerEvent *event) override
QScopedPointer< KisToolUtils::ColorSamplerConfig > m_config
void beginPrimaryAction(KoPointerEvent *event) override
void continuePrimaryAction(KoPointerEvent *event) override
void activate(const QSet< KoShape * > &) override
KisToolColorSampler(KoCanvasBase *canvas)
ColorSamplerOptionsWidget * m_optionsWidget
KisAsyncColorSamplerHelper m_helper
void deactivatePrimaryAction() override
void requestUpdateOutline(const QPointF &outlineDocPoint, const KoPointerEvent *event)
void activatePrimaryAction() override
void slotColorPickerSelectionFinished(const KoColor &color)
void mouseMoveEvent(KoPointerEvent *event) override
QPointer< KoCanvasResourceProvider > resourceManager
virtual QString channelValueText(const quint8 *pixel, quint32 channelIndex) const =0
QList< KoChannelInfo * > channels
virtual KoID colorModelId() const =0
virtual void normalisedChannelsValue(const quint8 *pixel, QVector< float > &channels) const =0
virtual QString normalisedChannelValueText(const quint8 *pixel, quint32 channelIndex) const =0
quint8 * data()
Definition KoColor.h:144
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
QPointF point
The point in document coordinates.
Q_INVOKABLE QString toolId() const
void useCursor(const QCursor &cursor)
virtual void zoom(qreal *zoomX, qreal *zoomY) const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
#define CHECK_MODE_SANITY_OR_RETURN(_mode)
Definition kis_tool.h:27
void setText(QSpinBox *spinBox, const QStringView textTemplate)
const QString Palettes
rgba palette[MAX_PALETTE]
Definition palette.c:35
void mouseMoveEvent(KoPointerEvent *event) override
Definition kis_tool.cc:520
void activate(const QSet< KoShape * > &shapes) override
Definition kis_tool.cc:93
void deactivate() override
Definition kis_tool.cc:131
@ PAINT_MODE
Definition kis_tool.h:300
QCursor cursor
Definition kis_tool.cc:64
virtual void setMode(ToolMode mode)
Definition kis_tool.cc:403
KisCanvas2 * canvas