Skip to content

Commit

Permalink
Merge pull request #58376 from troopa81/ui_cmyk_percent
Browse files Browse the repository at this point in the history
[ColorWidget] Edit CMYK as percent
  • Loading branch information
troopa81 authored Aug 22, 2024
2 parents 04dac19 + dac3d30 commit 0880614
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 46 deletions.
8 changes: 8 additions & 0 deletions python/PyQt6/gui/auto_additions/qgscolorwidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
QgsColorWidget.Magenta = QgsColorWidget.ColorComponent.Magenta
QgsColorWidget.Yellow = QgsColorWidget.ColorComponent.Yellow
QgsColorWidget.Black = QgsColorWidget.ColorComponent.Black
# monkey patching scoped based enum
QgsColorWidget.ComponentUnit.Scaled0to255.__doc__ = "Values in the range 0-255"
QgsColorWidget.ComponentUnit.Percent.__doc__ = "Percent values in the range 0-100"
QgsColorWidget.ComponentUnit.Degree.__doc__ = "Degree values in the range 0-359"
QgsColorWidget.ComponentUnit.__doc__ = "Specified the color component unit\n\n" + '* ``Scaled0to255``: ' + QgsColorWidget.ComponentUnit.Scaled0to255.__doc__ + '\n' + '* ``Percent``: ' + QgsColorWidget.ComponentUnit.Percent.__doc__ + '\n' + '* ``Degree``: ' + QgsColorWidget.ComponentUnit.Degree.__doc__
# --
QgsColorWidget.ComponentUnit.baseClass = QgsColorWidget
QgsColorRampWidget.Horizontal = QgsColorRampWidget.Orientation.Horizontal
QgsColorRampWidget.Vertical = QgsColorRampWidget.Orientation.Vertical
QgsColorTextWidget.HexRgb = QgsColorTextWidget.ColorTextFormat.HexRgb
Expand All @@ -31,5 +38,6 @@
except NameError:
pass
QgsColorWidget.createDragIcon = staticmethod(QgsColorWidget.createDragIcon)
QgsColorWidget.componentUnit = staticmethod(QgsColorWidget.componentUnit)
QgsColorWidget.alterColor = staticmethod(QgsColorWidget.alterColor)
QgsColorWidget.alterColorF = staticmethod(QgsColorWidget.alterColorF)
13 changes: 13 additions & 0 deletions python/PyQt6/gui/auto_generated/qgscolorwidgets.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ set to a color with an ambiguous hue (e.g., black or white shades).
Black
};

enum class ComponentUnit
{
Scaled0to255,
Percent,
Degree
};

QgsColorWidget( QWidget *parent /TransferThis/ = 0, ColorComponent component = Multiple );
%Docstring
Construct a new color widget.
Expand Down Expand Up @@ -102,6 +109,12 @@ Create an icon for dragging colors
:param color: for icon
%End

static ComponentUnit componentUnit( ColorComponent component );
%Docstring
Returns color ``component`` unit
%End


public slots:

virtual void setColor( const QColor &color, bool emitSignals = false );
Expand Down
8 changes: 8 additions & 0 deletions python/gui/auto_additions/qgscolorwidgets.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# The following has been generated automatically from src/gui/qgscolorwidgets.h
# monkey patching scoped based enum
QgsColorWidget.ComponentUnit.Scaled0to255.__doc__ = "Values in the range 0-255"
QgsColorWidget.ComponentUnit.Percent.__doc__ = "Percent values in the range 0-100"
QgsColorWidget.ComponentUnit.Degree.__doc__ = "Degree values in the range 0-359"
QgsColorWidget.ComponentUnit.__doc__ = "Specified the color component unit\n\n" + '* ``Scaled0to255``: ' + QgsColorWidget.ComponentUnit.Scaled0to255.__doc__ + '\n' + '* ``Percent``: ' + QgsColorWidget.ComponentUnit.Percent.__doc__ + '\n' + '* ``Degree``: ' + QgsColorWidget.ComponentUnit.Degree.__doc__
# --
QgsColorWidget.ComponentUnit.baseClass = QgsColorWidget
QgsColorTextWidget.ColorTextFormat.baseClass = QgsColorTextWidget
try:
QgsColorWidget.__attribute_docs__ = {'colorChanged': "Emitted when the widget's color changes\n\n:param color: new widget color\n", 'hovered': 'Emitted when mouse hovers over widget.\n'}
Expand All @@ -13,5 +20,6 @@
except NameError:
pass
QgsColorWidget.createDragIcon = staticmethod(QgsColorWidget.createDragIcon)
QgsColorWidget.componentUnit = staticmethod(QgsColorWidget.componentUnit)
QgsColorWidget.alterColor = staticmethod(QgsColorWidget.alterColor)
QgsColorWidget.alterColorF = staticmethod(QgsColorWidget.alterColorF)
13 changes: 13 additions & 0 deletions python/gui/auto_generated/qgscolorwidgets.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ set to a color with an ambiguous hue (e.g., black or white shades).
Black
};

enum class ComponentUnit
{
Scaled0to255,
Percent,
Degree
};

QgsColorWidget( QWidget *parent /TransferThis/ = 0, ColorComponent component = Multiple );
%Docstring
Construct a new color widget.
Expand Down Expand Up @@ -102,6 +109,12 @@ Create an icon for dragging colors
:param color: for icon
%End

static ComponentUnit componentUnit( ColorComponent component );
%Docstring
Returns color ``component`` unit
%End


public slots:

virtual void setColor( const QColor &color, bool emitSignals = false );
Expand Down
106 changes: 61 additions & 45 deletions src/gui/qgscolorwidgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,31 @@ QPixmap QgsColorWidget::createDragIcon( const QColor &color )
return pixmap;
}

QgsColorWidget::ComponentUnit QgsColorWidget::componentUnit( ColorComponent component )
{
switch ( component )
{
case QgsColorWidget::Hue:
return ComponentUnit::Degree;
case QgsColorWidget::Saturation:
case QgsColorWidget::Value:
case QgsColorWidget::Alpha:
case QgsColorWidget::Cyan:
case QgsColorWidget::Magenta:
case QgsColorWidget::Yellow:
case QgsColorWidget::Black:
return ComponentUnit::Percent;

case QgsColorWidget::Multiple:
case QgsColorWidget::Red:
case QgsColorWidget::Green:
case QgsColorWidget::Blue:
return ComponentUnit::Scaled0to255;
}

BUILTIN_UNREACHABLE
}

int QgsColorWidget::componentValue( const QgsColorWidget::ColorComponent component ) const
{
return static_cast<int>( std::round( componentValueF( component ) * static_cast<float>( componentRange( component ) ) ) );
Expand Down Expand Up @@ -1447,15 +1472,6 @@ QgsColorSliderWidget::QgsColorSliderWidget( QWidget *parent, const ColorComponen
mSpinBox->setMinimum( 0 );
mSpinBox->setMaximum( convertRealToDisplay( 1.f ) );
mSpinBox->setValue( convertRealToDisplay( componentValueF() ) );
if ( component == QgsColorWidget::Hue )
{
//degrees suffix for hue
mSpinBox->setSuffix( QChar( 176 ) );
}
else if ( component == QgsColorWidget::Saturation || component == QgsColorWidget::Value || component == QgsColorWidget::Alpha )
{
mSpinBox->setSuffix( tr( "%" ) );
}
hLayout->addWidget( mSpinBox );
setLayout( hLayout );

Expand All @@ -1468,21 +1484,21 @@ void QgsColorSliderWidget::setComponent( const QgsColorWidget::ColorComponent co
{
QgsColorWidget::setComponent( component );
mRampWidget->setComponent( component );
mSpinBox->setMaximum( convertRealToDisplay( componentRange() ) );
if ( component == QgsColorWidget::Hue )
{
//degrees suffix for hue
mSpinBox->setSuffix( QChar( 176 ) );
}
else if ( component == QgsColorWidget::Saturation || component == QgsColorWidget::Value || component == QgsColorWidget::Alpha )
{
//saturation, value and alpha are in %
mSpinBox->setSuffix( tr( "%" ) );
}
else
mSpinBox->setMaximum( convertRealToDisplay( static_cast<float>( componentRange() ) ) );

switch ( componentUnit( component ) )
{
//clear suffix
mSpinBox->setSuffix( QString() );
case ComponentUnit::Degree:
mSpinBox->setSuffix( QChar( 176 ) );
break;

case ComponentUnit::Percent:
mSpinBox->setSuffix( tr( "%" ) );
break;

case ComponentUnit::Scaled0to255:
//clear suffix
mSpinBox->setSuffix( QString() );
}
}

Expand Down Expand Up @@ -1529,36 +1545,36 @@ void QgsColorSliderWidget::rampChanged( float value )

float QgsColorSliderWidget::convertRealToDisplay( const float realValue ) const
{
//scale saturation, value or alpha to 0->100 range. This makes more sense for users
//for whom "255" is a totally arbitrary value!
if ( mComponent == QgsColorWidget::Saturation || mComponent == QgsColorWidget::Value || mComponent == QgsColorWidget::Alpha )
{
return realValue * 100.f;
}
else if ( mComponent == QgsColorWidget::Hue )
switch ( componentUnit( mComponent ) )
{
return realValue * HUE_MAX;
}
else
{
return realValue * 255.f;
case ComponentUnit::Percent:
return realValue * 100.f;

case ComponentUnit::Degree:
return realValue * HUE_MAX;

case ComponentUnit::Scaled0to255:
return realValue * 255.f;
}

BUILTIN_UNREACHABLE
}

float QgsColorSliderWidget::convertDisplayToReal( const float displayValue ) const
{
if ( mComponent == QgsColorWidget::Saturation || mComponent == QgsColorWidget::Value || mComponent == QgsColorWidget::Alpha )
{
return displayValue / 100.f;
}
else if ( mComponent == QgsColorWidget::Hue )
switch ( componentUnit( mComponent ) )
{
return displayValue / HUE_MAX;
}
else
{
return displayValue / 255.f;
case ComponentUnit::Percent:
return displayValue / 100.f;

case ComponentUnit::Degree:
return displayValue / HUE_MAX;

case ComponentUnit::Scaled0to255:
return displayValue / 255.f;
}

BUILTIN_UNREACHABLE
}

//
Expand Down
17 changes: 17 additions & 0 deletions src/gui/qgscolorwidgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ class GUI_EXPORT QgsColorWidget : public QWidget
Black //!< Black component (based on CMYK model) of color
};

/**
* Specified the color component unit
*/
enum class ComponentUnit
{
Scaled0to255, //!< Values in the range 0-255
Percent, //!< Percent values in the range 0-100
Degree //!< Degree values in the range 0-359
};
Q_ENUM( ComponentUnit )

/**
* Construct a new color widget.
* \param parent parent QWidget for the widget
Expand Down Expand Up @@ -107,6 +118,12 @@ class GUI_EXPORT QgsColorWidget : public QWidget
*/
static QPixmap createDragIcon( const QColor &color );

/**
* Returns color \a component unit
*/
static ComponentUnit componentUnit( ColorComponent component );


public slots:

/**
Expand Down
40 changes: 39 additions & 1 deletion tests/src/gui/testqgscompoundcolorwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class TestQgsCompoundColorWidget : public QgsTest
void testTabChange();
void testInvalidColor();
void testSliderWidgets();
void testSliderWidgetsCmyk();
};

void TestQgsCompoundColorWidget::initTestCase()
Expand Down Expand Up @@ -245,7 +246,7 @@ void TestQgsCompoundColorWidget::testInvalidColor()

void TestQgsCompoundColorWidget::testSliderWidgets()
{
QgsCompoundColorWidget w( nullptr, QColor::fromRgbF( 0.12f, 0.34f, 0.56, 0.78 ) );
QgsCompoundColorWidget w( nullptr, QColor::fromRgbF( 0.12f, 0.34f, 0.56f, 0.78f ) );
w.setVisible( true );

// TODO QGIS 4 remove the nolint instructions, QColor was qreal (double) and is now float
Expand Down Expand Up @@ -286,6 +287,43 @@ void TestQgsCompoundColorWidget::testSliderWidgets()
// NOLINTEND(bugprone-narrowing-conversions)
}

void TestQgsCompoundColorWidget::testSliderWidgetsCmyk()
{
QgsCompoundColorWidget w( nullptr, QColor::fromCmykF( 0.12f, 0.34f, 0.56f, 0.78f, 0.91f ) );
w.setVisible( true );

// TODO QGIS 4 remove the nolint instructions, QColor was qreal (double) and is now float
// NOLINTBEGIN(bugprone-narrowing-conversions)
QCOMPARE( w.mCyanSlider->mSpinBox->value(), 12 );
compareFloat( w.mCyanSlider->mRampWidget->color().cyanF(), 0.12f );
QCOMPARE( w.mMagentaSlider->mSpinBox->value(), 34 );
compareFloat( w.mMagentaSlider->mRampWidget->color().magentaF(), 0.34f );
QCOMPARE( w.mYellowSlider->mSpinBox->value(), 56 );
compareFloat( w.mYellowSlider->mRampWidget->color().yellowF(), 0.56f );
QCOMPARE( w.mBlackSlider->mSpinBox->value(), 78 );
compareFloat( w.mBlackSlider->mRampWidget->color().blackF(), 0.78f );
QCOMPARE( w.mAlphaSlider->mSpinBox->value(), 91 );
compareFloat( w.mAlphaSlider->mRampWidget->color().alphaF(), 0.91f );

w.mCyanSlider->mRampWidget->setColorFromPoint( QPointF( static_cast<float>( w.mCyanSlider->mRampWidget->width() ) / 2.f, 0.f ) );
w.mMagentaSlider->mRampWidget->setColorFromPoint( QPointF( static_cast<float>( w.mMagentaSlider->mRampWidget->width() ) / 2.f, 0.f ) );
w.mYellowSlider->mRampWidget->setColorFromPoint( QPointF( static_cast<float>( w.mYellowSlider->mRampWidget->width() ) / 2.f, 0.f ) );
w.mBlackSlider->mRampWidget->setColorFromPoint( QPointF( static_cast<float>( w.mBlackSlider->mRampWidget->width() ) / 2.f, 0.f ) );
w.mAlphaSlider->mRampWidget->setColorFromPoint( QPointF( static_cast<float>( w.mAlphaSlider->mRampWidget->width() ) / 2.f, 0.f ) );

QCOMPARE( w.mCyanSlider->mSpinBox->value(), 50 );
compareFloat( w.mCyanSlider->mRampWidget->color().cyanF(), 0.5f );
QCOMPARE( w.mMagentaSlider->mSpinBox->value(), 50 );
compareFloat( w.mMagentaSlider->mRampWidget->color().magentaF(), 0.5f );
QCOMPARE( w.mYellowSlider->mSpinBox->value(), 50 );
compareFloat( w.mYellowSlider->mRampWidget->color().yellowF(), 0.5f );
QCOMPARE( w.mBlackSlider->mSpinBox->value(), 50 );
compareFloat( w.mBlackSlider->mRampWidget->color().blackF(), 0.5f );
QCOMPARE( w.mAlphaSlider->mSpinBox->value(), 50 );
compareFloat( w.mAlphaSlider->mRampWidget->color().alphaF(), 0.5f );
// NOLINTEND(bugprone-narrowing-conversions)
}


QGSTEST_MAIN( TestQgsCompoundColorWidget )
#include "testqgscompoundcolorwidget.moc"

0 comments on commit 0880614

Please sign in to comment.