1005 lines
35 KiB
C++
1005 lines
35 KiB
C++
|
|
|
|
#include "toonzqt/styleeditor.h"
|
|
#include "toonzqt/colorfield.h"
|
|
#include "toonzqt/dvdialog.h"
|
|
#include "toonzqt/gutil.h"
|
|
#include "toonzqt/menubarcommand.h"
|
|
#include "toonz/cleanupcolorstyles.h"
|
|
#include "tconvert.h"
|
|
#include "tcolorstyles.h"
|
|
#include "trop.h"
|
|
#include "toonzqt/lutcalibrator.h"
|
|
#include "styledata.h"
|
|
|
|
// Qt includes
|
|
#include <QApplication>
|
|
#include <QClipboard>
|
|
#include <QLayout>
|
|
#include <QPainter>
|
|
#include <QMouseEvent>
|
|
#include <QLabel>
|
|
|
|
using namespace DVGui;
|
|
|
|
namespace {
|
|
|
|
void drawChessBoard(QPainter &p) {
|
|
for (int x = 0; x < 4; x++) {
|
|
for (int y = 0; y < 4; y++) {
|
|
QColor col((x + y) % 2 == 0 ? Qt::black : Qt::white);
|
|
p.fillRect(x * 4, y * 4, 4, 4, col);
|
|
}
|
|
}
|
|
}
|
|
|
|
QPixmap getIconPm(const QColor &color) {
|
|
QPixmap retPm(16, 16);
|
|
if (color.alpha() == 255) {
|
|
retPm.fill(color);
|
|
return retPm;
|
|
}
|
|
QPainter p(&retPm);
|
|
drawChessBoard(p);
|
|
p.fillRect(0, 0, 16, 16, color);
|
|
return retPm;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
//=============================================================================
|
|
|
|
CommonChessboard *CommonChessboard::instance() {
|
|
static CommonChessboard _instance;
|
|
return &_instance;
|
|
}
|
|
|
|
CommonChessboard::CommonChessboard() : m_bgRas(40.0, 40.0) { update(); }
|
|
|
|
void CommonChessboard::setChessboardColors(const TPixel32 &col1,
|
|
const TPixel32 &col2) {
|
|
TRop::checkBoard(m_bgRas, col1, col2,
|
|
TDimensionD(m_bgRas->getLx() / 8, m_bgRas->getLy() / 8),
|
|
TPointD(0, 0));
|
|
QImage img(m_bgRas->getRawData(), m_bgRas->getLx(), m_bgRas->getLy(),
|
|
QImage::Format_ARGB32);
|
|
m_bgPix = QPixmap::fromImage(img);
|
|
}
|
|
|
|
void CommonChessboard::update() {
|
|
TPixel32 col1, col2;
|
|
Preferences::instance()->getChessboardColors(col1, col2);
|
|
setChessboardColors(col1, col2);
|
|
}
|
|
|
|
//=============================================================================
|
|
/*! \class DVGui::StyleSample
|
|
\brief The StyleSample class provides to view a square color.
|
|
|
|
Inherits \b QWidget.
|
|
|
|
By default square color is set to \b TPixel32(235,235,235,255),
|
|
you
|
|
can set other color using setColor(); you can also define
|
|
current color
|
|
with a style \b TColorStyle, \b getStyle(), using setStyle().
|
|
You can pass to constructor square size.
|
|
|
|
StyleSample permit to manage click event, it's possile to enable
|
|
this
|
|
feature setting enableClick(bool on) to true.
|
|
If it is enable when click in square class emit the signal
|
|
clicked(const TColorStyle &style).
|
|
*/
|
|
/*! \fn void DVGui::StyleSample::clicked(const TColorStyle &style)
|
|
This signal is emitted when click event is enable and a style is
|
|
set.
|
|
*/
|
|
/*! \fn void DVGui::StyleSample::enableClick(bool on)
|
|
Set click event enable if \b is true, disable otherwise.
|
|
If true setStyle store current style and buttonPress emit signal
|
|
clicked(const TColorStyle &style).
|
|
*/
|
|
StyleSample::StyleSample(QWidget *parent, int sizeX, int sizeY)
|
|
: m_samplePixmap(sizeX, sizeY, QImage::Format_ARGB32)
|
|
, m_bgRas(sizeX, sizeY)
|
|
, m_style(0)
|
|
, m_clickEnabled(false)
|
|
, m_chessColor1(180, 180, 180)
|
|
, m_chessColor2(239, 239, 239)
|
|
, m_sysChessboard(false)
|
|
, m_stretch(true)
|
|
, m_isEditing(false) {
|
|
setMinimumSize(sizeX, sizeY);
|
|
setColor(TPixel32::Transparent);
|
|
TRop::checkBoard(m_bgRas, m_chessColor1, m_chessColor2,
|
|
TDimensionD(sizeX / 4, sizeX / 4), TPointD(0, 0));
|
|
setEnable(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
StyleSample::~StyleSample() {
|
|
if (m_style) delete m_style;
|
|
m_style = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Return current StyleSample \b TColorStyle style.
|
|
*/
|
|
TColorStyle *StyleSample::getStyle() const { return m_style; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Update current square colore and, if click event is enable set current
|
|
StyleSample \b TColorStyle style to \b style.
|
|
*/
|
|
void StyleSample::setStyle(TColorStyle &style, int colorParameterIndex) {
|
|
// Store current color
|
|
TPixel32 color = style.getColorParamValue(colorParameterIndex);
|
|
m_currentColor = QColor(color.r, color.g, color.b, color.m);
|
|
if (LutManager::instance()->isValid())
|
|
LutManager::instance()->convert(m_currentColor);
|
|
|
|
/*-- TSolidColorStyleの場合のみ、単色塗りつぶし --*/
|
|
if (style.getTagId() == 3) {
|
|
setColor(style.getMainColor());
|
|
m_stretch = true;
|
|
} else {
|
|
TDimension iconDim(width(), height());
|
|
|
|
// obtain square icon for the TMyPaintBrushStyle
|
|
// so that the checkerboard color will become consistent with solido style
|
|
// when the main color is semi-transparent.
|
|
if (style.getTagId() == 4001) {
|
|
int d = std::min(width(), height());
|
|
iconDim = TDimension(d, d);
|
|
}
|
|
|
|
TRaster32P icon = style.getIcon(iconDim);
|
|
// TRaster32P icon =
|
|
// style.getIcon(qsize2Dimension(m_samplePixmap.rect().size()));
|
|
m_samplePixmap = rasterToQImage(icon, false); // modified in 6.2
|
|
m_stretch = style.getTagId() == 4;
|
|
update();
|
|
}
|
|
|
|
if (m_cloneStyle) {
|
|
if (m_style) delete m_style; // avoid memory leak
|
|
m_style = style.clone();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Update current square colore to \b TPixel32 \b color.
|
|
Useful for efficiency if click event is disable.
|
|
*/
|
|
void StyleSample::setColor(const TPixel32 &pixel) {
|
|
QColor color(pixel.r, pixel.g, pixel.b, pixel.m);
|
|
if (LutManager::instance()->isValid()) LutManager::instance()->convert(color);
|
|
|
|
m_samplePixmap.fill(color.rgba());
|
|
update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void StyleSample::setChessboardColors(const TPixel32 &col1,
|
|
const TPixel32 &col2) {
|
|
m_chessColor1 = col1;
|
|
m_chessColor2 = col2;
|
|
TRop::checkBoard(m_bgRas, m_chessColor1, m_chessColor2,
|
|
TDimensionD(m_bgRas->getLx() / 8, m_bgRas->getLy() / 8),
|
|
TPointD(0, 0));
|
|
update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Paint square color.
|
|
*/
|
|
void StyleSample::paintEvent(QPaintEvent *event) {
|
|
if (!isEnable()) return;
|
|
QPainter painter(this);
|
|
if (m_sysChessboard) {
|
|
painter.drawTiledPixmap(rect(),
|
|
DVGui::CommonChessboard::instance()->getPixmap());
|
|
} else {
|
|
QImage img(m_bgRas->getRawData(), m_bgRas->getLx(), m_bgRas->getLy(),
|
|
QImage::Format_ARGB32);
|
|
painter.drawImage(0, 0, img.scaled(size()));
|
|
}
|
|
if (m_stretch) {
|
|
painter.drawImage(0, 0, m_samplePixmap.scaled(size()));
|
|
} else {
|
|
// put the icon on the left
|
|
int x = 0;
|
|
// int x = (width() - m_samplePixmap.width()) / 2;
|
|
int y = (height() - m_samplePixmap.height()) / 2;
|
|
painter.fillRect(rect(), m_currentColor);
|
|
painter.drawImage(x, y, m_samplePixmap);
|
|
}
|
|
if (m_isEditing) {
|
|
// QRect rect(0,0,m_bgRas->getLx(),m_bgRas->getLy());
|
|
painter.setPen(Qt::white);
|
|
painter.drawRect(rect().adjusted(0, 0, -1, -1));
|
|
painter.drawRect(rect().adjusted(2, 2, -3, -3));
|
|
painter.setPen(QColor(180, 210, 255));
|
|
painter.drawRect(rect().adjusted(1, 1, -2, -2));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! If exist current style and event click is enable emit signal
|
|
clicked(const TColorStyle &style).
|
|
*/
|
|
void StyleSample::mousePressEvent(QMouseEvent *event) {
|
|
if (m_clickEnabled)
|
|
emit clicked();
|
|
else
|
|
event->ignore();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void StyleSample::mouseDoubleClickEvent(QMouseEvent *event) { event->ignore(); }
|
|
|
|
//=============================================================================
|
|
/*! \class DVGui::ChannelField
|
|
\brief The ChannelField class is used to view an object to
|
|
manage a color
|
|
value, red, green, blue or transparency
|
|
channel.
|
|
|
|
Inherits \b QWidget.
|
|
|
|
The object is composed of grid layout \b QGridLayout which
|
|
contains a label
|
|
in first row, first column, to identify channel, a text field \b
|
|
IntLineEdit
|
|
in first row, second column, and a slider in second row, second
|
|
column.
|
|
Texf field and slider are connected, so if you change one the
|
|
other automatically
|
|
change. You can set current value getChannel(), using
|
|
setChannel().
|
|
This two object is used to manage channel value, them range is
|
|
fixed to [0,255].
|
|
This object size is fixed, [50, 2*DVGui::WidgetHeight].
|
|
|
|
To know when channel parameter value change class provides a
|
|
signal, valueChanged(int value);
|
|
class emit signal when slider value change or when text field is
|
|
editing,
|
|
see SLOT: onSliderChanged(int value) and onEditChanged(const
|
|
QString &str)
|
|
to know when signal is emitted.
|
|
*/
|
|
/*! \fn void DVGui::ChannelField::valueChanged(int value)
|
|
This signal is emitted when ChannelField, slider or text field,
|
|
value change;
|
|
if slider position change or text field is editing.
|
|
\sa onEditChanged(const QString &str) and onSliderChanged(int
|
|
value).
|
|
*/
|
|
ChannelField::ChannelField(QWidget *parent, const QString &string, int value,
|
|
int maxValue, bool horizontal, int labelWidth,
|
|
int sliderWidth)
|
|
: QWidget(parent), m_maxValue(maxValue) {
|
|
assert(maxValue > 0);
|
|
assert(0 <= value && value <= m_maxValue);
|
|
|
|
QLabel *channelName = new QLabel(string, this);
|
|
m_channelEdit = new DVGui::IntLineEdit(this, value, 0, maxValue);
|
|
m_channelSlider = new QSlider(Qt::Horizontal, this);
|
|
m_channelSlider->setFocusPolicy(Qt::NoFocus);
|
|
channelName->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
channelName->setFixedWidth(labelWidth);
|
|
|
|
m_channelSlider->setRange(0, maxValue);
|
|
m_channelSlider->setValue(value);
|
|
if (sliderWidth > 0) m_channelSlider->setFixedWidth(sliderWidth);
|
|
|
|
//----layout
|
|
QGridLayout *mainLayout = new QGridLayout(this);
|
|
mainLayout->setMargin(0);
|
|
mainLayout->setSpacing(3);
|
|
{
|
|
mainLayout->addWidget(channelName, 0, 0);
|
|
mainLayout->addWidget(m_channelEdit, 0, 1);
|
|
|
|
mainLayout->addWidget(m_channelSlider, horizontal ? 0 : 1,
|
|
horizontal ? 2 : 1);
|
|
}
|
|
mainLayout->setColumnStretch(0, 0);
|
|
mainLayout->setColumnStretch(1, 1);
|
|
mainLayout->setRowStretch(2, 1);
|
|
setLayout(mainLayout);
|
|
|
|
//----singnal-slot connections
|
|
|
|
bool ret = connect(m_channelEdit, SIGNAL(textChanged(const QString &)),
|
|
SLOT(onEditChanged(const QString &)));
|
|
ret = ret && connect(m_channelEdit, SIGNAL(editingFinished()),
|
|
SLOT(onEditFinished()));
|
|
ret = ret && connect(m_channelSlider, SIGNAL(valueChanged(int)),
|
|
SLOT(onSliderChanged(int)));
|
|
ret = ret && connect(m_channelSlider, SIGNAL(sliderReleased()),
|
|
SLOT(onSliderReleased()));
|
|
assert(ret);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Set current value to \b value.
|
|
\sa getChannel()
|
|
*/
|
|
void ChannelField::setChannel(int value) {
|
|
if (getChannel() == value) return;
|
|
assert(0 <= value && value <= m_maxValue);
|
|
m_channelSlider->setValue(value);
|
|
m_channelEdit->setValue(value);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Return current channel value.
|
|
\sa setChannel()
|
|
*/
|
|
int ChannelField::getChannel() {
|
|
int value = m_channelEdit->getValue();
|
|
assert(m_channelSlider->value() == value);
|
|
return value;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Set slider value to new string \b str value.
|
|
Verify if value is lower than 255 or greater than 0, range,
|
|
otherwise set
|
|
current value to 255 or 0. If slider value is different from
|
|
value in \b str
|
|
emit signal valueChanged(int value).
|
|
*/
|
|
void ChannelField::onEditChanged(const QString &str) {
|
|
int value = str.toInt();
|
|
if (value < 0) value = 0;
|
|
if (value > m_maxValue) value = m_maxValue;
|
|
assert(0 <= value && value <= m_maxValue);
|
|
if (str.toInt() != value) m_channelEdit->setValue(value);
|
|
if (m_channelSlider->value() == value) return;
|
|
m_channelSlider->setValue(value);
|
|
emit valueChanged(value, true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ChannelField::onEditFinished() {
|
|
emit valueChanged(m_channelEdit->getValue(), false);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Set text field value to \b value. If text field value is different from \b
|
|
value
|
|
emit signal valueChanged(int value).
|
|
*/
|
|
void ChannelField::onSliderChanged(int value) {
|
|
assert(0 <= value && value <= m_maxValue);
|
|
if (m_channelEdit->getValue() == value) return;
|
|
m_channelEdit->setText(QString(std::to_string(value).c_str()));
|
|
emit valueChanged(value, true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ChannelField::onSliderReleased() {
|
|
emit valueChanged(m_channelSlider->value(), false);
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
ColorField::ColorFieldEditorController *ColorField::m_editorController = 0;
|
|
// new
|
|
// ColorField::ColorFieldEditorController();
|
|
|
|
//=============================================================================
|
|
/*! \class DVGui::ColorField
|
|
\brief The ColorField class is used to view an object to manage
|
|
a color.
|
|
|
|
Inherits \b QWidget.
|
|
|
|
The object is composed of a horizontal layout \b QHBoxLayout
|
|
which contains
|
|
a StyleSample, and three or four ChannelField, it depend if
|
|
transparency is
|
|
count, to manage color channel.
|
|
You can pass to constructor current color value, getColor(), or
|
|
set it
|
|
calling setColor(). You can also pass to constructor a boolean
|
|
to know if
|
|
manage transparency channel or not, and an integer for
|
|
StyleSample size.
|
|
|
|
To know when color value change class provides a signal,
|
|
colorChanged(const TPixel32 &);
|
|
class emit signal when one ChannelField value change.
|
|
See SLOT: onRedChannelChanged(int value),
|
|
onGreenChannelChanged(int value),
|
|
onBlueChannelChanged(int value) and onAlphaChannelChanged(int
|
|
value) to know
|
|
when signal is emitted.
|
|
|
|
\b Example: initialize a ColorField with transparency channel.
|
|
\code
|
|
ColorField* colorFld = new
|
|
ColorField(0,true,TPixel32(0,0,255,255),50);
|
|
\endcode
|
|
\b Result:
|
|
\image html ColorField.jpg
|
|
*/
|
|
/*! \fn void DVGui::ColorField::colorChanged(const TPixel32 &)
|
|
This signal is emitted when a channel value of current color
|
|
change.
|
|
*/
|
|
/*! \fn TPixel32 DVGui::ColorField::getColor() const
|
|
Return ColorField current color.
|
|
*/
|
|
ColorField::ColorField(QWidget *parent, bool isAlphaActive, TPixel32 color,
|
|
int squareSize, bool useStyleEditor, int sliderWidth)
|
|
: QWidget(parent)
|
|
, m_color(color)
|
|
, m_notifyEditingChange(true)
|
|
, m_useStyleEditor(useStyleEditor) {
|
|
setMaximumHeight(squareSize);
|
|
QHBoxLayout *layout = new QHBoxLayout(this);
|
|
layout->setMargin(0);
|
|
layout->setSpacing(5);
|
|
|
|
layout->setSizeConstraint(QLayout::SetFixedSize);
|
|
|
|
int h = WidgetHeight;
|
|
|
|
m_colorSample = new StyleSample(this, squareSize, squareSize);
|
|
m_colorSample->setColor(m_color);
|
|
m_redChannel =
|
|
new ChannelField(this, tr("R:"), m_color.r, 255, false, 13, sliderWidth);
|
|
connect(m_redChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onRedChannelChanged(int, bool)));
|
|
m_greenChannel =
|
|
new ChannelField(this, tr("G:"), m_color.g, 255, false, 13, sliderWidth);
|
|
connect(m_greenChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onGreenChannelChanged(int, bool)));
|
|
m_blueChannel =
|
|
new ChannelField(this, tr("B:"), m_color.b, 255, false, 13, sliderWidth);
|
|
connect(m_blueChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onBlueChannelChanged(int, bool)));
|
|
m_alphaChannel =
|
|
new ChannelField(this, tr("A:"), m_color.m, 255, false, 13, sliderWidth);
|
|
connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onAlphaChannelChanged(int, bool)));
|
|
|
|
layout->addWidget(m_colorSample);
|
|
layout->addWidget(m_redChannel);
|
|
layout->addWidget(m_greenChannel);
|
|
layout->addWidget(m_blueChannel);
|
|
layout->addWidget(m_alphaChannel);
|
|
|
|
if (!isAlphaActive) m_alphaChannel->hide();
|
|
setLayout(layout);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Set ColorField current color to \b color. Update channel value of
|
|
\b ChannelField and \b StyleSample color.
|
|
*/
|
|
|
|
void ColorField::setAlphaActive(bool active) {
|
|
if (active && !m_alphaChannel->isVisible()) {
|
|
m_alphaChannel->show();
|
|
connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onAlphaChannelChanged(int, bool)));
|
|
assert(m_color.m == 255);
|
|
m_alphaChannel->setChannel(0);
|
|
m_color.m = 0;
|
|
m_colorSample->setColor(m_color);
|
|
emit colorChanged(m_color, false);
|
|
} else if (!active && m_alphaChannel->isVisible()) {
|
|
m_alphaChannel->hide();
|
|
disconnect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), this,
|
|
SLOT(onAlphaChannelChanged(int, bool)));
|
|
if (m_color.m != 255) {
|
|
m_alphaChannel->setChannel(255);
|
|
m_color.m = 255;
|
|
m_colorSample->setColor(m_color);
|
|
emit colorChanged(m_color, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------
|
|
|
|
void ColorField::setColor(const TPixel32 &color) {
|
|
if (m_color == color) return;
|
|
m_color = color;
|
|
updateChannels();
|
|
m_colorSample->setColor(m_color);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Set all \b ChannelField channel value to ColorField current color.
|
|
*/
|
|
void ColorField::hideChannelsFields(bool hide) {
|
|
if (hide) {
|
|
m_redChannel->hide();
|
|
m_greenChannel->hide();
|
|
m_blueChannel->hide();
|
|
m_alphaChannel->hide();
|
|
disconnect(m_redChannel, SIGNAL(valueChanged(int, bool)), this,
|
|
SLOT(onRedChannelChanged(int, bool)));
|
|
disconnect(m_greenChannel, SIGNAL(valueChanged(int, bool)), this,
|
|
SLOT(onGreenChannelChanged(int, bool)));
|
|
disconnect(m_blueChannel, SIGNAL(valueChanged(int, bool)), this,
|
|
SLOT(onBlueChannelChanged(int, bool)));
|
|
disconnect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), this,
|
|
SLOT(onAlphaChannelChanged(int, bool)));
|
|
} else {
|
|
m_redChannel->show();
|
|
m_greenChannel->show();
|
|
m_blueChannel->show();
|
|
m_alphaChannel->show();
|
|
;
|
|
connect(m_redChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onRedChannelChanged(int, bool)));
|
|
connect(m_greenChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onGreenChannelChanged(int, bool)));
|
|
connect(m_blueChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onBlueChannelChanged(int, bool)));
|
|
connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onAlphaChannelChanged(int, bool)));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! Set all \b ChannelField channel value to ColorField current color.
|
|
*/
|
|
void ColorField::updateChannels() {
|
|
m_redChannel->setChannel(m_color.r);
|
|
m_greenChannel->setChannel(m_color.g);
|
|
m_blueChannel->setChannel(m_color.b);
|
|
m_alphaChannel->setChannel(m_color.m);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::mousePressEvent(QMouseEvent *event) {
|
|
if (event->button() != Qt::LeftButton) return;
|
|
QPoint p = event->pos();
|
|
if (!m_colorSample->visibleRegion().contains(p)) return;
|
|
|
|
if (!m_useStyleEditor || !getEditorController()) return;
|
|
|
|
getEditorController()->edit(this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::mouseDoubleClickEvent(QMouseEvent *event) {
|
|
QPoint p = event->pos();
|
|
if (!m_colorSample->visibleRegion().contains(p)) return;
|
|
|
|
if (!m_useStyleEditor || !getEditorController()) return;
|
|
|
|
CommandManager::instance()->execute("MI_OpenStyleControl");
|
|
getEditorController()->edit(this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::hideEvent(QHideEvent *) {
|
|
if (!m_useStyleEditor || !getEditorController()) return;
|
|
|
|
getEditorController()->hide();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::contextMenuEvent(QContextMenuEvent *event) {
|
|
bool hasColor = QApplication::clipboard()->mimeData()->hasColor();
|
|
const StyleData *data =
|
|
dynamic_cast<const StyleData *>(QApplication::clipboard()->mimeData());
|
|
|
|
QMenu menu(this);
|
|
if (hasColor) { // pasting QColor
|
|
QColor color = qvariant_cast<QColor>(
|
|
QApplication::clipboard()->mimeData()->colorData());
|
|
QAction *action = new QAction(tr("Paste Color"), this);
|
|
action->setIcon(QIcon(getIconPm(color)));
|
|
action->setData(color);
|
|
|
|
connect(action, SIGNAL(triggered()), this, SLOT(onPasteColor()));
|
|
menu.addAction(action);
|
|
menu.addSeparator();
|
|
} else if (data && data->getStyleCount() > 0) { // pasting styles colors
|
|
// show 10 styles in maximum
|
|
int styleCount = std::min(10, data->getStyleCount());
|
|
for (int i = 0; i < styleCount; i++) {
|
|
QString styleName = QString::fromStdWString(data->getStyle(i)->getName());
|
|
TPixel32 color = data->getStyle(i)->getMainColor();
|
|
QColor _color(color.r, color.g, color.b, color.m);
|
|
|
|
QAction *action =
|
|
new QAction(tr("Paste Color of %1").arg(styleName), this);
|
|
action->setIcon(QIcon(getIconPm(_color)));
|
|
action->setData(_color);
|
|
|
|
connect(action, SIGNAL(triggered()), this, SLOT(onPasteColor()));
|
|
menu.addAction(action);
|
|
}
|
|
menu.addSeparator();
|
|
}
|
|
|
|
QAction *copyAction = new QAction(tr("Copy Color"), this);
|
|
connect(copyAction, SIGNAL(triggered()), this, SLOT(onCopyColor()));
|
|
menu.addAction(copyAction);
|
|
|
|
menu.exec(event->globalPos());
|
|
event->accept();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! If current red channel value of color is different from \b value set it,
|
|
change \b StyleSample color and emit signal \b
|
|
colorChanged(const TPixel32 &).
|
|
*/
|
|
void ColorField::onRedChannelChanged(int value, bool isDragging) {
|
|
if (m_color.r == value) {
|
|
if (!isDragging) emit colorChanged(m_color, isDragging);
|
|
return;
|
|
}
|
|
m_color = TPixel32(value, m_color.g, m_color.b, m_color.m);
|
|
m_colorSample->setColor(m_color);
|
|
emit colorChanged(m_color, isDragging);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! If current green channel value of color is different from \b value set it,
|
|
change \b StyleSample color and emit signal \b
|
|
colorChanged(const TPixel32 &).
|
|
*/
|
|
void ColorField::onGreenChannelChanged(int value, bool isDragging) {
|
|
if (m_color.g == value) {
|
|
if (!isDragging) emit colorChanged(m_color, isDragging);
|
|
return;
|
|
}
|
|
m_color = TPixel32(m_color.r, value, m_color.b, m_color.m);
|
|
m_colorSample->setColor(m_color);
|
|
emit colorChanged(m_color, isDragging);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! If current blue channel value of color is different from \b value set it,
|
|
change \b StyleSample color and emit signal \b
|
|
colorChanged(const TPixel32 &).
|
|
*/
|
|
void ColorField::onBlueChannelChanged(int value, bool isDragging) {
|
|
if (m_color.b == value) {
|
|
if (!isDragging) emit colorChanged(m_color, isDragging);
|
|
return;
|
|
}
|
|
m_color = TPixel32(m_color.r, m_color.g, value, m_color.m);
|
|
m_colorSample->setColor(m_color);
|
|
emit colorChanged(m_color, isDragging);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/*! If current alpha channel value of color is different from \b value set it,
|
|
change \b StyleSample color and emit signal \b
|
|
colorChanged(const TPixel32 &).
|
|
*/
|
|
void ColorField::onAlphaChannelChanged(int value, bool isDragging) {
|
|
if (m_color.m == value) {
|
|
if (!isDragging) emit colorChanged(m_color, isDragging);
|
|
return;
|
|
}
|
|
m_color = TPixel32(m_color.r, m_color.g, m_color.b, value);
|
|
m_colorSample->setColor(m_color);
|
|
emit colorChanged(m_color, isDragging);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::onPasteColor() {
|
|
QColor color = qobject_cast<QAction *>(sender())->data().value<QColor>();
|
|
|
|
m_color = TPixel32(color.red(), color.green(), color.blue(), color.alpha());
|
|
if (!m_alphaChannel->isVisible()) m_color.m = 255;
|
|
m_colorSample->setColor(m_color);
|
|
updateChannels();
|
|
emit colorChanged(m_color, false);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::onCopyColor() {
|
|
QColor color(m_color.r, m_color.g, m_color.b, m_color.m);
|
|
|
|
QMimeData *data = new QMimeData();
|
|
data->setColorData(color);
|
|
QApplication::clipboard()->setMimeData(data);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::setChessboardColors(const TPixel32 &col1,
|
|
const TPixel32 &col2) {
|
|
m_colorSample->setChessboardColors(col1, col2);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ColorField::setEditorController(
|
|
ColorFieldEditorController *editorController) {
|
|
m_editorController = editorController;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ColorField::ColorFieldEditorController *ColorField::getEditorController() {
|
|
return m_editorController;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
#define SQUARESIZE 50
|
|
|
|
void CleanupColorField::onBrightnessChannelChanged(int value, bool dragging) {
|
|
m_cleanupStyle->setBrightness(value);
|
|
m_ph->notifyColorStyleChanged(dragging);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
|
|
void CleanupColorField::onContrastChannelChanged(int value, bool dragging) {
|
|
m_cleanupStyle->setContrast(value);
|
|
m_ph->notifyColorStyleChanged(dragging);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
|
|
void CleanupColorField::onCThresholdChannelChanged(int value, bool dragging) {
|
|
((TBlackCleanupStyle *)m_cleanupStyle)->setColorThreshold((double)value);
|
|
m_ph->notifyColorStyleChanged(dragging);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
|
|
void CleanupColorField::onWThresholdChannelChanged(int value, bool dragging) {
|
|
((TBlackCleanupStyle *)m_cleanupStyle)->setWhiteThreshold((double)value);
|
|
m_ph->notifyColorStyleChanged(dragging);
|
|
}
|
|
|
|
void CleanupColorField::onHRangeChannelChanged(int value, bool dragging) {
|
|
((TColorCleanupStyle *)m_cleanupStyle)->setHRange(value);
|
|
m_ph->notifyColorStyleChanged(dragging);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
|
|
void CleanupColorField::onLineWidthChannelChanged(int value, bool dragging) {
|
|
((TColorCleanupStyle *)m_cleanupStyle)->setLineWidth(value);
|
|
m_ph->notifyColorStyleChanged(dragging);
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
|
|
void CleanupColorField::mousePressEvent(QMouseEvent *event) {
|
|
if (event->button() != Qt::LeftButton) return;
|
|
|
|
emit StyleSelected(m_cleanupStyle);
|
|
|
|
if (getEditorController()) getEditorController()->edit(this);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
CleanupColorField::CleanupColorField(QWidget *parent,
|
|
TCleanupStyle *cleanupStyle,
|
|
TPaletteHandle *ph, bool greyMode)
|
|
: QWidget(parent)
|
|
, m_style(cleanupStyle)
|
|
, m_cleanupStyle(cleanupStyle)
|
|
, m_ph(ph)
|
|
, m_greyMode(greyMode)
|
|
, m_notifyEditingChange(true) {
|
|
TBlackCleanupStyle *bs = dynamic_cast<TBlackCleanupStyle *>(cleanupStyle);
|
|
TColorCleanupStyle *cs = dynamic_cast<TColorCleanupStyle *>(cleanupStyle);
|
|
assert(bs || cs);
|
|
|
|
m_colorSample = new StyleSample(this, SQUARESIZE / 2, SQUARESIZE);
|
|
m_brightnessChannel =
|
|
new ChannelField(this, DVGui::CleanupColorField::tr("Brightness:"),
|
|
cleanupStyle->getBrightness(), 100, true, 75, -1);
|
|
m_contrastChannel =
|
|
new ChannelField(this, DVGui::CleanupColorField::tr("Contrast:"),
|
|
cleanupStyle->getContrast(), 100, true, 75, -1);
|
|
if (!greyMode) {
|
|
if (bs) {
|
|
m_cThresholdChannel =
|
|
new ChannelField(this, DVGui::CleanupColorField::tr("Color Thres"),
|
|
bs->getColorThreshold(), 100, true, 75, -1);
|
|
m_wThresholdChannel =
|
|
new ChannelField(this, DVGui::CleanupColorField::tr("White Thres"),
|
|
bs->getWhiteThreshold(), 100, true, 75, -1);
|
|
} else // cs
|
|
{
|
|
m_hRangeChannel =
|
|
new ChannelField(this, DVGui::CleanupColorField::tr("H Range"),
|
|
cs->getHRange(), 120, true, 75, -1);
|
|
m_lineWidthChannel =
|
|
new ChannelField(this, DVGui::CleanupColorField::tr("Line Width"),
|
|
cs->getLineWidth(), 100, true, 75, -1);
|
|
}
|
|
}
|
|
|
|
m_colorSample->setStyle(*cleanupStyle, 0);
|
|
|
|
//---- layout
|
|
|
|
QHBoxLayout *mainLay = new QHBoxLayout();
|
|
mainLay->setMargin(8);
|
|
mainLay->setSpacing(5);
|
|
{
|
|
mainLay->addWidget(m_colorSample, 0);
|
|
|
|
QVBoxLayout *paramLay = new QVBoxLayout();
|
|
paramLay->setMargin(0);
|
|
paramLay->setSpacing(3);
|
|
{
|
|
paramLay->addWidget(m_brightnessChannel);
|
|
paramLay->addWidget(m_contrastChannel);
|
|
if (!greyMode) {
|
|
if (bs) {
|
|
paramLay->addWidget(m_cThresholdChannel);
|
|
paramLay->addWidget(m_wThresholdChannel);
|
|
} else {
|
|
paramLay->addWidget(m_hRangeChannel);
|
|
paramLay->addWidget(m_lineWidthChannel);
|
|
}
|
|
}
|
|
}
|
|
mainLay->addLayout(paramLay, 1);
|
|
}
|
|
setLayout(mainLay);
|
|
|
|
//---- signal-slot connections
|
|
|
|
bool ret = true;
|
|
ret = ret && connect(m_brightnessChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onBrightnessChannelChanged(int, bool)));
|
|
ret = ret && connect(m_contrastChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onContrastChannelChanged(int, bool)));
|
|
if (!greyMode) {
|
|
if (bs) {
|
|
ret = ret && connect(m_cThresholdChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onCThresholdChannelChanged(int, bool)));
|
|
ret = ret && connect(m_wThresholdChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onWThresholdChannelChanged(int, bool)));
|
|
} else {
|
|
ret = ret && connect(m_hRangeChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onHRangeChannelChanged(int, bool)));
|
|
ret = ret && connect(m_lineWidthChannel, SIGNAL(valueChanged(int, bool)),
|
|
SLOT(onLineWidthChannelChanged(int, bool)));
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
void CleanupColorField::updateColor() {
|
|
if (m_cleanupStyle->canUpdate()) {
|
|
m_cleanupStyle->invalidateIcon();
|
|
m_colorSample->setStyle(*m_cleanupStyle, 0);
|
|
|
|
m_brightnessChannel->setChannel(m_cleanupStyle->getBrightness());
|
|
if (m_cleanupStyle->isContrastEnabled())
|
|
m_contrastChannel->setChannel(m_cleanupStyle->getContrast());
|
|
|
|
TBlackCleanupStyle *bs;
|
|
TColorCleanupStyle *cs;
|
|
if ((bs = dynamic_cast<TBlackCleanupStyle *>(m_cleanupStyle)) &&
|
|
!m_greyMode) {
|
|
m_cThresholdChannel->setChannel(bs->getColorThreshold());
|
|
m_wThresholdChannel->setChannel(bs->getWhiteThreshold());
|
|
} else if ((cs = dynamic_cast<TColorCleanupStyle *>(m_cleanupStyle))) {
|
|
m_hRangeChannel->setChannel(cs->getHRange());
|
|
m_lineWidthChannel->setChannel(cs->getLineWidth());
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
TPixel32 CleanupColorField::getColor() const {
|
|
return m_cleanupStyle->getMainColor();
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
void CleanupColorField::setColor(const TPixel32 &color) {
|
|
if (m_cleanupStyle->getMainColor() == color) return;
|
|
|
|
m_cleanupStyle->setMainColor(color);
|
|
m_cleanupStyle->invalidateIcon();
|
|
m_colorSample->setStyle(*m_cleanupStyle, 0);
|
|
m_ph->notifyColorStyleChanged(false);
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
|
|
TPixel32 CleanupColorField::getOutputColor() const {
|
|
return m_cleanupStyle->getColorParamValue(1);
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
|
|
void CleanupColorField::setOutputColor(const TPixel32 &color) {
|
|
if (getOutputColor() == color) return;
|
|
|
|
m_cleanupStyle->setColorParamValue(1, color);
|
|
m_cleanupStyle->invalidateIcon();
|
|
m_colorSample->setStyle(*m_cleanupStyle, 0);
|
|
m_ph->notifyColorStyleChanged();
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
|
|
void CleanupColorField::setStyle(TColorStyle *style) {
|
|
if (getColor() == style->getMainColor() &&
|
|
getOutputColor() == style->getColorParamValue(1))
|
|
return;
|
|
|
|
m_cleanupStyle->setMainColor(style->getMainColor());
|
|
m_cleanupStyle->setColorParamValue(1, style->getColorParamValue(1));
|
|
m_cleanupStyle->invalidateIcon();
|
|
m_colorSample->setStyle(*m_cleanupStyle, 0);
|
|
m_ph->notifyColorStyleChanged();
|
|
}
|
|
|
|
//------------------------------------------------------------
|
|
|
|
CleanupColorField::CleanupColorFieldEditorController
|
|
*CleanupColorField::m_editorController = 0;
|
|
|
|
CleanupColorField::CleanupColorFieldEditorController *
|
|
CleanupColorField::getEditorController() {
|
|
return m_editorController;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CleanupColorField::setEditorController(
|
|
CleanupColorFieldEditorController *editorController) {
|
|
m_editorController = editorController;
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
void CleanupColorField::mouseDoubleClickEvent(QMouseEvent *event) {
|
|
QPoint p = event->pos();
|
|
if (!m_colorSample->visibleRegion().contains(p)) return;
|
|
emit StyleSelected(m_cleanupStyle);
|
|
if (!getEditorController()) return;
|
|
|
|
CommandManager::instance()->execute("MI_OpenStyleControl");
|
|
getEditorController()->edit(this);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void CleanupColorField::hideEvent(QHideEvent *) {
|
|
if (!getEditorController()) return;
|
|
getEditorController()->edit(0);
|
|
getEditorController()->hide();
|
|
// setEditorController(0);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void CleanupColorField::setContrastEnabled(bool enable) {
|
|
m_contrastChannel->setEnabled(enable);
|
|
m_cleanupStyle->enableContrast(enable);
|
|
}
|