Commit f2025461 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Implemented basic framework for fetching properties from paintop presets

parent 57e58b14
......@@ -63,6 +63,7 @@ set(kritaimage_LIB_SRCS
brushengine/kis_paintop_preset.cpp
brushengine/kis_paintop_registry.cc
brushengine/kis_paintop_settings.cpp
brushengine/kis_paintop_settings_update_proxy.cpp
brushengine/kis_locked_properties.cc
brushengine/kis_locked_properties_proxy.cpp
brushengine/kis_locked_properties_server.cpp
......
/*
* Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_CALLBACK_BASED_PAINTOP_PROPERTY_H
#define __KIS_CALLBACK_BASED_PAINTOP_PROPERTY_H
#include <functional>
template <class ParentClass>
class KisCallbackBasedPaintopProperty : public ParentClass
{
public:
KisCallbackBasedPaintopProperty(typename ParentClass::Type type,
const QString &id,
const QString &name,
KisPaintOpSettingsSP settings,
QObject *parent)
: ParentClass(type, id, name, settings, parent) {}
typedef std::function<void (KisUniformPaintOpProperty*)> Callback;
void setReadCallback(Callback func) { m_readFunc = func; }
void setWriteCallback(Callback func) { m_writeFunc = func; }
protected:
virtual void readValueImpl() { if (m_readFunc) m_readFunc(this); }
virtual void writeValueImpl() { if (m_writeFunc) m_writeFunc(this); }
private:
Callback m_readFunc;
Callback m_writeFunc;
};
#endif /* __KIS_CALLBACK_BASED_PAINTOP_PROPERTY_H */
......@@ -36,6 +36,7 @@
#include <brushengine/kis_paint_information.h>
#include "kis_paintop_config_widget.h"
#include <brushengine/kis_paintop_preset.h>
#include "kis_paintop_settings_update_proxy.h"
#include <time.h>
#include<kis_types.h>
......@@ -45,6 +46,8 @@ struct Q_DECL_HIDDEN KisPaintOpSettings::Private {
QPointer<KisPaintOpConfigWidget> settingsWidget;
QString modelName;
KisPaintOpPresetWSP preset;
QScopedPointer<KisPaintopSettingsUpdateProxy> updateProxy;
QList<KisUniformPaintOpPropertySP> uniformProperties;
bool disableDirtyNotifications;
......@@ -299,7 +302,9 @@ void KisPaintOpSettings::setProperty(const QString & name, const QVariant & valu
void KisPaintOpSettings::onPropertyChanged()
{
if (d->updateProxy) {
d->updateProxy->notifySettingsChanged();
}
}
bool KisPaintOpSettings::isLodUserAllowed(const KisPropertiesConfiguration *config)
......@@ -311,3 +316,45 @@ void KisPaintOpSettings::setLodUserAllowed(KisPropertiesConfiguration *config, b
{
config->setProperty("lodUserAllowed", value);
}
KisPaintopSettingsUpdateProxy* KisPaintOpSettings::updateProxy() const
{
if (!d->updateProxy) {
d->updateProxy.reset(new KisPaintopSettingsUpdateProxy());
}
return d->updateProxy.data();
}
#include "kis_callback_based_paintop_property.h"
#include "kis_slider_based_paintop_property.h"
QList<KisUniformPaintOpPropertySP> KisPaintOpSettings::uniformProperties()
{
if (d->uniformProperties.isEmpty()) {
typedef KisCallbackBasedPaintopProperty<KisIntSliderBasedPaintOpProperty> IntSliderProp;
typedef KisCallbackBasedPaintopProperty<KisDoubleSliderBasedPaintOpProperty> DoubleSliderProp;
DoubleSliderProp *prop =
new DoubleSliderProp(DoubleSliderProp::Double,
"opacity",
i18n("Opacity"),
this, 0);
prop->setRange(0.0, 1.0);
prop->setSingleStep(0.01);
prop->setReadCallback(
[](KisUniformPaintOpProperty *prop) {
prop->setValue(prop->settings()->paintOpOpacity());
});
prop->setWriteCallback(
[](KisUniformPaintOpProperty *prop) {
prop->settings()->setPaintOpOpacity(prop->value().toReal());
});
QObject::connect(updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue()));
prop->requestReadValue();
d->uniformProperties.append(toQShared(prop));
}
return d->uniformProperties;
}
......@@ -28,9 +28,12 @@
#include "kis_shared.h"
#include "kis_properties_configuration.h"
#include <brushengine/kis_paint_information.h>
#include <brushengine/kis_uniform_paintop_property.h>
class KisPaintOpConfigWidget;
class KisPaintopSettingsUpdateProxy;
/**
* This class is used to cache the settings for a paintop
......@@ -233,6 +236,9 @@ public:
*/
void setProperty(const QString & name, const QVariant & value);
KisPaintopSettingsUpdateProxy* updateProxy() const;
virtual QList<KisUniformPaintOpPropertySP> uniformProperties();
static bool isLodUserAllowed(const KisPropertiesConfiguration *config);
static void setLodUserAllowed(KisPropertiesConfiguration *config, bool value);
......
/*
* Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_paintop_settings_update_proxy.h"
#include "kis_signal_compressor.h"
struct KisPaintopSettingsUpdateProxy::Private
{
Private() : updatesCompressor(100, KisSignalCompressor::FIRST_ACTIVE) {}
KisSignalCompressor updatesCompressor;
};
KisPaintopSettingsUpdateProxy::KisPaintopSettingsUpdateProxy(QObject *parent)
: QObject(parent),
m_d(new Private)
{
connect(&m_d->updatesCompressor, SIGNAL(timeout()), SIGNAL(sigSettingsChanged()));
}
KisPaintopSettingsUpdateProxy::~KisPaintopSettingsUpdateProxy()
{
}
void KisPaintopSettingsUpdateProxy::notifySettingsChanged()
{
m_d->updatesCompressor.start();
}
/*
* Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_PAINTOP_SETTINGS_UPDATE_PROXY_H
#define __KIS_PAINTOP_SETTINGS_UPDATE_PROXY_H
#include <QScopedPointer>
#include <QObject>
class KisPaintopSettingsUpdateProxy : public QObject
{
Q_OBJECT
public:
KisPaintopSettingsUpdateProxy(QObject *parent = 0);
~KisPaintopSettingsUpdateProxy();
void notifySettingsChanged();
Q_SIGNALS:
void sigSettingsChanged();
private:
struct Private;
const QScopedPointer<Private> m_d;
};
#endif /* __KIS_PAINTOP_SETTINGS_UPDATE_PROXY_H */
/*
* Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_SLIDER_BASED_PAINTOP_PROPERTY_H
#define __KIS_SLIDER_BASED_PAINTOP_PROPERTY_H
#include <QScopedPointer>
#include "kis_uniform_paintop_property.h"
template <typename T>
class KisSliderBasedPaintOpProperty : public KisUniformPaintOpProperty
{
public:
KisSliderBasedPaintOpProperty(Type type,
const QString &id,
const QString &name,
KisPaintOpSettingsSP settings,
QObject *parent)
: KisUniformPaintOpProperty(type, id, name, settings, parent),
m_min(T(0)),
m_max(T(100)),
m_singleStep(T(1)),
m_pageStep(T(10)),
m_exponentRatio(1.0),
m_decimals(2)
{
}
T min() const {
return m_min;
}
T max() const {
return m_max;
}
void setRange(T min, T max) {
m_min = min;
m_max = max;
}
T singleStep() const {
return m_singleStep;
}
void setSingleStep(T value) {
m_singleStep = value;
}
T pageStep() const {
return m_pageStep;
}
void setPageStep(T value) {
m_pageStep = value;
}
qreal exponentRatio() const {
return m_exponentRatio;
}
void setExponentRatio(qreal value) {
m_exponentRatio = value;
}
int decimals() const {
return m_decimals;
}
void setDecimals(int value) {
m_decimals = value;
}
QString suffix() const {
return m_suffix;
}
void setSuffix(QString value) {
m_suffix = value;
}
private:
T m_min;
T m_max;
T m_singleStep;
T m_pageStep;
qreal m_exponentRatio;
int m_decimals;
QString m_suffix;
};
typedef KisSliderBasedPaintOpProperty<int> KisIntSliderBasedPaintOpProperty;
typedef KisSliderBasedPaintOpProperty<qreal> KisDoubleSliderBasedPaintOpProperty;
#endif /* __KIS_SLIDER_BASED_PAINTOP_PROPERTY_H */
......@@ -20,26 +20,37 @@
#include <QVariant>
#include "kis_debug.h"
#include "kis_paintop_settings.h"
struct KisUniformPaintOpProperty::Private
{
Private(Type _type,
const QString &_id,
const QString &_name) : type(_type), id(_id), name(_name) {}
const QString &_name,
KisPaintOpSettingsSP _settings)
: type(_type),
id(_id),
name(_name),
settings(_settings),
isReadingValue(false) {}
Type type;
QString id;
QString name;
QVariant value;
bool isReadingValue;
KisWeakSharedPtr<KisPaintOpSettings> settings;
};
KisUniformPaintOpProperty::KisUniformPaintOpProperty(Type type,
const QString &id,
const QString &name,
KisPaintOpSettingsSP settings,
QObject *parent)
: QObject(parent),
m_d(new Private(type, id, name))
m_d(new Private(type, id, name, settings))
{
}
......@@ -62,63 +73,46 @@ KisUniformPaintOpProperty::Type KisUniformPaintOpProperty::type() const
return m_d->type;
}
int KisUniformPaintOpProperty::valueInt() const
QVariant KisUniformPaintOpProperty::value() const
{
KIS_ASSERT_RECOVER(m_d->type == Int) { return 0; }
return m_d->value.toInt();
return m_d->value;
}
qreal KisUniformPaintOpProperty::valueDouble() const
QWidget *KisUniformPaintOpProperty::createPropertyWidget()
{
KIS_ASSERT_RECOVER(m_d->type == Double) { return 0; }
return m_d->value.toReal();
return 0;
}
bool KisUniformPaintOpProperty::valueBool() const
void KisUniformPaintOpProperty::setValue(const QVariant &value)
{
KIS_ASSERT_RECOVER(m_d->type == Bool) { return 0; }
return m_d->value.toBool();
}
if (m_d->value == value) return;
m_d->value = value;
int KisUniformPaintOpProperty::valueCombo() const
{
KIS_ASSERT_RECOVER(m_d->type == Combo) { return 0; }
return m_d->value.toInt();
emit valueChanged(value);
if (!m_d->isReadingValue) {
writeValueImpl();
}
}
void KisUniformPaintOpProperty::setValueInt(int value)
void KisUniformPaintOpProperty::requestReadValue()
{
KIS_ASSERT_RECOVER_RETURN(m_d->type == Int);
if (m_d->value == value) return;
m_d->value = value;
emit sigValueIntChanged(value);
m_d->isReadingValue = true;
readValueImpl();
m_d->isReadingValue = false;
}
void KisUniformPaintOpProperty::setValueDouble(qreal value)
KisPaintOpSettingsSP KisUniformPaintOpProperty::settings()
{
KIS_ASSERT_RECOVER_RETURN(m_d->type == Double);
if (m_d->value == value) return;
m_d->value = value;
emit sigValueDoubleChanged(value);
// correct conversion weak-to-strong shared pointer
return m_d->settings ? m_d->settings : 0;
}
void KisUniformPaintOpProperty::setValueBool(bool value)
void KisUniformPaintOpProperty::readValueImpl()
{
KIS_ASSERT_RECOVER_RETURN(m_d->type == Bool);
if (m_d->value == value) return;
m_d->value = value;
emit sigValueBoolChanged(value);
}
void KisUniformPaintOpProperty::setValueCombo(int value)
void KisUniformPaintOpProperty::writeValueImpl()
{
KIS_ASSERT_RECOVER_RETURN(m_d->type == Combo);
if (m_d->value == value) return;
m_d->value = value;
emit sigValueComboChanged(value);
}
......@@ -23,6 +23,7 @@
#include <QObject>
#include "kritaimage_export.h"
#include "kis_types.h"
class KRITAIMAGE_EXPORT KisUniformPaintOpProperty : public QObject
......@@ -40,6 +41,7 @@ public:
KisUniformPaintOpProperty(Type type,
const QString &id,
const QString &name,
KisPaintOpSettingsSP settings,
QObject *parent);
~KisUniformPaintOpProperty();
......@@ -47,26 +49,33 @@ public:
QString name() const;
Type type() const;
int valueInt() const;
qreal valueDouble() const;
bool valueBool() const;
int valueCombo() const;
QVariant value() const;
QWidget *createPropertyWidget();
KisPaintOpSettingsSP settings();
public Q_SLOTS:
void setValueInt(int value);
void setValueDouble(qreal value);
void setValueBool(bool value);
void setValueCombo(int value);
void setValue(const QVariant &value);
void requestReadValue();
Q_SIGNALS:
void sigValueIntChanged(int value);
void sigValueDoubleChanged(qreal value);
void sigValueBoolChanged(bool value);
void sigValueComboChanged(int value);
void valueChanged(const QVariant &value);
protected:
virtual void readValueImpl();
virtual void writeValueImpl();
private:
struct Private;
const QScopedPointer<Private> m_d;
};
template<class T> class QSharedPointer;
template<class T> class QWeakPointer;
template<class T> class QList;
typedef QSharedPointer<KisUniformPaintOpProperty> KisUniformPaintOpPropertySP;
typedef QWeakPointer<KisUniformPaintOpProperty> KisUniformPaintOpPropertyWSP;
#endif /* __KIS_UNIFORM_PAINT_OP_PROPERTY_H */
......@@ -91,6 +91,21 @@ void KisAcyclicSignalConnector::connectBackwardVoid(QObject *sender, const char
connect(this, SIGNAL(backwardSignalVoid()), receiver, method);
}
void KisAcyclicSignalConnector::connectForwardVariant(QObject *sender, const char *signal,
QObject *receiver, const char *method)
{
connect(sender, signal, this, SLOT(forwardSlotVariant(const QVariant&)));
connect(this, SIGNAL(forwardSignalVariant(const QVariant&)), receiver, method);
}
void KisAcyclicSignalConnector::connectBackwardVariant(QObject *sender, const char *signal,
QObject *receiver, const char *method)
{
connect(sender, signal, this, SLOT(backwardSlotVariant(const QVariant&)));
connect(this, SIGNAL(backwardSignalVariant(const QVariant&)), receiver, method);
}
void KisAcyclicSignalConnector::forwardSlotDouble(double value)
{
if (m_signalsBlocked) return;
......@@ -163,3 +178,20 @@ void KisAcyclicSignalConnector::backwardSlotVoid()
m_signalsBlocked--;
}
void KisAcyclicSignalConnector::forwardSlotVariant(const QVariant &value)
{
if (m_signalsBlocked) return;
m_signalsBlocked++;
emit forwardSignalVariant(value);
m_signalsBlocked--;
}
void KisAcyclicSignalConnector::backwardSlotVariant(const QVariant &value)
{
if (m_signalsBlocked) return;
m_signalsBlocked++;
emit backwardSignalVariant(value);
m_signalsBlocked--;
}
......@@ -73,6 +73,12 @@ public:
void connectBackwardVoid(QObject *sender, const char *signal,
QObject *receiver, const char *method);
void connectForwardVariant(QObject *sender, const char *signal,
QObject *receiver, const char *method);
void connectBackwardVariant(QObject *sender, const char *signal,
QObject *receiver, const char *method);
private Q_SLOTS:
void forwardSlotDouble(double value);
void backwardSlotDouble(double value);
......@@ -86,6 +92,9 @@ private Q_SLOTS:
void forwardSlotVoid();
void backwardSlotVoid();
void forwardSlotVariant(const QVariant &value);
void backwardSlotVariant(const QVariant &value);
Q_SIGNALS:
void forwardSignalDouble(double value);
void backwardSignalDouble(double value);
......@@ -99,6 +108,9 @@ Q_SIGNALS:
void forwardSignalVoid();
void backwardSignalVoid();
void forwardSignalVariant(const QVariant &value);
void backwardSignalVariant(const QVariant &value);
private:
int m_signalsBlocked;
};
......
......@@ -27,7 +27,12 @@
#include <QEvent>
#include "kis_uniform_paintop_property.h"
#include "kis_slider_based_paintop_property.h"
#include "kis_uniform_paintop_property_widget.h"
#include "kis_canvas_resource_provider.h"
#include "kis_paintop_preset.h"
#include "kis_paintop_settings.h"
#include "kis_signal_auto_connection.h"
#include "kis_debug.h"
......@@ -37,12 +42,21 @@ struct KisBrushHud::Private
QPointer<QLabel> lblPresetName;
QPointer<QWidget> wdgProperties;
QPointer<QScrollArea> wdgPropertiesArea;
QPointer<QVBoxLayout> propertiesLayout;
KisCanvasResourceProvider *provider;
KisSignalAutoConnectionsStore connections;
KisPaintOpPresetSP currentPreset;
};
KisBrushHud::KisBrushHud(QWidget *parent)
KisBrushHud::KisBrushHud(KisCanvasResourceProvider *provider, QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint),
m_d(new Private)
{
m_d->provider = provider;
QVBoxLayout *layout = new QVBoxLayout(this);
m_d->lblPresetName = new QLabel("<Preset Name>", this);
layout->addWidget(m_d->lblPresetName);
......@@ -51,25 +65,17 @@ KisBrushHud::KisBrushHud(QWidget *parent)
m_d->wdgPropertiesArea->setAlignment(Qt::AlignLeft | Qt::AlignTop);
m_d->wdgPropertiesArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_d->wdgProperties = new QWidget(this);
QVBoxLayout *propsLayout = new QVBoxLayout(this);
propsLayout->setSpacing(0);
propsLayout->setContentsMargins(0, 0, 22, 0);
propsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
for (int i = 0; i < 10; i++) {
const QString name = QString("Property %1").arg(i);
const KisUniformPaintOpProperty::Type type =
KisUniformPaintOpProperty::Type(i%2);
m_d->wdgPropertiesArea->setWidgetResizable(true);
KisUniformPaintOpProperty *prop = new KisUniformPaintOpProperty(type, name, name, this);
KisUniformPaintOpPropertyWidget *w = new KisUniformPaintOpPropertyWidget(prop, m_d->wdgProperties);
m_d->wdgProperties = new QWidget(this);
m_d->propertiesLayout = new QVBoxLayout(this);
m_d->propertiesLayout->setSpacing(0);
m_d->propertiesLayout->setContentsMargins(0, 0, 22, 0);
m_d->propertiesLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
w->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
propsLayout->addWidget(w);
}
// not adding any widgets until explicitly requested
m_d->wdgProperties->setLayout(propsLayout);
m_d->wdgProperties->setLayout(m_d->propertiesLayout);
m_d->wdgPropertiesArea->setWidget(m_d->wdgProperties);
layout->addWidget(m_d->wdgPropertiesArea);
......@@ -81,6 +87,59 @@ KisBrushHud::~KisBrushHud()
{
}
void KisBrushHud::updateProperties()
{
KisPaintOpPresetSP preset = m_d->provider->currentPreset();
KisPaintOpSettingsSP settings = preset->settings();
if (preset == m_d->currentPreset) return;
m_d->currentPreset = preset;
Q_FOREACH (QWidget *w, m_d->wdgProperties->findChildren<QWidget*>()) {
w->deleteLater();
}
m_d->lblPresetName->setText(preset->name());
QList<KisUniformPaintOpPropertySP> properties = settings->uniformProperties();
Q_FOREACH(auto property, properties) {
QWidget *w = 0;
if (property->type() == KisUniformPaintOpProperty::Int) {
w = new KisUniformPaintOpPropertyIntSlider(property, m_d->wdgProperties);
} else if (property->type() == KisUniformPaintOpProperty::Double) {
w = new KisUniformPaintOpPropertyDoubleSlider(property, m_d->wdgProperties);
}