diff --git a/stuff/config/colornames.txt b/stuff/config/colornames.txt new file mode 100644 index 0000000..f139a27 --- /dev/null +++ b/stuff/config/colornames.txt @@ -0,0 +1,164 @@ + + + + #FF0000 + #00FF00 + #0000FF + + #FFFFFF00 + #FFFFFF00 + #00000000 + #000000 + #FF0000 + #00FF00 + #0000FF + + #F0F8FF + #FAEBD7 + #00FFFF + #7FFFD4 + #F0FFFF + #F5F5DC + #FFE4C4 + #000000 + #FFEBCD + #0000FF + #8A2BE2 + #A52A2A + #DEB887 + #5F9EA0 + #7FFF00 + #D2691E + #FF7F50 + #6495ED + #FFF8DC + #DC143C + #00FFFF + #00008B + #008B8B + #B8860B + #A9A9A9 + #A9A9A9 + #006400 + #BDB76B + #8B008B + #556B2F + #FF8C00 + #9932CC + #8B0000 + #E9967A + #8FBC8F + #483D8B + #2F4F4F + #2F4F4F + #00CED1 + #9400D3 + #FF1493 + #00BFFF + #696969 + #696969 + #1E90FF + #B22222 + #FFFAF0 + #228B22 + #FF00FF + #DCDCDC + #F8F8FF + #FFD700 + #DAA520 + #808080 + #808080 + #008000 + #ADFF2F + #F0FFF0 + #FF69B4 + #CD5C5C + #4B0082 + #FFFFF0 + #F0E68C + #E6E6FA + #FFF0F5 + #7CFC00 + #FFFACD + #ADD8E6 + #F08080 + #E0FFFF + #FAFAD2 + #D3D3D3 + #D3D3D3 + #90EE90 + #FFB6C1 + #FFA07A + #20B2AA + #87CEFA + #778899 + #778899 + #B0C4DE + #FFFFE0 + #00FF00 + #32CD32 + #FAF0E6 + #FF00FF + #800000 + #66CDAA + #0000CD + #BA55D3 + #9370DB + #3CB371 + #7B68EE + #00FA9A + #48D1CC + #C71585 + #191970 + #F5FFFA + #FFE4E1 + #FFE4B5 + #FFDEAD + #000080 + #FDF5E6 + #808000 + #6B8E23 + #FFA500 + #FF4500 + #DA70D6 + #EEE8AA + #98FB98 + #AFEEEE + #DB7093 + #FFEFD5 + #FFDAB9 + #CD853F + #FFC0CB + #DDA0DD + #B0E0E6 + #800080 + #663399 + #FF0000 + #BC8F8F + #4169E1 + #8B4513 + #FA8072 + #F4A460 + #2E8B57 + #FFF5EE + #A0522D + #C0C0C0 + #87CEEB + #6A5ACD + #708090 + #708090 + #FFFAFA + #00FF7F + #4682B4 + #D2B48C + #008080 + #D8BFD8 + #FF6347 + #40E0D0 + #EE82EE + #F5DEB3 + #FFFFFF + #F5F5F5 + #FFFF00 + #9ACD32 + diff --git a/toonz/sources/include/toonzqt/colorfield.h b/toonz/sources/include/toonzqt/colorfield.h index 4e44902..9148f26 100644 --- a/toonz/sources/include/toonzqt/colorfield.h +++ b/toonz/sources/include/toonzqt/colorfield.h @@ -37,6 +37,25 @@ class TPaletteHandle; namespace DVGui { //============================================================================= +// CommonChessboard singleton +//----------------------------------------------------------------------------- + +class DVAPI CommonChessboard final : public QObject { + Q_OBJECT + TRaster32P m_bgRas; + QPixmap m_bgPix; + void setChessboardColors(const TPixel32 &col1, const TPixel32 &col2); + +public: + CommonChessboard(); + + const QPixmap &getPixmap() { return m_bgPix; } + void update(); + + static CommonChessboard *instance(); +}; + +//============================================================================= // StyleSample //----------------------------------------------------------------------------- @@ -49,6 +68,10 @@ class DVAPI StyleSample final : public QWidget { bool m_drawEnable; TPixel m_chessColor1; TPixel m_chessColor2; + bool m_cloneStyle; + bool m_sysChessboard; + bool m_stretch; + QColor m_currentColor; bool m_isEditing; @@ -58,7 +81,7 @@ public: void enableClick(bool on) { m_clickEnabled = on; } - void setStyle(TColorStyle &style); + void setStyle(TColorStyle &style, int colorParameterIndex); TColorStyle *getStyle() const; void setColor(const TPixel32 &color); @@ -73,13 +96,16 @@ public: void setEnable(bool drawEnable) { m_drawEnable = drawEnable; } bool isEnable() const { return m_drawEnable; } + void setCloneStyle(bool enable) { m_cloneStyle = enable; } + void setSystemChessboard(bool enable) { m_sysChessboard = enable; } + protected: void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *) override; void mouseDoubleClickEvent(QMouseEvent *event) override; signals: - void clicked(const TColorStyle &style); + void clicked(); }; //============================================================================= diff --git a/toonz/sources/include/toonzqt/styleeditor.h b/toonz/sources/include/toonzqt/styleeditor.h index e4e93c6..b661dd2 100644 --- a/toonz/sources/include/toonzqt/styleeditor.h +++ b/toonz/sources/include/toonzqt/styleeditor.h @@ -74,6 +74,35 @@ class LutCalibrator; //============================================= +class HexLineEdit : public QLineEdit { + Q_OBJECT + +public: + HexLineEdit(const QString &contents, QWidget *parent); + ~HexLineEdit() {} + + bool loadDefaultColorNames(bool reload); + bool hasUserColorNames(); + bool loadUserColorNames(bool reload); + void setStyle(TColorStyle &style, int index); + void updateColor(); + void setColor(TPixel color); + TPixel getColor() { return m_color; } + bool fromText(QString text); + bool fromHex(QString text); + +protected: + void loadColorTableXML(QMap &table, const TFilePath &fp); + void mousePressEvent(QMouseEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void showEvent(QShowEvent *event) override; + + bool m_editing; + TPixel m_color; + static QMap s_defcolornames; // make it shared + static QMap s_usercolornames; // ... +}; + //============================================================================= namespace StyleEditorGUI { //============================================================================= @@ -238,13 +267,13 @@ signals: //============================================================================= /*! \brief The ColorSlider is used to set a color channel. - Inherits \b QSlider. + Inherits \b QAbstractSlider. This object show a bar which colors differ from minimum to maximum channel color value. */ -class DVAPI ColorSlider final : public QSlider { +class DVAPI ColorSlider final : public QAbstractSlider { Q_OBJECT public: ColorSlider(Qt::Orientation orientation, QWidget *parent = 0); @@ -259,6 +288,9 @@ protected: void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + + void chandleMouse(int x, int y); // QIcon getFirstArrowIcon(); // QIcon getLastArrowIcon(); @@ -268,6 +300,8 @@ protected: private: ColorChannel m_channel; ColorModel m_color; + static int s_chandle_size; + static int s_chandle_tall; }; //============================================================================= @@ -614,6 +648,7 @@ class DVAPI StyleEditor final : public QWidget, public SaveLoadQSettings { PaletteController *m_paletteController; TPaletteHandle *m_paletteHandle; TPaletteHandle *m_cleanupPaletteHandle; + HexLineEdit *m_hexLineEdit; QWidget *m_parent; TXshLevelHandle *m_levelHandle; //!< for clearing the level cache when the color changed @@ -652,6 +687,7 @@ class DVAPI StyleEditor final : public QWidget, public SaveLoadQSettings { QAction *m_hsvAction; QAction *m_alphaAction; QAction *m_rgbAction; + QAction *m_hexAction; TColorStyleP m_oldStyle; //!< A copy of current style \a before the last change. @@ -727,7 +763,8 @@ protected slots: void onStyleSwitched(); void onStyleChanged(bool isDragging); void onCleanupStyleChanged(bool isDragging); - void onOldStyleClicked(const TColorStyle &); + void onOldStyleClicked(); + void onNewStyleClicked(); void updateOrientationButton(); void checkPaletteLock(); // called (e.g.) by PaletteController when an other StyleEditor change the @@ -752,6 +789,8 @@ protected slots: void onParamStyleChanged(bool isDragging); + void onHexChanged(); + void onSpecialButtonToggled(bool on); void onCustomButtonToggled(bool on); void onVectorBrushButtonToggled(bool on); diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index dda75ac..872aa69 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -706,6 +706,12 @@ void PreferencesPopup::onTranspCheckDataChanged() { invalidateIcons(); } //----------------------------------------------------------------------------- +void PreferencesPopup::onChessboardChanged() { + CommonChessboard::instance()->update(); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onSVNEnabledChanged() { if (m_pref->getBoolValue(SVNEnabled)) { if (!VersionControl::instance()->testSetup()) @@ -2043,6 +2049,10 @@ QWidget* PreferencesPopup::createColorsPage() { &PreferencesPopup::notifySceneChanged); m_onEditedFuncMap.insert(chessboardColor2, &PreferencesPopup::notifySceneChanged); + m_onEditedFuncMap.insert(chessboardColor1, + &PreferencesPopup::onChessboardChanged); + m_onEditedFuncMap.insert(chessboardColor2, + &PreferencesPopup::onChessboardChanged); return widget; } diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index df95d9b..06d986c 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -147,6 +147,7 @@ private: void onOnionColorChanged(); // Colors void onTranspCheckDataChanged(); + void onChessboardChanged(); // Version Control void onSVNEnabledChanged(); // Commonly used diff --git a/toonz/sources/toonzqt/Resources/h_chandle_arrow.svg b/toonz/sources/toonzqt/Resources/h_chandle_arrow.svg new file mode 100644 index 0000000..34c1405 --- /dev/null +++ b/toonz/sources/toonzqt/Resources/h_chandle_arrow.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/toonz/sources/toonzqt/Resources/v_chandle_arrow.svg b/toonz/sources/toonzqt/Resources/v_chandle_arrow.svg new file mode 100644 index 0000000..1863d86 --- /dev/null +++ b/toonz/sources/toonzqt/Resources/v_chandle_arrow.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/toonz/sources/toonzqt/colorfield.cpp b/toonz/sources/toonzqt/colorfield.cpp index 52bc928..c1aaf1f 100644 --- a/toonz/sources/toonzqt/colorfield.cpp +++ b/toonz/sources/toonzqt/colorfield.cpp @@ -48,6 +48,31 @@ QPixmap getIconPm(const QColor &color) { } // 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. @@ -82,6 +107,8 @@ StyleSample::StyleSample(QWidget *parent, int sizeX, int sizeY) , m_clickEnabled(false) , m_chessColor1(0, 0, 0) , m_chessColor2(255, 255, 255) + , m_sysChessboard(false) + , m_stretch(true) , m_isEditing(false) { setMinimumSize(sizeX, sizeY); setColor(TPixel32::Transparent); @@ -106,17 +133,26 @@ 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) { +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); + /*-- TSolidColorStyleの場合のみ、単色塗りつぶし --*/ - if (style.getTagId() == 3) + if (style.getTagId() == 3) { setColor(style.getMainColor()); - else { + m_stretch = true; + } else { TRaster32P icon = style.getIcon(qsize2Dimension(m_samplePixmap.rect().size())); m_samplePixmap = rasterToQImage(icon, false); // modified in 6.2 + m_stretch = false; update(); } - if (m_clickEnabled) m_style = style.clone(); + if (m_cloneStyle) { + if (m_style) delete m_style; // avoid memory leak + m_style = style.clone(); + } } //----------------------------------------------------------------------------- @@ -149,10 +185,22 @@ void StyleSample::setChessboardColors(const TPixel32 &col1, void StyleSample::paintEvent(QPaintEvent *event) { if (!isEnable()) return; QPainter painter(this); - QImage img(m_bgRas->getRawData(), m_bgRas->getLx(), m_bgRas->getLy(), - QImage::Format_ARGB32); - painter.drawImage(0, 0, img.scaled(size())); - painter.drawImage(0, 0, m_samplePixmap.scaled(size())); + 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 { + 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); @@ -168,8 +216,8 @@ void StyleSample::paintEvent(QPaintEvent *event) { clicked(const TColorStyle &style). */ void StyleSample::mousePressEvent(QMouseEvent *event) { - if (m_style && m_clickEnabled) - emit clicked(*m_style); + if (m_clickEnabled) + emit clicked(); else event->ignore(); } @@ -771,7 +819,7 @@ CleanupColorField::CleanupColorField(QWidget *parent, } } - m_colorSample->setStyle(*cleanupStyle); + m_colorSample->setStyle(*cleanupStyle, 0); //---- layout @@ -828,7 +876,7 @@ CleanupColorField::CleanupColorField(QWidget *parent, void CleanupColorField::updateColor() { if (m_cleanupStyle->canUpdate()) { m_cleanupStyle->invalidateIcon(); - m_colorSample->setStyle(*m_cleanupStyle); + m_colorSample->setStyle(*m_cleanupStyle, 0); m_brightnessChannel->setChannel(m_cleanupStyle->getBrightness()); if (m_cleanupStyle->isContrastEnabled()) @@ -860,7 +908,7 @@ void CleanupColorField::setColor(const TPixel32 &color) { m_cleanupStyle->setMainColor(color); m_cleanupStyle->invalidateIcon(); - m_colorSample->setStyle(*m_cleanupStyle); + m_colorSample->setStyle(*m_cleanupStyle, 0); m_ph->notifyColorStyleChanged(false); } @@ -877,7 +925,7 @@ void CleanupColorField::setOutputColor(const TPixel32 &color) { m_cleanupStyle->setColorParamValue(1, color); m_cleanupStyle->invalidateIcon(); - m_colorSample->setStyle(*m_cleanupStyle); + m_colorSample->setStyle(*m_cleanupStyle, 0); m_ph->notifyColorStyleChanged(); } @@ -891,7 +939,7 @@ void CleanupColorField::setStyle(TColorStyle *style) { m_cleanupStyle->setMainColor(style->getMainColor()); m_cleanupStyle->setColorParamValue(1, style->getColorParamValue(1)); m_cleanupStyle->invalidateIcon(); - m_colorSample->setStyle(*m_cleanupStyle); + m_colorSample->setStyle(*m_cleanupStyle, 0); m_ph->notifyColorStyleChanged(); } diff --git a/toonz/sources/toonzqt/styleeditor.cpp b/toonz/sources/toonzqt/styleeditor.cpp index 78334a9..3f00653 100644 --- a/toonz/sources/toonzqt/styleeditor.cpp +++ b/toonz/sources/toonzqt/styleeditor.cpp @@ -37,6 +37,7 @@ #include "tvectorrenderdata.h" #include "tsimplecolorstyles.h" #include "tvectorbrushstyle.h" +#include "tenv.h" // Qt includes #include @@ -61,6 +62,212 @@ using namespace StyleEditorGUI; //***************************************************************************** +// Hex line editor +//***************************************************************************** + +#define COLORNAMES_FILE "colornames.txt" + +QMap HexLineEdit::s_defcolornames; +QMap HexLineEdit::s_usercolornames; + +HexLineEdit::HexLineEdit(const QString &contents, QWidget *parent) + : QLineEdit(contents, parent), m_editing(false), m_color(0, 0, 0) {} + +bool HexLineEdit::loadDefaultColorNames(bool reload) { + TFilePath defCTFp = TEnv::getConfigDir() + COLORNAMES_FILE; + + // Load default color names + try { + if (reload || s_defcolornames.size() == 0) { + s_defcolornames.clear(); + loadColorTableXML(s_defcolornames, defCTFp); + } + } catch (...) { + return false; + } + return true; +} + +bool HexLineEdit::hasUserColorNames() { + TFilePath userCTFp = ToonzFolder::getMyModuleDir() + COLORNAMES_FILE; + return TFileStatus(userCTFp).doesExist(); +} + +bool HexLineEdit::loadUserColorNames(bool reload) { + TFilePath userCTFp = ToonzFolder::getMyModuleDir() + COLORNAMES_FILE; + + // Load user color names (if exists...) + if (TFileStatus(userCTFp).doesExist()) { + try { + if (reload || s_usercolornames.size() == 0) { + s_usercolornames.clear(); + loadColorTableXML(s_usercolornames, userCTFp); + } + } catch (...) { + return false; + } + } + return true; +} + +void HexLineEdit::updateColor() { + if (m_color.m == 255) { + // Opaque, omit alpha + setText(QString("#%1%2%3") + .arg(m_color.r, 2, 16, QLatin1Char('0')) + .arg(m_color.g, 2, 16, QLatin1Char('0')) + .arg(m_color.b, 2, 16, QLatin1Char('0')) + .toUpper()); + } else { + setText(QString("#%1%2%3%4") + .arg(m_color.r, 2, 16, QLatin1Char('0')) + .arg(m_color.g, 2, 16, QLatin1Char('0')) + .arg(m_color.b, 2, 16, QLatin1Char('0')) + .arg(m_color.m, 2, 16, QLatin1Char('0')) + .toUpper()); + } +} + +void HexLineEdit::setColor(TPixel color) { + if (m_color != color) { + m_color = color; + if (isVisible()) updateColor(); + } +} + +bool HexLineEdit::fromText(QString text) { + static QRegExp space("\\s"); + text.remove(space); + if (text.size() == 0) return false; + if (text[0] == "#") return fromHex(text); + text = text.toLower(); // table names are lowercase + + // Find color from tables, user takes priority + QMap::const_iterator it; + it = s_usercolornames.constFind(text); + if (it == s_usercolornames.constEnd()) { + it = s_defcolornames.constFind(text); + if (it == s_defcolornames.constEnd()) return false; + } + + QString hexText = it.value(); + return fromHex(hexText); +} + +// Whitespaces can break this implementation, thankfully +// '.fromText' already took care of it. +bool HexLineEdit::fromHex(QString text) { + if (text.size() == 0) return false; + if (text[0] != "#") return false; + text.remove(0, 1); + bool ok; + uint parsedValue = text.toUInt(&ok, 16); + if (!ok) return false; + + switch (text.length()) { + case 8: // #RRGGBBAA + m_color.r = parsedValue >> 24; + m_color.g = parsedValue >> 16; + m_color.b = parsedValue >> 8; + m_color.m = parsedValue; + break; + case 6: // #RRGGBB + m_color.r = parsedValue >> 16; + m_color.g = parsedValue >> 8; + m_color.b = parsedValue; + m_color.m = 255; + break; + case 4: // #RGBA + m_color.r = (parsedValue >> 12) & 15; + m_color.r |= m_color.r << 4; + m_color.g = (parsedValue >> 8) & 15; + m_color.g |= m_color.g << 4; + m_color.b = (parsedValue >> 4) & 15; + m_color.b |= m_color.b << 4; + m_color.m = parsedValue & 15; + m_color.m |= m_color.m << 4; + break; + case 3: // #RGB + m_color.r = (parsedValue >> 8) & 15; + m_color.r |= m_color.r << 4; + m_color.g = (parsedValue >> 4) & 15; + m_color.g |= m_color.g << 4; + m_color.b = parsedValue & 15; + m_color.b |= m_color.b << 4; + m_color.m = 255; + break; + case 2: // #VV (non-standard) + m_color.r = parsedValue; + m_color.g = m_color.r; + m_color.b = m_color.r; + m_color.m = 255; + break; + case 1: // #V (non-standard) + m_color.r = parsedValue & 15; + m_color.r |= m_color.r << 4; + m_color.g = m_color.r; + m_color.b = m_color.r; + m_color.m = 255; + break; + default: + return false; + } + updateColor(); + return true; +} + +void HexLineEdit::loadColorTableXML(QMap &table, + const TFilePath &fp) { + if (!TFileStatus(fp).doesExist()) throw TException("File not found"); + + TIStream is(fp); + if (!is) throw TException("Can't read color names"); + + std::string tagName; + if (!is.matchTag(tagName) || tagName != "colors") + throw TException("Not a color names file"); + + while (!is.matchEndTag()) { + if (!is.matchTag(tagName)) throw TException("Expected tag"); + if (tagName == "color") { + QString name, hex; + name = QString::fromStdString(is.getTagAttribute("name")); + std::string hexs; + is >> hexs; + hex = QString::fromStdString(hexs); + if (name.size() != 0 && hex.size() != 0) + table.insert(name.toLower(), hex); + if (!is.matchEndTag()) throw TException("Expected end tag"); + } else + throw TException("unexpected tag /" + tagName + "/"); + } +} + +void HexLineEdit::setStyle(TColorStyle &style, int index) { + setColor(style.getColorParamValue(index)); +} + +void HexLineEdit::mousePressEvent(QMouseEvent *event) { + QLineEdit::mousePressEvent(event); + // Make Ctrl key disable select all so the user can click a specific character + // after a focus-in, this likely will fall into a hidden feature thought. + bool ctrlDown = event->modifiers() & Qt::ControlModifier; + if (!m_editing && !ctrlDown) selectAll(); + m_editing = true; +} + +void HexLineEdit::focusOutEvent(QFocusEvent *event) { + QLineEdit::focusOutEvent(event); + deselect(); + m_editing = false; +} + +void HexLineEdit::showEvent(QShowEvent *event) { + QLineEdit::showEvent(event); + updateColor(); +} + +//***************************************************************************** // UndoPaletteChange definition //***************************************************************************** @@ -476,25 +683,13 @@ QPixmap makeLinearShading(const ColorModel &color, ColorChannel channel, int size, bool isVertical) { switch (channel) { case eRed: - if (isVertical) - return makeLinearShading(RedShadeMaker(color), size, isVertical); - else - return QPixmap(":Resources/grad_r.png").scaled(size, 1); + return makeLinearShading(RedShadeMaker(color), size, isVertical); case eGreen: - if (isVertical) - return makeLinearShading(GreenShadeMaker(color), size, isVertical); - else - return QPixmap(":Resources/grad_g.png").scaled(size, 1); + return makeLinearShading(GreenShadeMaker(color), size, isVertical); case eBlue: - if (isVertical) - return makeLinearShading(BlueShadeMaker(color), size, isVertical); - else - return QPixmap(":Resources/grad_b.png").scaled(size, 1); + return makeLinearShading(BlueShadeMaker(color), size, isVertical); case eAlpha: - if (isVertical) - return makeLinearShading(AlphaShadeMaker(color), size, isVertical); - else - return QPixmap(":Resources/grad_m.png").scaled(size, 1); + return makeLinearShading(AlphaShadeMaker(color), size, isVertical); case eHue: return makeLinearShading(HueShadeMaker(color), size, isVertical); case eSaturation: @@ -981,8 +1176,12 @@ void SquaredColorWheel::setChannel(int channel) { // ColorSlider implementation //***************************************************************************** +// Adquire size later... +int ColorSlider::s_chandle_size = -1; +int ColorSlider::s_chandle_tall = -1; + ColorSlider::ColorSlider(Qt::Orientation orientation, QWidget *parent) - : QSlider(orientation, parent), m_channel(eRed), m_color() { + : QAbstractSlider(parent), m_channel(eRed), m_color() { setFocusPolicy(Qt::NoFocus); setOrientation(orientation); @@ -992,6 +1191,13 @@ ColorSlider::ColorSlider(Qt::Orientation orientation, QWidget *parent) setMinimumHeight(7); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + // Get color handle size once + if (s_chandle_size == -1) { + QImage chandle = QImage(":Resources/h_chandle_arrow.svg"); + s_chandle_size = chandle.width(); + s_chandle_tall = chandle.height(); + } + // Attenzione: necessario per poter individuare l'oggetto nel file di // definizione dello stile setObjectName("colorSlider"); @@ -1021,18 +1227,25 @@ void ColorSlider::paintEvent(QPaintEvent *event) { bool isVertical = orientation() == Qt::Vertical; - if (!isVertical) h -= 5; + if (isVertical) { + y += s_chandle_size / 2; + h -= s_chandle_size; + w -= 3; + } else { + x += s_chandle_size / 2; + w -= s_chandle_size; + h -= 3; + } QPixmap bgPixmap = makeLinearShading(m_color, m_channel, isVertical ? h : w, isVertical); if (m_channel == eAlpha) { - static QPixmap checkboard(":Resources/backg.png"); - p.drawTiledPixmap(x, y + 1, w, h, checkboard); + p.drawTiledPixmap(x, y, w, h, DVGui::CommonChessboard::instance()->getPixmap()); } if (!bgPixmap.isNull()) { - p.drawTiledPixmap(x, y + 1, w, h, bgPixmap); + p.drawTiledPixmap(x, y, w, h, bgPixmap); } /*! @@ -1040,59 +1253,20 @@ void ColorSlider::paintEvent(QPaintEvent *event) { In this case we draw "manually" the slider handle at correct position */ if (isVertical) { - int pos = QStyle::sliderPositionFromValue(minimum(), maximum(), value(), - h - 9, true); - static QPixmap vHandlePixmap(":Resources/v_chandle.png"); - p.drawPixmap(0, pos, vHandlePixmap); + static QPixmap vHandlePixmap = svgToPixmap(":Resources/v_chandle_arrow.svg"); + int pos = QStyle::sliderPositionFromValue(0, maximum(), value(), h, true); + p.drawPixmap(width() - s_chandle_tall, pos, vHandlePixmap); } else { - static QPixmap hHandleUpPm(":Resources/h_chandleUp.png"); - static QPixmap hHandleDownPm(":Resources/h_chandleDown.png"); - static QPixmap hHandleCenterPm(":Resources/h_chandleCenter.png"); - int pos = QStyle::sliderPositionFromValue( - 0, maximum(), value(), width() - hHandleCenterPm.width(), false); - p.drawPixmap(pos, 0, hHandleUpPm); - p.drawPixmap(pos, height() - hHandleDownPm.height(), hHandleDownPm); - p.drawPixmap(pos, hHandleUpPm.height(), hHandleCenterPm.width(), - height() - hHandleUpPm.height() - hHandleDownPm.height(), - hHandleCenterPm); + static QPixmap hHandlePixmap = svgToPixmap(":Resources/h_chandle_arrow.svg"); + int pos = QStyle::sliderPositionFromValue(0, maximum(), value(), w, false); + p.drawPixmap(pos, height() - s_chandle_tall, hHandlePixmap); } }; //----------------------------------------------------------------------------- void ColorSlider::mousePressEvent(QMouseEvent *event) { - // vogliamo che facendo click sullo slider, lontano dall'handle - // l'handle salti subito nella posizione giusta invece di far partire - // l'autorepeat. - // - // cfr. qslider.cpp:429: sembra che questo comportamento si possa ottenere - // anche con SH_Slider_AbsoluteSetButtons. Ma non capisco come si possa fare - // per definire quest hint - QStyleOptionSlider opt; - initStyleOption(&opt); - const QRect handleRect = style()->subControlRect( - QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); - if (!handleRect.contains(event->pos())) { - const QPoint handleCenter = handleRect.center(); - const QRect grooveRect = style()->subControlRect( - QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this); - int pos, span; - bool upsideDown = false; - if (opt.orientation == Qt::Vertical) { - upsideDown = true; - int handleSize = handleRect.height(); - pos = event->pos().y() - handleSize / 2; - span = grooveRect.height() - handleSize; - } else { - int handleSize = QPixmap(":Resources/h_chandleCenter.png").width(); - pos = event->pos().x() - handleSize / 2; - span = grooveRect.width() - handleSize; - } - int value = QStyle::sliderValueFromPosition(minimum(), maximum(), pos, span, - upsideDown); - setValue(value); - } - QSlider::mousePressEvent(event); + chandleMouse(event->pos().x(), event->pos().y()); } //----------------------------------------------------------------------------- @@ -1101,6 +1275,26 @@ void ColorSlider::mouseReleaseEvent(QMouseEvent *event) { emit sliderReleased(); } +//----------------------------------------------------------------------------- + +void ColorSlider::mouseMoveEvent(QMouseEvent *event) { + chandleMouse(event->pos().x(), event->pos().y()); +} + +//----------------------------------------------------------------------------- + +void ColorSlider::chandleMouse(int mouse_x, int mouse_y) { + if (orientation() == Qt::Vertical) { + int pos = mouse_y - s_chandle_size / 2; + int span = height() - s_chandle_size; + setValue(QStyle::sliderValueFromPosition(0, maximum(), pos, span, true)); + } else { + int pos = mouse_x - s_chandle_size / 2; + int span = width() - s_chandle_size; + setValue(QStyle::sliderValueFromPosition(0, maximum(), pos, span, false)); + } +} + //***************************************************************************** // ArrowButton implementation //***************************************************************************** @@ -1425,7 +1619,7 @@ StyleEditorPage::StyleEditorPage(QWidget *parent) : QFrame(parent) { ColorParameterSelector::ColorParameterSelector(QWidget *parent) : QWidget(parent) - , m_index(-1) + , m_index(0) , m_chipSize(21, 21) , m_chipOrigin(0, 1) , m_chipDelta(21, 0) { @@ -1479,7 +1673,7 @@ void ColorParameterSelector::setStyle(const TColorStyle &style) { void ColorParameterSelector::clear() { if (m_colors.size() != 0) m_colors.clear(); - m_index = -1; + m_index = 0; update(); } @@ -1490,7 +1684,7 @@ void ColorParameterSelector::mousePressEvent(QMouseEvent *event) { int index = pos.x() / m_chipDelta.x(); QRect chipRect(index * m_chipDelta, m_chipSize); if (chipRect.contains(pos)) { - m_index = index; + if (index < m_colors.size()) m_index = index; emit colorParamChanged(); update(); } @@ -2391,7 +2585,7 @@ void SpecialStyleChooserPage::loadItems() { tagId == 2000 || // imagepattern tagId == 2800 || // imagepattern tagId == 2001 || // cleanup - tagId == 2002 || // ?? + tagId == 2002 || // black cleanup tagId == 3000 || // vector brush tagId == 4001 // mypaint brush ) @@ -3013,19 +3207,23 @@ StyleEditor::StyleEditor(PaletteController *paletteController, QWidget *parent) m_hsvAction = new QAction(tr("HSV"), this); m_alphaAction = new QAction(tr("Alpha"), this); m_rgbAction = new QAction(tr("RGB"), this); + m_hexAction = new QAction(tr("Hex"), this); m_wheelAction->setCheckable(true); m_hsvAction->setCheckable(true); m_alphaAction->setCheckable(true); m_rgbAction->setCheckable(true); + m_hexAction->setCheckable(true); m_wheelAction->setChecked(true); m_hsvAction->setChecked(true); m_alphaAction->setChecked(true); m_rgbAction->setChecked(true); + m_hexAction->setChecked(false); menu->addAction(m_wheelAction); menu->addAction(m_hsvAction); menu->addAction(m_alphaAction); menu->addAction(m_rgbAction); + menu->addAction(m_hexAction); QToolButton *toolButton = new QToolButton(this); toolButton->setIcon(createQIcon("menu")); @@ -3106,6 +3304,10 @@ StyleEditor::StyleEditor(PaletteController *paletteController, QWidget *parent) m_plainColorPage->m_alphaFrame, SLOT(setVisible(bool))); ret = ret && connect(m_rgbAction, SIGNAL(toggled(bool)), m_plainColorPage->m_rgbFrame, SLOT(setVisible(bool))); + ret = ret && connect(m_hexAction, SIGNAL(toggled(bool)), m_hexLineEdit, + SLOT(setVisible(bool))); + ret = ret && connect(m_hexLineEdit, SIGNAL(editingFinished()), this, + SLOT(onHexChanged())); ret = ret && connect(m_toggleOrientationAction, SIGNAL(triggered()), m_plainColorPage, SLOT(toggleOrientation())); ret = ret && connect(m_toggleOrientationAction, SIGNAL(triggered()), this, @@ -3135,8 +3337,8 @@ void StyleEditor::setPaletteHandle(TPaletteHandle* paletteHandle) QFrame *StyleEditor::createBottomWidget() { QFrame *bottomWidget = new QFrame(this); m_autoButton = new QPushButton(tr("Auto")); - m_oldColor = new DVGui::StyleSample(this, 42, 20); - m_newColor = new DVGui::StyleSample(this, 42, 20); + m_oldColor = new DVGui::StyleSample(this, 42, 24); + m_newColor = new DVGui::StyleSample(this, 42, 24); m_applyButton = new QPushButton(tr("Apply")); bottomWidget->setFrameStyle(QFrame::StyledPanel); @@ -3154,8 +3356,18 @@ QFrame *StyleEditor::createBottomWidget() { m_oldColor->setToolTip(tr("Return To Previous Style")); m_oldColor->enableClick(true); m_oldColor->setEnable(false); + m_oldColor->setSystemChessboard(true); + m_oldColor->setCloneStyle(true); m_newColor->setToolTip(tr("Current Style")); + m_newColor->enableClick(true); m_newColor->setEnable(false); + m_newColor->setSystemChessboard(true); + + m_hexLineEdit = new HexLineEdit("", this); + m_hexLineEdit->setObjectName("HexLineEdit"); + m_hexLineEdit->setFixedWidth(75); + m_hexLineEdit->loadDefaultColorNames(false); + m_hexLineEdit->loadUserColorNames(false); /* ------ layout ------ */ QVBoxLayout *mainLayout = new QVBoxLayout; @@ -3167,10 +3379,13 @@ QFrame *StyleEditor::createBottomWidget() { hLayout->setSpacing(0); { hLayout->addWidget(m_autoButton); + hLayout->addSpacing(2); hLayout->addWidget(m_applyButton); hLayout->addSpacing(2); hLayout->addWidget(m_newColor, 1); hLayout->addWidget(m_oldColor, 1); + hLayout->addSpacing(2); + hLayout->addWidget(m_hexLineEdit); } mainLayout->addLayout(hLayout); @@ -3188,8 +3403,10 @@ QFrame *StyleEditor::createBottomWidget() { SLOT(applyButtonClicked())); ret = ret && connect(m_autoButton, SIGNAL(toggled(bool)), this, SLOT(autoCheckChanged(bool))); - ret = ret && connect(m_oldColor, SIGNAL(clicked(const TColorStyle &)), this, - SLOT(onOldStyleClicked(const TColorStyle &))); + ret = ret && connect(m_oldColor, SIGNAL(clicked()), this, + SLOT(onOldStyleClicked())); + ret = ret && connect(m_newColor, SIGNAL(clicked()), this, + SLOT(onNewStyleClicked())); assert(ret); return bottomWidget; @@ -3308,6 +3525,7 @@ void StyleEditor::showEvent(QShowEvent *) { m_plainColorPage->m_hsvFrame->setVisible(m_hsvAction->isChecked()); m_plainColorPage->m_alphaFrame->setVisible(m_alphaAction->isChecked()); m_plainColorPage->m_rgbFrame->setVisible(m_rgbAction->isChecked()); + m_hexLineEdit->setVisible(m_hexAction->isChecked()); updateOrientationButton(); assert(ret); } @@ -3404,9 +3622,11 @@ void StyleEditor::onStyleChanged(bool isDragging) { m_plainColorPage->setColor(*m_editedStyle, getColorParam()); m_colorParameterSelector->setStyle(*m_editedStyle); m_settingsPage->setStyle(m_editedStyle); - m_newColor->setStyle(*m_editedStyle); + m_newColor->setStyle(*m_editedStyle, getColorParam()); m_oldColor->setStyle( - *m_oldStyle); // This line is needed for proper undo behavior + *m_oldStyle, + getColorParam()); // This line is needed for proper undo behavior + m_hexLineEdit->setStyle(*m_editedStyle, getColorParam()); } //----------------------------------------------------------------------- @@ -3501,8 +3721,9 @@ void StyleEditor::onColorChanged(const ColorModel &color, bool isDragging) { delete style; } - m_newColor->setStyle(*m_editedStyle); + m_newColor->setStyle(*m_editedStyle, getColorParam()); m_colorParameterSelector->setStyle(*m_editedStyle); + m_hexLineEdit->setStyle(*m_editedStyle, getColorParam()); // Auto Button should be disabled with locked palette if (m_autoButton->isEnabled() && m_autoButton->isChecked()) { copyEditedStyleToPalette(isDragging); @@ -3524,6 +3745,7 @@ void StyleEditor::enable(bool enabled, bool enabledOnlyFirstTab, m_applyButton->setDisabled(!enabled || m_autoButton->isChecked()); m_oldColor->setEnable(enabled); m_newColor->setEnable(enabled); + m_hexLineEdit->setEnabled(enabled); if (enabled == false) { m_oldColor->setColor(TPixel32::Transparent); m_newColor->setColor(TPixel32::Transparent); @@ -3558,13 +3780,19 @@ void StyleEditor::checkPaletteLock() { //----------------------------------------------------------------------------- -void StyleEditor::onOldStyleClicked(const TColorStyle &) { +void StyleEditor::onOldStyleClicked() { if (!m_enabled) return; selectStyle(*(m_oldColor->getStyle())); } //----------------------------------------------------------------------------- +void StyleEditor::onNewStyleClicked() { + applyButtonClicked(); +} + +//----------------------------------------------------------------------------- + void StyleEditor::setPage(int index) { if (!m_enabledFirstAndLastTab) { m_styleChooser->setCurrentIndex(index); @@ -3636,8 +3864,9 @@ bool StyleEditor::setStyle(TColorStyle *currentStyle) { if (currentStyle) { m_colorParameterSelector->setStyle(*currentStyle); m_plainColorPage->setColor(*currentStyle, getColorParam()); - m_oldColor->setStyle(*currentStyle); - m_newColor->setStyle(*currentStyle); + m_oldColor->setStyle(*currentStyle, getColorParam()); + m_newColor->setStyle(*currentStyle, getColorParam()); + m_hexLineEdit->setStyle(*m_editedStyle, getColorParam()); setOldStyleToStyle(currentStyle); } @@ -3702,10 +3931,11 @@ void StyleEditor::selectStyle(const TColorStyle &newStyle) { } // Update editor widgets - m_newColor->setStyle(*m_editedStyle); + m_newColor->setStyle(*m_editedStyle, getColorParam()); m_plainColorPage->setColor(*m_editedStyle, getColorParam()); m_colorParameterSelector->setStyle(*m_editedStyle); m_settingsPage->setStyle(m_editedStyle); + m_hexLineEdit->setStyle(*m_editedStyle, getColorParam()); } //----------------------------------------------------------------------------- @@ -3722,8 +3952,12 @@ void StyleEditor::onColorParamChanged() { if (TColorStyle *currentStyle = palette->getStyle(styleIndex)) { setEditedStyleToStyle(currentStyle); + m_newColor->setStyle(*m_editedStyle, getColorParam()); + m_oldColor->setStyle(*m_editedStyle, getColorParam()); m_plainColorPage->setColor(*m_editedStyle, getColorParam()); + m_colorParameterSelector->setStyle(*m_editedStyle); m_settingsPage->setStyle(m_editedStyle); + m_hexLineEdit->setStyle(*m_editedStyle, getColorParam()); } } @@ -3739,7 +3973,19 @@ void StyleEditor::onParamStyleChanged(bool isDragging) { if (m_autoButton->isChecked()) copyEditedStyleToPalette(isDragging); m_editedStyle->invalidateIcon(); // Refresh the new color icon - m_newColor->setStyle(*m_editedStyle); // + m_newColor->setStyle(*m_editedStyle, getColorParam()); + m_hexLineEdit->setStyle(*m_editedStyle, getColorParam()); +} + +//----------------------------------------------------------------------------- + +void StyleEditor::onHexChanged() { + if (m_hexLineEdit->fromText(m_hexLineEdit->text())) { + ColorModel cm; + cm.setTPixel(m_hexLineEdit->getColor()); + onColorChanged(cm, false); + m_hexLineEdit->selectAll(); + } } //----------------------------------------------------------------------------- @@ -3775,6 +4021,7 @@ void StyleEditor::save(QSettings &settings) const { if (m_hsvAction->isChecked()) visibleParts |= 0x02; if (m_alphaAction->isChecked()) visibleParts |= 0x04; if (m_rgbAction->isChecked()) visibleParts |= 0x08; + if (m_hexAction->isChecked()) visibleParts |= 0x10; settings.setValue("visibleParts", visibleParts); settings.setValue("splitterState", m_plainColorPage->getSplitterState()); } @@ -3804,6 +4051,10 @@ void StyleEditor::load(QSettings &settings) { m_rgbAction->setChecked(true); else m_rgbAction->setChecked(false); + if (visiblePartsInt & 0x10) + m_hexAction->setChecked(true); + else + m_hexAction->setChecked(false); } QVariant splitterState = settings.value("splitterState"); if (splitterState.canConvert(QVariant::ByteArray)) @@ -3814,4 +4065,4 @@ void StyleEditor::load(QSettings &settings) { void StyleEditor::updateColorCalibration() { m_plainColorPage->updateColorCalibration(); -} \ No newline at end of file +} diff --git a/toonz/sources/toonzqt/toonzqt.qrc b/toonz/sources/toonzqt/toonzqt.qrc index a2a8845..20066b8 100644 --- a/toonz/sources/toonzqt/toonzqt.qrc +++ b/toonz/sources/toonzqt/toonzqt.qrc @@ -26,9 +26,8 @@ Resources/grad_g.png Resources/grad_b.png Resources/grad_m.png - Resources/h_chandleDown.png - Resources/h_chandleCenter.png - Resources/h_chandleUp.png + Resources/h_chandle_arrow.svg + Resources/v_chandle_arrow.svg Resources/schematic_palette.png Resources/schematic_tablenode.png Resources/port_red.svg