Commit 851a193f authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Added an ability to pick colors from the Color To Alpha filter

This patch makes several quite significant changes:
1) KisToolPickColor now saves (!) its configuration to the disk! So you'll
   have your options loaded on the next run of Krita
2) KisToolPickColor now has two sets of settings: for temporary activation
   (the one used in filters) and for usual activation. They both are
   load/save'able.
3) The KoToolManager's methods for temporary switching of the tool are now
   made public. I guess, they were made private initially, because there was
   no usecase for it those days.

So the interaction with the color2alpha filter is the following:

1) You open a filter
2) The filter activates the picker tool
3) You can pick colors and change options of the tool: these changes will
   not affect your normal settings
4) When you press Ok/Cancel the original tool is reactivated

Known bugs:
Color Picking doesn't work with Adj. Layers and Filter Masks :(

CCBUG:316985
parent b59f44eb
......@@ -25,6 +25,10 @@
#include <kcolorbutton.h>
#include <KoColor.h>
#include <kis_view2.h>
#include <kis_canvas_resource_provider.h>
#include <filter/kis_filter.h>
#include <filter/kis_filter_configuration.h>
#include <kis_selection.h>
......@@ -33,7 +37,9 @@
#include "ui_wdgcolortoalphabase.h"
KisWdgColorToAlpha::KisWdgColorToAlpha(QWidget * parent) : KisConfigWidget(parent)
KisWdgColorToAlpha::KisWdgColorToAlpha(QWidget * parent)
: KisConfigWidget(parent),
m_view(0)
{
m_widget = new Ui_WdgColorToAlphaBase();
m_widget->setupUi(this);
......@@ -43,9 +49,24 @@ KisWdgColorToAlpha::KisWdgColorToAlpha(QWidget * parent) : KisConfigWidget(paren
KisWdgColorToAlpha::~KisWdgColorToAlpha()
{
KoToolManager::instance()->switchBackRequested();
delete m_widget;
}
void KisWdgColorToAlpha::setView(KisView2 *view)
{
m_view = view;
connect(view->resourceProvider(), SIGNAL(sigFGColorChanged(const KoColor&)), this, SLOT(slotFgColorChanged(const KoColor&)));
KoToolManager::instance()->switchToolTemporaryRequested("KritaSelected/KisToolColorPicker");
}
void KisWdgColorToAlpha::slotFgColorChanged(const KoColor &color)
{
m_widget->colorSelector->setQColor(color.toQColor());
emit sigConfigurationItemChanged();
}
void KisWdgColorToAlpha::setConfiguration(const KisPropertiesConfiguration* config)
{
QVariant value;
......
......@@ -23,9 +23,11 @@
#include <kis_config_widget.h>
class KoColor;
class KisFilter;
class Ui_WdgColorToAlphaBase;
class KisWdgColorToAlpha : public KisConfigWidget
{
Q_OBJECT
......@@ -35,10 +37,18 @@ public:
inline const Ui_WdgColorToAlphaBase* widget() const {
return m_widget;
}
void setView(KisView2 *view);
virtual void setConfiguration(const KisPropertiesConfiguration*);
virtual KisPropertiesConfiguration* configuration() const;
private slots:
void slotFgColorChanged(const KoColor &color);
private:
Ui_WdgColorToAlphaBase* m_widget;
KisView2 *m_view;
};
#endif
......@@ -39,6 +39,7 @@
#include "kis_cursor.h"
#include "kis_image.h"
#include "kis_paint_device.h"
#include "kis_properties_configuration.h"
#include "kis_tool_colorpicker.moc"
#include "KoPointerEvent.h"
......@@ -50,34 +51,104 @@
namespace
{
// The location of the sample all visible layers in the combobox
const int SAMPLE_MERGED = 0;
// The location of the sample all visible layers in the combobox
const int SAMPLE_MERGED = 0;
const QString CONFIG_GROUP_NAME = "tool_color_picker";
}
KisToolColorPicker::Configuration::Configuration()
: toForegroundColor(true),
updateColor(true),
addPalette(false),
normaliseValues(false),
sampleMerged(true),
radius(1)
{
}
inline QString getConfigKey(KisTool::ToolActivation activation) {
QString configKey;
switch (activation) {
case KisTool::TemporaryActivation:
configKey = "ColorPickerTemporaryActivation";
break;
case KisTool::DefaultActivation:
configKey = "ColorPickerDefaultActivation";
break;
};
return configKey;
}
void KisToolColorPicker::Configuration::save(ToolActivation activation) const
{
KisPropertiesConfiguration props;
props.setProperty("toForegroundColor", toForegroundColor);
props.setProperty("updateColor", updateColor);
props.setProperty("addPalette", addPalette);
props.setProperty("normaliseValues", normaliseValues);
props.setProperty("sampleMerged", sampleMerged);
props.setProperty("radius", radius);
KConfigGroup config = KGlobal::config()->group(CONFIG_GROUP_NAME);
config.writeEntry(getConfigKey(activation), props.toXML());
}
void KisToolColorPicker::Configuration::load(ToolActivation activation)
{
KisPropertiesConfiguration props;
KConfigGroup config = KGlobal::config()->group(CONFIG_GROUP_NAME);
props.fromXML(config.readEntry(getConfigKey(activation)));
toForegroundColor = props.getBool("toForegroundColor", true);
updateColor = props.getBool("updateColor", true);
addPalette = props.getBool("addPalette", false);
normaliseValues = props.getBool("normaliseValues", false);
sampleMerged = props.getBool("sampleMerged", activation == KisTool::TemporaryActivation ? false : true);
radius = props.getInt("radius", 1);
}
KisToolColorPicker::KisToolColorPicker(KoCanvasBase* canvas)
: KisTool(canvas, KisCursor::pickerCursor())
{
setObjectName("tool_colorpicker");
m_isActivated = false;
m_optionsWidget = 0;
m_radius = 1;
m_addPalette = false;
m_updateColor = true;
m_normaliseValues = false;
m_pickedColor = KoColor();
m_toForegroundColor = true;
}
KisToolColorPicker::~KisToolColorPicker()
{
if (m_isActivated) {
m_config.save(m_toolActivationSource);
}
}
void KisToolColorPicker::paint(QPainter& gc, const KoViewConverter &converter)
{
Q_UNUSED(gc);
Q_UNUSED(converter);
}
void KisToolColorPicker::activate(ToolActivation activation, const QSet<KoShape*> &shapes)
{
m_isActivated = true;
m_toolActivationSource = activation;
m_config.load(m_toolActivationSource);
updateOptionWidget();
KisTool::activate(activation, shapes);
}
void KisToolColorPicker::deactivate()
{
m_config.save(m_toolActivationSource);
m_isActivated = false;
KisTool::deactivate();
}
void KisToolColorPicker::pickColor(const QPointF& pos)
{
if(m_colorPickerDelayTimer.isActive()) {
......@@ -103,7 +174,7 @@ void KisToolColorPicker::pickColor(const QPointF& pos)
dev = currentImage()->projection();
}
if (m_radius == 1) {
if (m_config.radius == 1) {
dev->pixel(pos.x(), pos.y(), &m_pickedColor);
} else {
// radius 2 ==> 9 pixels, 3 => 9 pixels, etc
......@@ -113,15 +184,15 @@ void KisToolColorPicker::pickColor(const QPointF& pos)
int pixelSize = cs->pixelSize();
quint8* data = new quint8[pixelSize];
quint8** pixels = new quint8*[counts[m_radius]];
qint16* weights = new qint16[counts[m_radius]];
quint8** pixels = new quint8*[counts[m_config.radius]];
qint16* weights = new qint16[counts[m_config.radius]];
int i = 0;
KisRandomConstAccessorSP accessor = dev->createRandomConstAccessorNG(0, 0);
for (int y = -m_radius; y <= m_radius; y++) {
for (int x = -m_radius; x <= m_radius; x++) {
if (((x * x) + (y * y)) < m_radius * m_radius) {
for (int y = -m_config.radius; y <= m_config.radius; y++) {
for (int x = -m_config.radius; x <= m_config.radius; x++) {
if (((x * x) + (y * y)) < m_config.radius * m_config.radius) {
accessor->moveTo(pos.x() + x, pos.y() + y);
......@@ -134,9 +205,9 @@ void KisToolColorPicker::pickColor(const QPointF& pos)
// to sum to 255 in total
// It's -(counts -1), because we'll add the center one implicitly
// through that calculation
weights[i] = 255 - (counts[m_radius] - 1) * (255 / counts[m_radius]);
weights[i] = 255 - (counts[m_config.radius] - 1) * (255 / counts[m_config.radius]);
} else {
weights[i] = 255 / counts[m_radius];
weights[i] = 255 / counts[m_config.radius];
}
i++;
}
......@@ -144,18 +215,18 @@ void KisToolColorPicker::pickColor(const QPointF& pos)
}
// Weird, I can't do that directly :/
const quint8** cpixels = const_cast<const quint8**>(pixels);
cs->mixColorsOp()->mixColors(cpixels, weights, counts[m_radius], data);
cs->mixColorsOp()->mixColors(cpixels, weights, counts[m_config.radius], data);
m_pickedColor = KoColor(data, cs);
for (i = 0; i < counts[m_radius]; i++){
for (i = 0; i < counts[m_config.radius]; i++){
delete[] pixels[i];
}
delete[] pixels;
delete[] data;
}
if (m_updateColor) {
if (m_toForegroundColor)
if (m_config.updateColor) {
if (m_config.toForegroundColor)
canvas()->resourceManager()->setResource(KoCanvasResourceManager::ForegroundColor, m_pickedColor);
else
canvas()->resourceManager()->setResource(KoCanvasResourceManager::BackgroundColor, m_pickedColor);
......@@ -192,7 +263,7 @@ void KisToolColorPicker::mousePressEvent(KoPointerEvent *event)
return;
}
m_toForegroundColor = (event->button() == Qt::LeftButton);
//m_toForegroundColor = (event->button() == Qt::LeftButton);
pickColor(pos);
displayPickedColor();
}
......@@ -218,7 +289,7 @@ void KisToolColorPicker::mouseReleaseEvent(KoPointerEvent *event)
if(RELEASE_CONDITION_WB(event, KisTool::PAINT_MODE, Qt::LeftButton | Qt::RightButton)) {
setMode(KisTool::HOVER_MODE);
if (m_addPalette) {
if (m_config.addPalette) {
KoColorSetEntry ent;
ent.color = m_pickedColor;
// We don't ask for a name, too intrusive here
......@@ -247,7 +318,7 @@ void KisToolColorPicker::displayPickedColor()
QString channelValueText;
int pos = channels[i]->pos() / channels[i]->size(); // HACK This doesn't work if the channels differ in size
if (m_normaliseValues) {
if (m_config.normaliseValues) {
channelValueText = m_pickedColor.colorSpace()->normalisedChannelValueText(m_pickedColor.data(), pos);
} else {
channelValueText = m_pickedColor.colorSpace()->channelValueText(m_pickedColor.data(), pos);
......@@ -264,22 +335,18 @@ QWidget* KisToolColorPicker::createOptionWidget()
{
m_optionsWidget = new ColorPickerOptionsWidget(0);
m_optionsWidget->setObjectName(toolId() + " option widget");
m_optionsWidget->cbUpdateCurrentColor->setChecked(m_updateColor);
m_optionsWidget->cmbSources->setCurrentIndex(0);
m_optionsWidget->cbNormaliseValues->setChecked(m_normaliseValues);
m_optionsWidget->cbPalette->setChecked(m_addPalette);
m_optionsWidget->radius->setValue(m_radius);
m_optionsWidget->listViewChannels->setSortingEnabled(false);
updateOptionWidget();
connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool)));
connect(m_optionsWidget->cbNormaliseValues, SIGNAL(toggled(bool)), SLOT(slotSetNormaliseValues(bool)));
connect(m_optionsWidget->cbPalette, SIGNAL(toggled(bool)),
SLOT(slotSetAddPalette(bool)));
connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)),
SLOT(slotChangeRadius(int)));
connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)),
SLOT(slotSetColorSource(int)));
KoResourceServer<KoColorSet>* srv = KoResourceServerProvider::instance()->paletteServer();
......@@ -298,31 +365,47 @@ QWidget* KisToolColorPicker::createOptionWidget()
//TODO
//connect(srv, SIGNAL(resourceAdded(KoResource*)), this, SLOT(slotAddPalette(KoResource*)));
//m_optionsWidget->setFixedHeight(m_optionsWidget->sizeHint().height());
// m_optionsWidget->setFixedHeight(m_optionsWidget->sizeHint().height());
return m_optionsWidget;
}
void KisToolColorPicker::updateOptionWidget()
{
if (!m_optionsWidget) return;
m_optionsWidget->cbNormaliseValues->setChecked(m_config.normaliseValues);
m_optionsWidget->cbUpdateCurrentColor->setChecked(m_config.updateColor);
m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config.sampleMerged);
m_optionsWidget->cbPalette->setChecked(m_config.addPalette);
m_optionsWidget->radius->setValue(m_config.radius);
}
void KisToolColorPicker::slotSetUpdateColor(bool state)
{
m_updateColor = state;
m_config.updateColor = state;
}
void KisToolColorPicker::slotSetNormaliseValues(bool state)
{
m_normaliseValues = state;
m_config.normaliseValues = state;
displayPickedColor();
}
void KisToolColorPicker::slotSetAddPalette(bool state)
{
m_addPalette = state;
m_config.addPalette = state;
}
void KisToolColorPicker::slotChangeRadius(int value)
{
m_radius = value;
m_config.radius = value;
}
void KisToolColorPicker::slotSetColorSource(int value)
{
m_config.sampleMerged = value == SAMPLE_MERGED;
}
void KisToolColorPicker::slotAddPalette(KoResource* resource)
......
......@@ -52,8 +52,22 @@ public:
virtual ~KisToolColorPicker();
public:
virtual QWidget* createOptionWidget();
struct Configuration {
Configuration();
bool toForegroundColor;
bool updateColor;
bool addPalette;
bool normaliseValues;
bool sampleMerged;
int radius;
void save(ToolActivation activation) const;
void load(ToolActivation activation);
};
public:
virtual QWidget* createOptionWidget();
virtual void mousePressEvent(KoPointerEvent *event);
virtual void mouseMoveEvent(KoPointerEvent *event);
......@@ -61,22 +75,27 @@ public:
virtual void paint(QPainter& gc, const KoViewConverter &converter);
protected:
void activate(ToolActivation activation, const QSet<KoShape*> &);
void deactivate();
public slots:
void slotSetUpdateColor(bool);
void slotSetNormaliseValues(bool);
void slotSetAddPalette(bool);
void slotChangeRadius(int);
void slotAddPalette(KoResource* resource);
void slotSetColorSource(int value);
private:
void displayPickedColor();
void pickColor(const QPointF& pos);
void updateOptionWidget();
Configuration m_config;
ToolActivation m_toolActivationSource;
bool m_isActivated;
bool m_toForegroundColor;
bool m_updateColor;
bool m_addPalette;
bool m_normaliseValues;
int m_radius;
KoColor m_pickedColor;
// used to skip some of the tablet events and don't update the colour that often
......
......@@ -581,19 +581,6 @@ void KoToolManager::Private::updateCursor(const QCursor &cursor)
canvasData->canvas->canvas()->setCursor(cursor);
}
void KoToolManager::Private::switchBackRequested()
{
Q_ASSERT(canvasData);
if (!canvasData) return;
if (canvasData->stack.isEmpty()) {
// default to changing to the interactionTool
switchTool(KoInteractionTool_ID, false);
return;
}
switchTool(canvasData->stack.pop(), false);
}
void KoToolManager::Private::selectionChanged(QList<KoShape*> shapes)
{
QList<QString> types;
......@@ -715,11 +702,6 @@ void KoToolManager::Private::switchToolByShortcut(QKeyEvent *event)
}
}
void KoToolManager::Private::switchToolTemporaryRequested(const QString &id)
{
switchTool(id, true);
}
// ******** KoToolManager **********
KoToolManager::KoToolManager()
: QObject(),
......@@ -840,6 +822,24 @@ void KoToolManager::switchToolRequested(const QString & id)
d->switchTool(id, false);
}
void KoToolManager::switchToolTemporaryRequested(const QString &id)
{
d->switchTool(id, true);
}
void KoToolManager::switchBackRequested()
{
Q_ASSERT(d->canvasData);
if (!d->canvasData) return;
if (d->canvasData->stack.isEmpty()) {
// default to changing to the interactionTool
d->switchTool(KoInteractionTool_ID, false);
return;
}
d->switchTool(d->canvasData->stack.pop(), false);
}
KoCreateShapesTool * KoToolManager::shapeCreatorTool(KoCanvasBase *canvas) const
{
Q_ASSERT(canvas);
......
......@@ -215,6 +215,21 @@ public slots:
*/
void addDeferredToolFactory(KoToolFactoryBase *toolFactory);
/**
* Request for temporary switching the tools.
* This switch can be later reverted with switchBackRequested().
* @param id the id of the tool
*
* @see switchBackRequested()
*/
void switchToolTemporaryRequested(const QString &id);
/**
* Switches back to the original tool after the temporary switch
* has been done. It the user changed the tool manually on the way,
* then it switches to the interaction tool
*/
void switchBackRequested();
signals:
/**
......@@ -272,10 +287,8 @@ private:
Q_PRIVATE_SLOT(d, void attachCanvas(KoCanvasController *controller))
Q_PRIVATE_SLOT(d, void movedFocus(QWidget *from, QWidget *to))
Q_PRIVATE_SLOT(d, void updateCursor(const QCursor &cursor))
Q_PRIVATE_SLOT(d, void switchBackRequested())
Q_PRIVATE_SLOT(d, void selectionChanged(QList<KoShape*> shapes))
Q_PRIVATE_SLOT(d, void currentLayerChanged(const KoShapeLayer *layer))
Q_PRIVATE_SLOT(d, void switchToolTemporaryRequested(const QString &id))
QPair<QString, KoToolBase*> createTools(KoCanvasController *controller, ToolHelper *tool);
......
......@@ -217,7 +217,6 @@ void KoTriangleColorSelector::setQColor(const QColor& c)
if( hue >= 0 && hue <= 360)
d->hue = hue;
d->invalidTriangle = true;
tellColorChanged();
d->updateTimer.start();
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment