Merge pull request #57361 from troopa81/cmyk_colorwidget

[ColorWidget] Add CMYK support
This commit is contained in:
Julien Cabieces 2024-05-23 18:03:52 +02:00 committed by GitHub
commit eaa0261c5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 1504 additions and 808 deletions

View File

@ -7,6 +7,10 @@ QgsColorWidget.Hue = QgsColorWidget.ColorComponent.Hue
QgsColorWidget.Saturation = QgsColorWidget.ColorComponent.Saturation QgsColorWidget.Saturation = QgsColorWidget.ColorComponent.Saturation
QgsColorWidget.Value = QgsColorWidget.ColorComponent.Value QgsColorWidget.Value = QgsColorWidget.ColorComponent.Value
QgsColorWidget.Alpha = QgsColorWidget.ColorComponent.Alpha QgsColorWidget.Alpha = QgsColorWidget.ColorComponent.Alpha
QgsColorWidget.Cyan = QgsColorWidget.ColorComponent.Cyan
QgsColorWidget.Magenta = QgsColorWidget.ColorComponent.Magenta
QgsColorWidget.Yellow = QgsColorWidget.ColorComponent.Yellow
QgsColorWidget.Black = QgsColorWidget.ColorComponent.Black
QgsColorRampWidget.Horizontal = QgsColorRampWidget.Orientation.Horizontal QgsColorRampWidget.Horizontal = QgsColorRampWidget.Orientation.Horizontal
QgsColorRampWidget.Vertical = QgsColorRampWidget.Orientation.Vertical QgsColorRampWidget.Vertical = QgsColorRampWidget.Orientation.Vertical
QgsColorTextWidget.HexRgb = QgsColorTextWidget.ColorTextFormat.HexRgb QgsColorTextWidget.HexRgb = QgsColorTextWidget.ColorTextFormat.HexRgb

View File

@ -33,7 +33,11 @@ set to a color with an ambiguous hue (e.g., black or white shades).
Hue, Hue,
Saturation, Saturation,
Value, Value,
Alpha Alpha,
Cyan,
Magenta,
Yellow,
Black
}; };
QgsColorWidget( QWidget *parent /TransferThis/ = 0, ColorComponent component = Multiple ); QgsColorWidget( QWidget *parent /TransferThis/ = 0, ColorComponent component = Multiple );
@ -145,7 +149,7 @@ Returns the range of valid values for the color widget's component
:return: maximum value allowed for color component, or -1 if widget has multiple components :return: maximum value allowed for color component, or -1 if widget has multiple components
%End %End
int componentRange( ColorComponent component ) const; static int componentRange( ColorComponent component );
%Docstring %Docstring
Returns the range of valid values a color component Returns the range of valid values a color component
@ -172,7 +176,7 @@ as QColor returns a hue of -1 if the color's hue is ambiguous (e.g., if the satu
:return: explicitly set hue for widget :return: explicitly set hue for widget
%End %End
void alterColor( QColor &color, QgsColorWidget::ColorComponent component, int newValue ) const; static void alterColor( QColor &color, QgsColorWidget::ColorComponent component, int newValue );
%Docstring %Docstring
Alters a color by modifying the value of a specific color component Alters a color by modifying the value of a specific color component
@ -182,6 +186,16 @@ Alters a color by modifying the value of a specific color component
valid range for the color component. valid range for the color component.
%End %End
QColor::Spec colorSpec() const;
%Docstring
Returns color widget type of color, either RGB, HSV, CMYK, or Invalid if this component value is Multiple or Alpha
%End
static QColor::Spec colorSpec( QgsColorWidget::ColorComponent component );
%Docstring
Returns ``component`` type of color, either RGB, HSV, CMYK, or Invalid if ``component`` value is Multiple or Alpha
%End
static const QPixmap &transparentBackground(); static const QPixmap &transparentBackground();
%Docstring %Docstring
Generates a checkboard pattern pixmap for use as a background to transparent colors Generates a checkboard pattern pixmap for use as a background to transparent colors
@ -201,6 +215,7 @@ Generates a checkboard pattern pixmap for use as a background to transparent col
virtual void mouseReleaseEvent( QMouseEvent *e ); virtual void mouseReleaseEvent( QMouseEvent *e );
}; };

View File

@ -33,7 +33,11 @@ set to a color with an ambiguous hue (e.g., black or white shades).
Hue, Hue,
Saturation, Saturation,
Value, Value,
Alpha Alpha,
Cyan,
Magenta,
Yellow,
Black
}; };
QgsColorWidget( QWidget *parent /TransferThis/ = 0, ColorComponent component = Multiple ); QgsColorWidget( QWidget *parent /TransferThis/ = 0, ColorComponent component = Multiple );
@ -145,7 +149,7 @@ Returns the range of valid values for the color widget's component
:return: maximum value allowed for color component, or -1 if widget has multiple components :return: maximum value allowed for color component, or -1 if widget has multiple components
%End %End
int componentRange( ColorComponent component ) const; static int componentRange( ColorComponent component );
%Docstring %Docstring
Returns the range of valid values a color component Returns the range of valid values a color component
@ -172,7 +176,7 @@ as QColor returns a hue of -1 if the color's hue is ambiguous (e.g., if the satu
:return: explicitly set hue for widget :return: explicitly set hue for widget
%End %End
void alterColor( QColor &color, QgsColorWidget::ColorComponent component, int newValue ) const; static void alterColor( QColor &color, QgsColorWidget::ColorComponent component, int newValue );
%Docstring %Docstring
Alters a color by modifying the value of a specific color component Alters a color by modifying the value of a specific color component
@ -182,6 +186,16 @@ Alters a color by modifying the value of a specific color component
valid range for the color component. valid range for the color component.
%End %End
QColor::Spec colorSpec() const;
%Docstring
Returns color widget type of color, either RGB, HSV, CMYK, or Invalid if this component value is Multiple or Alpha
%End
static QColor::Spec colorSpec( QgsColorWidget::ColorComponent component );
%Docstring
Returns ``component`` type of color, either RGB, HSV, CMYK, or Invalid if ``component`` value is Multiple or Alpha
%End
static const QPixmap &transparentBackground(); static const QPixmap &transparentBackground();
%Docstring %Docstring
Generates a checkboard pattern pixmap for use as a background to transparent colors Generates a checkboard pattern pixmap for use as a background to transparent colors
@ -201,6 +215,7 @@ Generates a checkboard pattern pixmap for use as a background to transparent col
virtual void mouseReleaseEvent( QMouseEvent *e ); virtual void mouseReleaseEvent( QMouseEvent *e );
}; };

View File

@ -102,6 +102,14 @@ int QgsColorWidget::componentValue( const QgsColorWidget::ColorComponent compone
return mCurrentColor.value(); return mCurrentColor.value();
case QgsColorWidget::Alpha: case QgsColorWidget::Alpha:
return mCurrentColor.alpha(); return mCurrentColor.alpha();
case QgsColorWidget::Cyan:
return mCurrentColor.cyan();
case QgsColorWidget::Yellow:
return mCurrentColor.yellow();
case QgsColorWidget::Magenta:
return mCurrentColor.magenta();
case QgsColorWidget::Black:
return mCurrentColor.black();
default: default:
return -1; return -1;
} }
@ -112,7 +120,7 @@ int QgsColorWidget::componentRange() const
return componentRange( mComponent ); return componentRange( mComponent );
} }
int QgsColorWidget::componentRange( const QgsColorWidget::ColorComponent component ) const int QgsColorWidget::componentRange( const QgsColorWidget::ColorComponent component )
{ {
if ( component == QgsColorWidget::Multiple ) if ( component == QgsColorWidget::Multiple )
{ {
@ -144,42 +152,144 @@ int QgsColorWidget::hue() const
} }
} }
void QgsColorWidget::alterColor( QColor &color, const QgsColorWidget::ColorComponent component, const int newValue ) const void QgsColorWidget::alterColor( QColor &color, const QgsColorWidget::ColorComponent component, const int newValue )
{ {
int h, s, v, a;
color.getHsv( &h, &s, &v, &a );
//clip value to sensible range //clip value to sensible range
const int clippedValue = std::min( std::max( 0, newValue ), componentRange( component ) ); const int clippedValue = std::min( std::max( 0, newValue ), componentRange( component ) );
if ( colorSpec( component ) == QColor::Spec::Cmyk )
{
int c, m, y, k, a;
color.getCmyk( &c, &m, &y, &k, &a );
switch ( component )
{
case QgsColorWidget::Cyan:
if ( c == clippedValue )
{
return;
}
color.setCmyk( clippedValue, m, y, k, a );
break;
case QgsColorWidget::Magenta:
if ( m == clippedValue )
{
return;
}
color.setCmyk( c, clippedValue, y, k, a );
break;
case QgsColorWidget::Yellow:
if ( y == clippedValue )
{
return;
}
color.setCmyk( c, m, clippedValue, k, a );
break;
case QgsColorWidget::Black:
if ( k == clippedValue )
{
return;
}
color.setCmyk( c, m, y, clippedValue, a );
break;
default:
return;
}
}
else
{
int r, g, b, a;
color.getRgb( &r, &g, &b, &a );
int h, s, v;
color.getHsv( &h, &s, &v );
switch ( component )
{
case QgsColorWidget::Red:
if ( r == clippedValue )
{
return;
}
color.setRed( clippedValue );
break;
case QgsColorWidget::Green:
if ( g == clippedValue )
{
return;
}
color.setGreen( clippedValue );
break;
case QgsColorWidget::Blue:
if ( b == clippedValue )
{
return;
}
color.setBlue( clippedValue );
break;
case QgsColorWidget::Hue:
if ( h == clippedValue )
{
return;
}
color.setHsv( clippedValue, s, v, a );
break;
case QgsColorWidget::Saturation:
if ( s == clippedValue )
{
return;
}
color.setHsv( h, clippedValue, v, a );
break;
case QgsColorWidget::Value:
if ( v == clippedValue )
{
return;
}
color.setHsv( h, s, clippedValue, a );
break;
case QgsColorWidget::Alpha:
if ( a == clippedValue )
{
return;
}
color.setAlpha( clippedValue );
break;
default:
return;
}
}
}
QColor::Spec QgsColorWidget::colorSpec( QgsColorWidget::ColorComponent component )
{
switch ( component ) switch ( component )
{ {
case QgsColorWidget::Red: case Red:
color.setRed( clippedValue ); case Green:
return; case Blue:
case QgsColorWidget::Green: return QColor::Spec::Rgb;
color.setGreen( clippedValue );
return; case Hue:
case QgsColorWidget::Blue: case Saturation:
color.setBlue( clippedValue ); case Value:
return; return QColor::Spec::Hsv;
case QgsColorWidget::Hue:
color.setHsv( clippedValue, s, v, a ); case Cyan:
return; case Magenta:
case QgsColorWidget::Saturation: case Yellow:
color.setHsv( h, clippedValue, v, a ); case Black:
return; return QColor::Spec::Cmyk;
case QgsColorWidget::Value:
color.setHsv( h, s, clippedValue, a );
return;
case QgsColorWidget::Alpha:
color.setAlpha( clippedValue );
return;
default: default:
return; return QColor::Spec::Invalid;
} }
} }
QColor::Spec QgsColorWidget::colorSpec() const
{
return colorSpec( mComponent );
}
const QPixmap &QgsColorWidget::transparentBackground() const QPixmap &QgsColorWidget::transparentBackground()
{ {
static QPixmap sTranspBkgrd; static QPixmap sTranspBkgrd;
@ -269,72 +379,19 @@ void QgsColorWidget::setComponentValue( const int value )
return; return;
} }
//clip value to valid range
int valueClipped = std::min( value, componentRange() );
valueClipped = std::max( valueClipped, 0 );
int r, g, b, a;
mCurrentColor.getRgb( &r, &g, &b, &a );
int h, s, v;
mCurrentColor.getHsv( &h, &s, &v );
//overwrite hue with explicit hue if required //overwrite hue with explicit hue if required
h = hue(); if ( mComponent == QgsColorWidget::Saturation || mComponent == QgsColorWidget::Value )
switch ( mComponent )
{ {
case QgsColorWidget::Red: int h, s, v, a;
if ( r == valueClipped ) mCurrentColor.getHsv( &h, &s, &v, &a );
{
return; h = hue();
}
mCurrentColor.setRed( valueClipped ); mCurrentColor.setHsv( h, s, v, a );
break;
case QgsColorWidget::Green:
if ( g == valueClipped )
{
return;
}
mCurrentColor.setGreen( valueClipped );
break;
case QgsColorWidget::Blue:
if ( b == valueClipped )
{
return;
}
mCurrentColor.setBlue( valueClipped );
break;
case QgsColorWidget::Hue:
if ( h == valueClipped )
{
return;
}
mCurrentColor.setHsv( valueClipped, s, v, a );
break;
case QgsColorWidget::Saturation:
if ( s == valueClipped )
{
return;
}
mCurrentColor.setHsv( h, valueClipped, v, a );
break;
case QgsColorWidget::Value:
if ( v == valueClipped )
{
return;
}
mCurrentColor.setHsv( h, s, valueClipped, a );
break;
case QgsColorWidget::Alpha:
if ( a == valueClipped )
{
return;
}
mCurrentColor.setAlpha( valueClipped );
break;
default:
return;
} }
alterColor( mCurrentColor, mComponent, value );
//update recorded hue //update recorded hue
if ( mCurrentColor.hue() >= 0 ) if ( mCurrentColor.hue() >= 0 )
{ {
@ -839,30 +896,19 @@ void QgsColorBox::setComponent( const QgsColorWidget::ColorComponent component )
void QgsColorBox::setColor( const QColor &color, const bool emitSignals ) void QgsColorBox::setColor( const QColor &color, const bool emitSignals )
{ {
//check if we need to redraw the box image //check if we need to redraw the box image
if ( mComponent == QgsColorWidget::Red && mCurrentColor.red() != color.red() ) mDirty |= (
{ ( mComponent == QgsColorWidget::Red && mCurrentColor.red() != color.red() ) ||
mDirty = true; ( mComponent == QgsColorWidget::Green && mCurrentColor.green() != color.green() ) ||
} ( mComponent == QgsColorWidget::Blue && mCurrentColor.blue() != color.blue() ) ||
else if ( mComponent == QgsColorWidget::Green && mCurrentColor.green() != color.green() ) ( mComponent == QgsColorWidget::Hue && color.hsvHue() >= 0 && hue() != color.hsvHue() ) ||
{ ( mComponent == QgsColorWidget::Saturation && mCurrentColor.hsvSaturation() != color.hsvSaturation() ) ||
mDirty = true; ( mComponent == QgsColorWidget::Value && mCurrentColor.value() != color.value() ) ||
} ( mComponent == QgsColorWidget::Cyan && mCurrentColor.cyan() != color.cyan() ) ||
else if ( mComponent == QgsColorWidget::Blue && mCurrentColor.blue() != color.blue() ) ( mComponent == QgsColorWidget::Magenta && mCurrentColor.magenta() != color.magenta() ) ||
{ ( mComponent == QgsColorWidget::Yellow && mCurrentColor.yellow() != color.yellow() ) ||
mDirty = true; ( mComponent == QgsColorWidget::Black && mCurrentColor.black() != color.black() )
} );
else if ( mComponent == QgsColorWidget::Hue && color.hsvHue() >= 0 && hue() != color.hsvHue() )
{
mDirty = true;
}
else if ( mComponent == QgsColorWidget::Saturation && mCurrentColor.hsvSaturation() != color.hsvSaturation() )
{
mDirty = true;
}
else if ( mComponent == QgsColorWidget::Value && mCurrentColor.value() != color.value() )
{
mDirty = true;
}
QgsColorWidget::setColor( color, emitSignals ); QgsColorWidget::setColor( color, emitSignals );
} }
@ -949,14 +995,22 @@ QgsColorWidget::ColorComponent QgsColorBox::yComponent() const
{ {
case QgsColorWidget::Red: case QgsColorWidget::Red:
return QgsColorWidget::Green; return QgsColorWidget::Green;
case QgsColorWidget:: Green: case QgsColorWidget::Green:
case QgsColorWidget:: Blue: case QgsColorWidget::Blue:
return QgsColorWidget::Red; return QgsColorWidget::Red;
case QgsColorWidget::Hue: case QgsColorWidget::Hue:
return QgsColorWidget:: Saturation; return QgsColorWidget::Saturation;
case QgsColorWidget:: Saturation: case QgsColorWidget::Saturation:
case QgsColorWidget:: Value: case QgsColorWidget::Value:
return QgsColorWidget::Hue; return QgsColorWidget::Hue;
case QgsColorWidget::Magenta:
return QgsColorWidget::Yellow;
case QgsColorWidget::Yellow:
case QgsColorWidget::Cyan:
return QgsColorWidget::Magenta;
default: default:
//should not occur //should not occur
return QgsColorWidget::Red; return QgsColorWidget::Red;
@ -972,16 +1026,24 @@ QgsColorWidget::ColorComponent QgsColorBox::xComponent() const
{ {
switch ( mComponent ) switch ( mComponent )
{ {
case QgsColorWidget::Red: case QgsColorWidget::Red:
case QgsColorWidget:: Green: case QgsColorWidget::Green:
return QgsColorWidget::Blue; return QgsColorWidget::Blue;
case QgsColorWidget:: Blue: case QgsColorWidget::Blue:
return QgsColorWidget::Green; return QgsColorWidget::Green;
case QgsColorWidget::Hue: case QgsColorWidget::Hue:
case QgsColorWidget:: Saturation: case QgsColorWidget::Saturation:
return QgsColorWidget:: Value; return QgsColorWidget::Value;
case QgsColorWidget:: Value: case QgsColorWidget::Value:
return QgsColorWidget::Saturation; return QgsColorWidget::Saturation;
case QgsColorWidget::Magenta:
case QgsColorWidget::Yellow:
return QgsColorWidget::Cyan;
case QgsColorWidget::Cyan:
return QgsColorWidget::Yellow;
default: default:
//should not occur //should not occur
return QgsColorWidget::Red; return QgsColorWidget::Red;

View File

@ -53,7 +53,11 @@ class GUI_EXPORT QgsColorWidget : public QWidget
Hue, //!< Hue component of color (based on HSV model) Hue, //!< Hue component of color (based on HSV model)
Saturation, //!< Saturation component of color (based on HSV model) Saturation, //!< Saturation component of color (based on HSV model)
Value, //!< Value component of color (based on HSV model) Value, //!< Value component of color (based on HSV model)
Alpha //!< Alpha component (opacity) of color Alpha, //!< Alpha component (opacity) of color
Cyan, //!< Cyan component (based on CMYK model) of color
Magenta, //!< Magenta component (based on CMYK model) of color
Yellow, //!< Yellow component (based on CMYK model) of color
Black //!< Black component (based on CMYK model) of color
}; };
/** /**
@ -155,7 +159,7 @@ class GUI_EXPORT QgsColorWidget : public QWidget
* Returns the range of valid values a color component * Returns the range of valid values a color component
* \returns maximum value allowed for color component * \returns maximum value allowed for color component
*/ */
int componentRange( ColorComponent component ) const; static int componentRange( ColorComponent component );
/** /**
* Returns the value of a component of the widget's current color. This method correctly * Returns the value of a component of the widget's current color. This method correctly
@ -180,7 +184,17 @@ class GUI_EXPORT QgsColorWidget : public QWidget
* \param newValue new value of color component. Values are automatically clipped to a * \param newValue new value of color component. Values are automatically clipped to a
* valid range for the color component. * valid range for the color component.
*/ */
void alterColor( QColor &color, QgsColorWidget::ColorComponent component, int newValue ) const; static void alterColor( QColor &color, QgsColorWidget::ColorComponent component, int newValue );
/**
* Returns color widget type of color, either RGB, HSV, CMYK, or Invalid if this component value is Multiple or Alpha
*/
QColor::Spec colorSpec() const;
/**
* Returns \a component type of color, either RGB, HSV, CMYK, or Invalid if \a component value is Multiple or Alpha
*/
static QColor::Spec colorSpec( QgsColorWidget::ColorComponent component );
/** /**
* Generates a checkboard pattern pixmap for use as a background to transparent colors * Generates a checkboard pattern pixmap for use as a background to transparent colors
@ -197,6 +211,8 @@ class GUI_EXPORT QgsColorWidget : public QWidget
void mouseMoveEvent( QMouseEvent *e ) override; void mouseMoveEvent( QMouseEvent *e ) override;
void mousePressEvent( QMouseEvent *e ) override; void mousePressEvent( QMouseEvent *e ) override;
void mouseReleaseEvent( QMouseEvent *e ) override; void mouseReleaseEvent( QMouseEvent *e ) override;
friend class TestQgsCompoundColorWidget;
}; };

View File

@ -22,6 +22,7 @@
#include "qgsscreenhelper.h" #include "qgsscreenhelper.h"
#include "qgsguiutils.h" #include "qgsguiutils.h"
#include <QButtonGroup>
#include <QHeaderView> #include <QHeaderView>
#include <QPushButton> #include <QPushButton>
#include <QMenu> #include <QMenu>
@ -41,18 +42,55 @@ QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor &c
mScreenHelper = new QgsScreenHelper( this ); mScreenHelper = new QgsScreenHelper( this );
connect( mHueRadio, &QRadioButton::toggled, this, &QgsCompoundColorWidget::mHueRadio_toggled ); mRgbRadios =
connect( mSaturationRadio, &QRadioButton::toggled, this, &QgsCompoundColorWidget::mSaturationRadio_toggled ); {
connect( mValueRadio, &QRadioButton::toggled, this, &QgsCompoundColorWidget::mValueRadio_toggled ); { mHueRadio, QgsColorWidget::ColorComponent::Hue },
connect( mRedRadio, &QRadioButton::toggled, this, &QgsCompoundColorWidget::mRedRadio_toggled ); { mSaturationRadio, QgsColorWidget::ColorComponent::Saturation },
connect( mGreenRadio, &QRadioButton::toggled, this, &QgsCompoundColorWidget::mGreenRadio_toggled ); { mValueRadio, QgsColorWidget::ColorComponent::Value },
connect( mBlueRadio, &QRadioButton::toggled, this, &QgsCompoundColorWidget::mBlueRadio_toggled ); { mRedRadio, QgsColorWidget::ColorComponent::Red },
{ mGreenRadio, QgsColorWidget::ColorComponent::Green },
{ mBlueRadio, QgsColorWidget::ColorComponent::Blue }
};
mCmykRadios =
{
{ mCyanRadio, QgsColorWidget::ColorComponent::Cyan },
{ mMagentaRadio, QgsColorWidget::ColorComponent::Magenta },
{ mYellowRadio, QgsColorWidget::ColorComponent::Yellow },
{ mBlackRadio, QgsColorWidget::ColorComponent::Black }
};
mRgbGroup = new QButtonGroup( this );
int i = 0;
for ( auto colorRadio : mRgbRadios )
mRgbGroup->addButton( colorRadio.first, i++ );
mCmykGroup = new QButtonGroup( this );
i = 0;
for ( auto colorRadio : mCmykRadios )
mCmykGroup->addButton( colorRadio.first, i++ );
connect( mRgbGroup, &QButtonGroup::idToggled, this, &QgsCompoundColorWidget::onColorButtonGroupToggled );
connect( mCmykGroup, &QButtonGroup::idToggled, this, &QgsCompoundColorWidget::onColorButtonGroupToggled );
connect( mAddColorToSchemeButton, &QPushButton::clicked, this, &QgsCompoundColorWidget::mAddColorToSchemeButton_clicked ); connect( mAddColorToSchemeButton, &QPushButton::clicked, this, &QgsCompoundColorWidget::mAddColorToSchemeButton_clicked );
connect( mAddCustomColorButton, &QPushButton::clicked, this, &QgsCompoundColorWidget::mAddCustomColorButton_clicked ); connect( mAddCustomColorButton, &QPushButton::clicked, this, &QgsCompoundColorWidget::mAddCustomColorButton_clicked );
connect( mSampleButton, &QPushButton::clicked, this, &QgsCompoundColorWidget::mSampleButton_clicked ); connect( mSampleButton, &QPushButton::clicked, this, &QgsCompoundColorWidget::mSampleButton_clicked );
connect( mTabWidget, &QTabWidget::currentChanged, this, &QgsCompoundColorWidget::mTabWidget_currentChanged ); connect( mTabWidget, &QTabWidget::currentChanged, this, &QgsCompoundColorWidget::mTabWidget_currentChanged );
connect( mActionShowInButtons, &QAction::toggled, this, &QgsCompoundColorWidget::mActionShowInButtons_toggled ); connect( mActionShowInButtons, &QAction::toggled, this, &QgsCompoundColorWidget::mActionShowInButtons_toggled );
mColorModel->addItem( tr( "RGB" ), QColor::Spec::Rgb );
mColorModel->addItem( tr( "CMYK" ), QColor::Spec::Cmyk );
connect( mColorModel, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this]( int )
{
const QColor::Spec spec = static_cast< QColor::Spec >( mColorModel->currentData().toInt() );
if ( spec == QColor::Spec::Cmyk )
setColor( this->color().toCmyk() );
else
setColor( this->color().toRgb() );
updateComponent();
} );
if ( widgetLayout == LayoutVertical ) if ( widgetLayout == LayoutVertical )
{ {
// shuffle stuff around // shuffle stuff around
@ -112,7 +150,7 @@ QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor &c
mSchemeToolButton->setMenu( schemeMenu ); mSchemeToolButton->setMenu( schemeMenu );
connect( mSchemeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsCompoundColorWidget::schemeIndexChanged ); connect( mSchemeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsCompoundColorWidget::schemeIndexChanged );
connect( mSchemeList, &QgsColorSchemeList::colorSelected, this, &QgsCompoundColorWidget::setColor ); connect( mSchemeList, &QgsColorSchemeList::colorSelected, this, &QgsCompoundColorWidget::_setColor );
mOldColorLabel->hide(); mOldColorLabel->hide();
@ -127,6 +165,10 @@ QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor &c
mSaturationSlider->setComponent( QgsColorWidget::Saturation ); mSaturationSlider->setComponent( QgsColorWidget::Saturation );
mValueSlider->setComponent( QgsColorWidget::Value ); mValueSlider->setComponent( QgsColorWidget::Value );
mAlphaSlider->setComponent( QgsColorWidget::Alpha ); mAlphaSlider->setComponent( QgsColorWidget::Alpha );
mCyanSlider->setComponent( QgsColorWidget::Cyan );
mMagentaSlider->setComponent( QgsColorWidget::Magenta );
mYellowSlider->setComponent( QgsColorWidget::Yellow );
mBlackSlider->setComponent( QgsColorWidget::Black );
mSwatchButton1->setShowMenu( false ); mSwatchButton1->setShowMenu( false );
mSwatchButton1->setBehavior( QgsColorButton::SignalOnly ); mSwatchButton1->setBehavior( QgsColorButton::SignalOnly );
@ -232,61 +274,51 @@ QgsCompoundColorWidget::QgsCompoundColorWidget( QWidget *parent, const QColor &c
setColor( color ); setColor( color );
} }
//restore active component radio button // restore active Rgb/Cmyk component radio button
const int activeRadio = settings.value( QStringLiteral( "Windows/ColorDialog/activeComponent" ), 2 ).toInt(); const int activeRgbRadio = settings.value( QStringLiteral( "Windows/ColorDialog/activeComponent" ), 2 ).toInt();
switch ( activeRadio ) if ( QAbstractButton *rgbRadio = mRgbGroup->button( activeRgbRadio ) )
{ rgbRadio->setChecked( true );
case 0:
mHueRadio->setChecked( true ); const int activeCmykRadio = settings.value( QStringLiteral( "Windows/ColorDialog/activeCmykComponent" ), 0 ).toInt();
break; if ( QAbstractButton *cmykRadio = mCmykGroup->button( activeCmykRadio ) )
case 1: cmykRadio->setChecked( true );
mSaturationRadio->setChecked( true );
break;
case 2:
mValueRadio->setChecked( true );
break;
case 3:
mRedRadio->setChecked( true );
break;
case 4:
mGreenRadio->setChecked( true );
break;
case 5:
mBlueRadio->setChecked( true );
break;
}
const int currentTab = settings.value( QStringLiteral( "Windows/ColorDialog/activeTab" ), 0 ).toInt(); const int currentTab = settings.value( QStringLiteral( "Windows/ColorDialog/activeTab" ), 0 ).toInt();
mTabWidget->setCurrentIndex( currentTab ); mTabWidget->setCurrentIndex( currentTab );
//setup connections //setup connections
connect( mColorBox, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mColorBox, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mColorWheel, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mColorWheel, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mColorText, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mColorText, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mVerticalRamp, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mVerticalRamp, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mRedSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mRedSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mGreenSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mGreenSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mBlueSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mBlueSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mHueSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mHueSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mValueSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mValueSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mSaturationSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mCyanSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mAlphaSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mMagentaSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mColorPreview, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::setColor ); connect( mYellowSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton1, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mBlackSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton2, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSaturationSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton3, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mAlphaSlider, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton4, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mColorPreview, &QgsColorWidget::colorChanged, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton5, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton1, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton6, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton2, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton7, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton3, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton8, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton4, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton9, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton5, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton10, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton6, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton11, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton7, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton12, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton8, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton13, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton9, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton14, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton10, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton15, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton11, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton16, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::setColor ); connect( mSwatchButton12, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton13, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton14, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton15, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
connect( mSwatchButton16, &QgsColorButton::colorClicked, this, &QgsCompoundColorWidget::_setColor );
} }
QgsCompoundColorWidget::~QgsCompoundColorWidget() QgsCompoundColorWidget::~QgsCompoundColorWidget()
@ -601,12 +633,9 @@ void QgsCompoundColorWidget::mTabWidget_currentChanged( int index )
{ {
//disable radio buttons if not using the first tab, as they have no meaning for other tabs //disable radio buttons if not using the first tab, as they have no meaning for other tabs
const bool enabled = index == 0; const bool enabled = index == 0;
mRedRadio->setEnabled( enabled ); const QList<QRadioButton *> colorRadios{ mHueRadio, mSaturationRadio, mValueRadio, mRedRadio, mGreenRadio, mBlueRadio, mCyanRadio, mMagentaRadio, mYellowRadio, mBlackRadio };
mBlueRadio->setEnabled( enabled ); for ( QRadioButton *colorRadio : colorRadios )
mGreenRadio->setEnabled( enabled ); colorRadio->setEnabled( enabled );
mHueRadio->setEnabled( enabled );
mSaturationRadio->setEnabled( enabled );
mValueRadio->setEnabled( enabled );
} }
void QgsCompoundColorWidget::mActionShowInButtons_toggled( bool state ) void QgsCompoundColorWidget::mActionShowInButtons_toggled( bool state )
@ -641,21 +670,9 @@ void QgsCompoundColorWidget::saveSettings()
QgsSettings settings; QgsSettings settings;
//record active component // record active component
int activeRadio = 0; settings.setValue( QStringLiteral( "Windows/ColorDialog/activeComponent" ), mRgbGroup->checkedId() );
if ( mHueRadio->isChecked() ) settings.setValue( QStringLiteral( "Windows/ColorDialog/activeCmykComponent" ), mCmykGroup->checkedId() );
activeRadio = 0;
if ( mSaturationRadio->isChecked() )
activeRadio = 1;
if ( mValueRadio->isChecked() )
activeRadio = 2;
if ( mRedRadio->isChecked() )
activeRadio = 3;
if ( mGreenRadio->isChecked() )
activeRadio = 4;
if ( mBlueRadio->isChecked() )
activeRadio = 5;
settings.setValue( QStringLiteral( "Windows/ColorDialog/activeComponent" ), activeRadio );
//record current scheme //record current scheme
settings.setValue( QStringLiteral( "Windows/ColorDialog/activeScheme" ), mSchemeComboBox->currentIndex() ); settings.setValue( QStringLiteral( "Windows/ColorDialog/activeScheme" ), mSchemeComboBox->currentIndex() );
@ -707,6 +724,15 @@ void QgsCompoundColorWidget::stopPicking( QPoint eventPos, const bool takeSample
} }
void QgsCompoundColorWidget::setColor( const QColor &color ) void QgsCompoundColorWidget::setColor( const QColor &color )
{
const QColor::Spec colorSpec = color.spec() == QColor::Cmyk ? QColor::Cmyk : QColor::Rgb;
mColorModel->setCurrentIndex( mColorModel->findData( colorSpec ) );
mRGB->setVisible( color.spec() != QColor::Cmyk );
mCMYK->setVisible( color.spec() == QColor::Cmyk );
_setColor( color );
}
void QgsCompoundColorWidget::_setColor( const QColor &color )
{ {
if ( !color.isValid() ) if ( !color.isValid() )
{ {
@ -719,6 +745,12 @@ void QgsCompoundColorWidget::setColor( const QColor &color )
//opacity disallowed, so don't permit transparent colors //opacity disallowed, so don't permit transparent colors
fixedColor.setAlpha( 255 ); fixedColor.setAlpha( 255 );
} }
if ( mColorModel->currentIndex() && fixedColor.spec() != QColor::Cmyk )
{
fixedColor = fixedColor.toCmyk();
}
const QList<QgsColorWidget *> colorWidgets = this->findChildren<QgsColorWidget *>(); const QList<QgsColorWidget *> colorWidgets = this->findChildren<QgsColorWidget *>();
const auto constColorWidgets = colorWidgets; const auto constColorWidgets = colorWidgets;
for ( QgsColorWidget *widget : constColorWidgets ) for ( QgsColorWidget *widget : constColorWidgets )
@ -731,6 +763,8 @@ void QgsCompoundColorWidget::setColor( const QColor &color )
widget->setColor( fixedColor ); widget->setColor( fixedColor );
widget->blockSignals( false ); widget->blockSignals( false );
} }
emit currentColorChanged( fixedColor ); emit currentColorChanged( fixedColor );
} }
@ -850,58 +884,26 @@ void QgsCompoundColorWidget::keyPressEvent( QKeyEvent *e )
stopPicking( QCursor::pos(), e->key() == Qt::Key_Space ); stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
} }
void QgsCompoundColorWidget::mHueRadio_toggled( bool checked )
void QgsCompoundColorWidget::updateComponent()
{ {
if ( checked ) const bool isCmyk = mColorModel->currentData().toInt() == QColor::Spec::Cmyk;
const auto radios = isCmyk ? mCmykRadios : mRgbRadios;
const QButtonGroup *group = isCmyk ? mCmykGroup : mRgbGroup;
const int id = group->checkedId();
if ( id >= 0 && id < radios.count() )
{ {
mColorBox->setComponent( QgsColorWidget::Hue ); const QgsColorWidget::ColorComponent component = radios.at( group->checkedId() ).second;
mVerticalRamp->setComponent( QgsColorWidget::Hue ); mColorBox->setComponent( component );
mVerticalRamp->setComponent( component );
} }
} }
void QgsCompoundColorWidget::mSaturationRadio_toggled( bool checked ) void QgsCompoundColorWidget::onColorButtonGroupToggled( int, bool checked )
{ {
if ( checked ) if ( checked )
{ updateComponent();
mColorBox->setComponent( QgsColorWidget::Saturation );
mVerticalRamp->setComponent( QgsColorWidget::Saturation );
}
}
void QgsCompoundColorWidget::mValueRadio_toggled( bool checked )
{
if ( checked )
{
mColorBox->setComponent( QgsColorWidget::Value );
mVerticalRamp->setComponent( QgsColorWidget::Value );
}
}
void QgsCompoundColorWidget::mRedRadio_toggled( bool checked )
{
if ( checked )
{
mColorBox->setComponent( QgsColorWidget::Red );
mVerticalRamp->setComponent( QgsColorWidget::Red );
}
}
void QgsCompoundColorWidget::mGreenRadio_toggled( bool checked )
{
if ( checked )
{
mColorBox->setComponent( QgsColorWidget::Green );
mVerticalRamp->setComponent( QgsColorWidget::Green );
}
}
void QgsCompoundColorWidget::mBlueRadio_toggled( bool checked )
{
if ( checked )
{
mColorBox->setComponent( QgsColorWidget::Blue );
mVerticalRamp->setComponent( QgsColorWidget::Blue );
}
} }
void QgsCompoundColorWidget::mAddColorToSchemeButton_clicked() void QgsCompoundColorWidget::mAddColorToSchemeButton_clicked()

View File

@ -146,12 +146,7 @@ class GUI_EXPORT QgsCompoundColorWidget : public QgsPanelWidget, private Ui::Qgs
private slots: private slots:
void mHueRadio_toggled( bool checked ); void onColorButtonGroupToggled( int, bool checked );
void mSaturationRadio_toggled( bool checked );
void mValueRadio_toggled( bool checked );
void mRedRadio_toggled( bool checked );
void mGreenRadio_toggled( bool checked );
void mBlueRadio_toggled( bool checked );
void mAddColorToSchemeButton_clicked(); void mAddColorToSchemeButton_clicked();
@ -167,14 +162,24 @@ class GUI_EXPORT QgsCompoundColorWidget : public QgsPanelWidget, private Ui::Qgs
void mSampleButton_clicked(); void mSampleButton_clicked();
void mTabWidget_currentChanged( int index ); void mTabWidget_currentChanged( int index );
private slots:
void mActionShowInButtons_toggled( bool state ); void mActionShowInButtons_toggled( bool state );
/**
* Internal color setter. Set \a color without changing current color model (RGB or CMYK),
* contrary to public setColor()
*/
void _setColor( const QColor &color );
private: private:
static QScreen *findScreenAt( QPoint pos ); static QScreen *findScreenAt( QPoint pos );
/**
* Helper method to update current widget display with current component according to
* color model and selected color component radio button
*/
void updateComponent();
QgsScreenHelper *mScreenHelper = nullptr; QgsScreenHelper *mScreenHelper = nullptr;
bool mAllowAlpha = true; bool mAllowAlpha = true;
@ -185,6 +190,11 @@ class GUI_EXPORT QgsCompoundColorWidget : public QgsPanelWidget, private Ui::Qgs
bool mDiscarded = false; bool mDiscarded = false;
QList<QPair<QRadioButton *, QgsColorWidget::ColorComponent>> mRgbRadios;
QList<QPair<QRadioButton *, QgsColorWidget::ColorComponent>> mCmykRadios;
QButtonGroup *mCmykGroup = nullptr;
QButtonGroup *mRgbGroup = nullptr;
/** /**
* Saves all widget settings * Saves all widget settings
*/ */
@ -224,6 +234,8 @@ class GUI_EXPORT QgsCompoundColorWidget : public QgsPanelWidget, private Ui::Qgs
//! Updates the state of actions for the current selected scheme //! Updates the state of actions for the current selected scheme
void updateActionsForCurrentScheme(); void updateActionsForCurrentScheme();
friend class TestQgsCompoundColorWidget;
}; };
#endif // QGSCOMPOUNDCOLORWIDGET_H #endif // QGSCOMPOUNDCOLORWIDGET_H

File diff suppressed because it is too large Load Diff

View File

@ -74,6 +74,7 @@ set(TESTS
testqgsexternalresourcewidgetwrapper.cpp testqgsexternalresourcewidgetwrapper.cpp
testqgsquerybuilder.cpp testqgsquerybuilder.cpp
testqgsqueryresultwidget.cpp testqgsqueryresultwidget.cpp
testqgscompoundcolorwidget.cpp
) )
foreach(TESTSRC ${TESTS}) foreach(TESTSRC ${TESTS})

View File

@ -0,0 +1,229 @@
/***************************************************************************
testqgscompoundcolorwidget.cpp
---------------------
begin : 2024/05/07
copyright : (C) 2024 by Julien Cabieces
email : julien dot cabieces at oslandia dot 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. *
* *
***************************************************************************/
#include "qgstest.h"
#include "qgscompoundcolorwidget.h"
#include "qgssettings.h"
Q_DECLARE_METATYPE( QgsColorWidget::ColorComponent )
class TestQgsCompoundColorWidget : public QgsTest
{
Q_OBJECT
public:
TestQgsCompoundColorWidget() : QgsTest( QStringLiteral( "Compound color widget Tests" ) ) {}
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void testCmykConversion();
void testComponentChange();
void testComponentSettings_data();
void testComponentSettings();
void testModelChange();
void testTabChange();
};
void TestQgsCompoundColorWidget::initTestCase()
{
// Set up the QgsSettings environment
QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );
}
void TestQgsCompoundColorWidget::cleanupTestCase()
{
}
void TestQgsCompoundColorWidget::init()
{
}
void TestQgsCompoundColorWidget::cleanup()
{
}
void TestQgsCompoundColorWidget::testCmykConversion()
{
QgsCompoundColorWidget w( nullptr, QColor( 10, 20, 30, 50 ) );
w.setVisible( true );
QCOMPARE( w.color(), QColor( 10, 20, 30, 50 ) );
QCOMPARE( w.mColorModel->currentIndex(), 0 );
QVERIFY( w.mRGB->isVisible() );
QVERIFY( !w.mCMYK->isVisible() );
// switch to CMYK
w.mColorModel->setCurrentIndex( 1 );
QVERIFY( !w.mRGB->isVisible() );
QVERIFY( w.mCMYK->isVisible() );
QCOMPARE( w.mColorModel->currentIndex(), 1 );
QCOMPARE( w.color(), QColor::fromCmyk( 170, 85, 0, 225, 50 ) );
// switch back to RGB
w.mColorModel->setCurrentIndex( 0 );
QVERIFY( w.mRGB->isVisible() );
QVERIFY( !w.mCMYK->isVisible() );
QCOMPARE( w.mColorModel->currentIndex(), 0 );
QCOMPARE( w.color(), QColor( 10, 20, 30, 50 ) );
// edit color in CMYK mode
w.mColorModel->setCurrentIndex( 1 );
QVERIFY( !w.mRGB->isVisible() );
QVERIFY( w.mCMYK->isVisible() );
QCOMPARE( w.mColorModel->currentIndex(), 1 );
QCOMPARE( w.color(), QColor::fromCmyk( 170, 85, 0, 225, 50 ) );
w.mCyanSlider->setColor( QColor::fromCmyk( 120, 85, 0, 225, 50 ), true );
QCOMPARE( w.color(), QColor::fromCmyk( 120, 85, 0, 225, 50 ) );
// edit color in RGB, the returned color is still CMYK
w.mColorWheel->setColor( QColor( 10, 20, 30, 50 ), true );
QCOMPARE( w.color(), QColor::fromCmyk( 170, 85, 0, 225, 50 ) );
}
void TestQgsCompoundColorWidget::testComponentSettings_data()
{
QTest::addColumn<int>( "settingsComponent" );
QTest::addColumn<QgsColorWidget::ColorComponent>( "expectedComponent" );
QTest::addColumn<QgsColorWidget::ColorComponent>( "newComponent" );
QTest::addColumn<int>( "newSettingsComponent" );
QTest::newRow( "hue" ) << 0 << QgsColorWidget::ColorComponent::Hue << QgsColorWidget::ColorComponent::Saturation << 1;
QTest::newRow( "saturation" ) << 1 << QgsColorWidget::ColorComponent::Saturation << QgsColorWidget::ColorComponent::Value << 2;
QTest::newRow( "value" ) << 2 << QgsColorWidget::ColorComponent::Value << QgsColorWidget::ColorComponent::Red << 3;
QTest::newRow( "red" ) << 3 << QgsColorWidget::ColorComponent::Red << QgsColorWidget::ColorComponent::Green << 4;
QTest::newRow( "green" ) << 4 << QgsColorWidget::ColorComponent::Green << QgsColorWidget::ColorComponent::Blue << 5;
QTest::newRow( "blue" ) << 5 << QgsColorWidget::ColorComponent::Blue << QgsColorWidget::ColorComponent::Hue << 0;
QTest::newRow( "cyan" ) << 0 << QgsColorWidget::ColorComponent::Cyan << QgsColorWidget::ColorComponent::Magenta << 1;
QTest::newRow( "magenta" ) << 1 << QgsColorWidget::ColorComponent::Magenta << QgsColorWidget::ColorComponent::Yellow << 2;
QTest::newRow( "yellow" ) << 2 << QgsColorWidget::ColorComponent::Yellow << QgsColorWidget::ColorComponent::Black << 3;
QTest::newRow( "black" ) << 3 << QgsColorWidget::ColorComponent::Black << QgsColorWidget::ColorComponent::Cyan << 0;
}
void TestQgsCompoundColorWidget::testComponentSettings()
{
QFETCH( int, settingsComponent );
QFETCH( QgsColorWidget::ColorComponent, expectedComponent );
QFETCH( QgsColorWidget::ColorComponent, newComponent );
QFETCH( int, newSettingsComponent );
QgsSettings().setValue( QgsColorWidget::colorSpec( expectedComponent ) == QColor::Cmyk ?
QStringLiteral( "Windows/ColorDialog/activeCmykComponent" ) : QStringLiteral( "Windows/ColorDialog/activeComponent" ), settingsComponent );
QgsCompoundColorWidget w( nullptr, QgsColorWidget::colorSpec( expectedComponent ) == QColor::Cmyk ?
QColor::fromCmyk( 1, 2, 3, 4 ) : QColor( 10, 20, 30, 50 ) );
w.setVisible( true );
QCOMPARE( w.mColorBox->component(), expectedComponent );
QCOMPARE( w.mVerticalRamp->component(), expectedComponent );
( QgsColorWidget::colorSpec( expectedComponent ) == QColor::Cmyk ? w.mCmykRadios : w.mRgbRadios ).at( newSettingsComponent ).first->setChecked( true );
QCOMPARE( w.mColorBox->component(), newComponent );
QCOMPARE( w.mVerticalRamp->component(), newComponent );
w.saveSettings();
const int newValue = QgsSettings().value( QgsColorWidget::colorSpec( expectedComponent ) == QColor::Cmyk ?
QStringLiteral( "Windows/ColorDialog/activeCmykComponent" ) : QStringLiteral( "Windows/ColorDialog/activeComponent" ), -1 ).toInt();
QCOMPARE( newValue, newSettingsComponent );
}
void TestQgsCompoundColorWidget::testComponentChange()
{
QgsSettings().setValue( QStringLiteral( "Windows/ColorDialog/activeComponent" ), 3 );
QgsCompoundColorWidget w( nullptr, QColor( 10, 20, 30, 50 ) );
w.setVisible( true );
QCOMPARE( w.mColorBox->component(), QgsColorWidget::Red );
QCOMPARE( w.mVerticalRamp->component(), QgsColorWidget::Red );
const QList<QPair<QRadioButton *, QgsColorWidget::ColorComponent>> colors =
{
{ w.mHueRadio, QgsColorWidget::Hue },
{ w.mSaturationRadio, QgsColorWidget::Saturation },
{ w.mValueRadio, QgsColorWidget::Value },
{ w.mRedRadio, QgsColorWidget::Red },
{ w.mGreenRadio, QgsColorWidget::Green },
{ w.mBlueRadio, QgsColorWidget::Blue },
{ w.mCyanRadio, QgsColorWidget::Cyan },
{ w.mMagentaRadio, QgsColorWidget::Magenta },
{ w.mYellowRadio, QgsColorWidget::Yellow },
{ w.mBlackRadio, QgsColorWidget::Black }
};
for ( QPair<QRadioButton *, QgsColorWidget::ColorComponent> color : colors )
{
if ( QgsColorWidget::colorSpec( color.second ) != w.mColorModel->currentData() )
w.mColorModel->setCurrentIndex( w.mColorModel->findData( QgsColorWidget::colorSpec( color.second ) ) );
color.first->setChecked( true );
QCOMPARE( w.mColorBox->component(), color.second );
QCOMPARE( w.mVerticalRamp->component(), color.second );
}
}
void TestQgsCompoundColorWidget::testModelChange()
{
QgsCompoundColorWidget w( nullptr, QColor( 10, 20, 30, 50 ) );
w.setVisible( true );
QCOMPARE( w.mColorModel->currentData(), QColor::Rgb );
w.mColorModel->setCurrentIndex( w.mColorModel->findData( QColor::Cmyk ) );
QCOMPARE( w.mColorModel->currentData(), QColor::Cmyk );
w.setColor( QColor( 1, 2, 3 ) );
QCOMPARE( w.mColorModel->currentData(), QColor::Rgb );
}
void TestQgsCompoundColorWidget::testTabChange()
{
QgsCompoundColorWidget w( nullptr, QColor( 10, 20, 30, 50 ) );
w.setVisible( true );
QCOMPARE( w.mTabWidget->currentIndex(), 0 );
QVERIFY( w.mRedRadio->isEnabled() );
QVERIFY( w.mBlueRadio->isEnabled() );
QVERIFY( w.mGreenRadio->isEnabled() );
QVERIFY( w.mHueRadio->isEnabled() );
QVERIFY( w.mSaturationRadio->isEnabled() );
QVERIFY( w.mCyanRadio->isEnabled() );
QVERIFY( w.mMagentaRadio->isEnabled() );
QVERIFY( w.mYellowRadio->isEnabled() );
QVERIFY( w.mBlackRadio->isEnabled() );
w.mTabWidget->setCurrentIndex( 1 );
QVERIFY( !w.mRedRadio->isEnabled() );
QVERIFY( !w.mBlueRadio->isEnabled() );
QVERIFY( !w.mGreenRadio->isEnabled() );
QVERIFY( !w.mHueRadio->isEnabled() );
QVERIFY( !w.mSaturationRadio->isEnabled() );
QVERIFY( !w.mCyanRadio->isEnabled() );
QVERIFY( !w.mMagentaRadio->isEnabled() );
QVERIFY( !w.mYellowRadio->isEnabled() );
QVERIFY( !w.mBlackRadio->isEnabled() );
}
QGSTEST_MAIN( TestQgsCompoundColorWidget )
#include "testqgscompoundcolorwidget.moc"

View File

@ -0,0 +1,172 @@
"""QGIS Unit tests for QgsColorWidget
.. note:: 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.
"""
__author__ = 'Julien Cabieces'
__date__ = '02/05/2024'
__copyright__ = 'Copyright 2024, The QGIS Project'
from qgis.PyQt.QtGui import QColor
from qgis.gui import QgsColorWidget
import unittest
from qgis.testing import start_app, QgisTestCase
start_app()
class TestQgsColorWidget(QgisTestCase):
def testAlterColor(self):
"""
test alterColor method
"""
# rgb
color = QColor(12, 34, 56)
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Red, 112)
self.assertEqual(color, QColor(112, 34, 56, 255))
self.assertEqual(color.spec(), QColor.Spec.Rgb)
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Green, 134)
self.assertEqual(color.spec(), QColor.Spec.Rgb)
self.assertEqual(color, QColor(112, 134, 56, 255))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Blue, 156)
self.assertEqual(color.spec(), QColor.Spec.Rgb)
self.assertEqual(color, QColor(112, 134, 156, 255))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Alpha, 210)
self.assertEqual(color.spec(), QColor.Spec.Rgb)
self.assertEqual(color, QColor(112, 134, 156, 210))
# hsv
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Hue, 100)
self.assertEqual(color.spec(), QColor.Spec.Hsv)
self.assertEqual(color, QColor.fromHsv(100, 72, 156, 210))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Saturation, 150)
self.assertEqual(color.spec(), QColor.Spec.Hsv)
self.assertEqual(color, QColor.fromHsv(100, 150, 156, 210))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Value, 200)
self.assertEqual(color.spec(), QColor.Spec.Hsv)
self.assertEqual(color, QColor.fromHsv(100, 150, 200, 210))
# clipped value
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Value, 300)
self.assertEqual(color.spec(), QColor.Spec.Hsv)
self.assertEqual(color, QColor.fromHsv(100, 150, 255, 210))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Value, -2)
self.assertEqual(color.spec(), QColor.Spec.Hsv)
self.assertEqual(color, QColor.fromHsv(100, 150, 0, 210))
# cmyk
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Cyan, 22)
self.assertEqual(color.spec(), QColor.Spec.Cmyk)
self.assertEqual(color, QColor.fromCmyk(22, 0, 0, 255, 210))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Magenta, 33)
self.assertEqual(color.spec(), QColor.Spec.Cmyk)
self.assertEqual(color, QColor.fromCmyk(22, 33, 0, 255, 210))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Yellow, 44)
self.assertEqual(color.spec(), QColor.Spec.Cmyk)
self.assertEqual(color, QColor.fromCmyk(22, 33, 44, 255, 210))
QgsColorWidget.alterColor(color, QgsColorWidget.ColorComponent.Black, 55)
self.assertEqual(color.spec(), QColor.Spec.Cmyk)
self.assertEqual(color, QColor.fromCmyk(22, 33, 44, 55, 210))
def testSetComponentValue(self):
"""
test setComponentValue method
"""
w = QgsColorWidget()
w.setColor(QColor(12, 34, 56))
self.assertEqual(w.color(), QColor(12, 34, 56))
# rgb
w.setComponent(QgsColorWidget.ColorComponent.Red)
w.setComponentValue(112)
self.assertEqual(w.color(), QColor(112, 34, 56, 255))
self.assertEqual(w.color().spec(), QColor.Spec.Rgb)
w.setComponent(QgsColorWidget.ColorComponent.Green)
w.setComponentValue(134)
self.assertEqual(w.color().spec(), QColor.Spec.Rgb)
self.assertEqual(w.color(), QColor(112, 134, 56, 255))
w.setComponent(QgsColorWidget.ColorComponent.Blue)
w.setComponentValue(156)
self.assertEqual(w.color().spec(), QColor.Spec.Rgb)
self.assertEqual(w.color(), QColor(112, 134, 156, 255))
w.setComponent(QgsColorWidget.ColorComponent.Alpha)
w.setComponentValue(210)
self.assertEqual(w.color().spec(), QColor.Spec.Rgb)
self.assertEqual(w.color(), QColor(112, 134, 156, 210))
# hsv
w.setComponent(QgsColorWidget.ColorComponent.Hue)
w.setComponentValue(100)
self.assertEqual(w.color().spec(), QColor.Spec.Hsv)
self.assertEqual(w.color(), QColor.fromHsv(100, 72, 156, 210))
w.setComponent(QgsColorWidget.ColorComponent.Saturation)
w.setComponentValue(150)
self.assertEqual(w.color().spec(), QColor.Spec.Hsv)
self.assertEqual(w.color(), QColor.fromHsv(100, 150, 156, 210))
w.setComponent(QgsColorWidget.ColorComponent.Value)
w.setComponentValue(200)
self.assertEqual(w.color().spec(), QColor.Spec.Hsv)
self.assertEqual(w.color(), QColor.fromHsv(100, 150, 200, 210))
# clipped value
w.setComponent(QgsColorWidget.ColorComponent.Value)
w.setComponentValue(300)
self.assertEqual(w.color().spec(), QColor.Spec.Hsv)
self.assertEqual(w.color(), QColor.fromHsv(100, 150, 255, 210))
w.setComponent(QgsColorWidget.ColorComponent.Value)
w.setComponentValue(-2)
self.assertEqual(w.color().spec(), QColor.Spec.Hsv)
self.assertEqual(w.color(), QColor.fromHsv(100, 150, 0, 210))
# Multiple component has no effect
w.setComponent(QgsColorWidget.ColorComponent.Multiple)
w.setComponentValue(18)
self.assertEqual(w.color().spec(), QColor.Spec.Hsv)
self.assertEqual(w.color(), QColor.fromHsv(100, 150, 0, 210))
# set an achromatic color to check it keeps the hue
w.setColor(QColor(130, 130, 130, 255))
self.assertEqual(w.color().spec(), QColor.Spec.Rgb)
self.assertEqual(w.color(), QColor(130, 130, 130, 255))
w.setComponent(QgsColorWidget.ColorComponent.Value)
w.setComponentValue(42)
self.assertEqual(w.color(), QColor.fromHsv(100, 0, 42, 255))
self.assertEqual(w.componentValue(QgsColorWidget.ColorComponent.Hue), 100)
# cmyk
w.setComponent(QgsColorWidget.ColorComponent.Cyan)
w.setComponentValue(22)
self.assertEqual(w.color().spec(), QColor.Spec.Cmyk)
self.assertEqual(w.color(), QColor.fromCmyk(22, 0, 0, 213, 255))
w.setComponent(QgsColorWidget.ColorComponent.Magenta)
w.setComponentValue(33)
self.assertEqual(w.color().spec(), QColor.Spec.Cmyk)
self.assertEqual(w.color(), QColor.fromCmyk(22, 33, 0, 213, 255))
w.setComponent(QgsColorWidget.ColorComponent.Yellow)
w.setComponentValue(44)
self.assertEqual(w.color().spec(), QColor.Spec.Cmyk)
self.assertEqual(w.color(), QColor.fromCmyk(22, 33, 44, 213, 255))
w.setComponent(QgsColorWidget.ColorComponent.Black)
w.setComponentValue(55)
self.assertEqual(w.color().spec(), QColor.Spec.Cmyk)
self.assertEqual(w.color(), QColor.fromCmyk(22, 33, 44, 55, 255))
# set an achromatic color to check it keeps the hue (set from former cmyk values)
self.assertEqual(w.color().hue(), 30)
w.setColor(QColor(130, 130, 130, 255))
self.assertEqual(w.color().spec(), QColor.Spec.Rgb)
self.assertEqual(w.color(), QColor(130, 130, 130, 255))
w.setComponent(QgsColorWidget.ColorComponent.Value)
w.setComponentValue(42)
self.assertEqual(w.color(), QColor.fromHsv(30, 0, 42, 255))
self.assertEqual(w.componentValue(QgsColorWidget.ColorComponent.Hue), 30)
if __name__ == '__main__':
unittest.main()