31#include <QFontMetrics>
39#include <QResizeEvent>
41#include <QStyleOptionFrame>
44#include "moc_qgscolorwidgets.cpp"
46using namespace Qt::StringLiterals;
67 setAcceptDrops(
true );
84 QPixmap pixmap( iconSize, iconSize );
85 pixmap.fill( Qt::transparent );
87 painter.begin( &pixmap );
89 painter.fillRect( QRect( 0, 0, iconSize, iconSize ), QBrush( QColor( 200, 200, 200 ) ) );
91 QColor pixmapColor =
color;
92 pixmapColor.setAlpha( 255 );
93 painter.setBrush( QBrush( pixmapColor ) );
94 painter.setPen( QPen( Qt::white ) );
95 painter.drawRect( QRect( 1, 1, iconSize - 2, iconSize - 2 ) );
197 return static_cast<int>( std::round(
hueF() *
HUE_MAX ) );
221 float_type clippedValue = std::clamp( newValue, 0.f, 1.f );
226 color.getCmykF( &
c, &m, &y, &k, &a );
231 color.setCmykF( clippedValue, m, y, k, a );
234 color.setCmykF(
c, clippedValue, y, k, a );
237 color.setCmykF(
c, m, clippedValue, k, a );
240 color.setCmykF(
c, m, y, clippedValue, a );
249 color.getRgbF( &r, &g, &b, &a );
251 color.getHsvF( &h, &s, &v );
256 color.setRedF( clippedValue );
259 color.setGreenF( clippedValue );
262 color.setBlueF( clippedValue );
265 color.setHsvF( clippedValue, s, v, a );
268 color.setHsvF( h, clippedValue, v, a );
271 color.setHsvF( h, s, clippedValue, a );
274 color.setAlphaF( clippedValue );
289 return QColor::Spec::Rgb;
294 return QColor::Spec::Hsv;
300 return QColor::Spec::Cmyk;
303 return QColor::Spec::Invalid;
314 static QPixmap sTranspBkgrd;
316 if ( sTranspBkgrd.isNull() )
328 if ( mimeColor.isValid() )
331 e->acceptProposedAction();
338 bool hasAlpha =
false;
341 if ( mimeColor.isValid() )
344 e->acceptProposedAction();
438 if (
color.hue() >= 0 )
460 QConicalGradient wheelGradient = QConicalGradient( 0, 0, 0 );
461 const int wheelStops = 20;
462 QColor gradColor = QColor::fromHsvF( 1.0, 1.0, 1.0 );
463 for (
int pos = 0; pos <= wheelStops; ++pos )
465 const double relativePos =
static_cast<double>( pos ) / wheelStops;
466 gradColor.setHsvF( relativePos, 1, 1 );
467 wheelGradient.setColorAt( relativePos, gradColor );
469 mWheelBrush = QBrush( wheelGradient );
480 return QSize( size, size );
486 QPainter painter(
this );
488 if ( mWidgetImage.isNull() || mWheelImage.isNull() || mTriangleImage.isNull() )
490 createImages( size() );
494 mWidgetImage.fill( Qt::transparent );
495 QPainter imagePainter( &mWidgetImage );
496 imagePainter.setRenderHint( QPainter::Antialiasing );
505 const QPointF center = QPointF( mWidgetImage.width() / 2.0 / mWidgetImage.devicePixelRatioF(), mWidgetImage.height() / 2.0 / mWidgetImage.devicePixelRatioF() );
506 imagePainter.drawImage( QPointF( center.x() - ( mWheelImage.width() / 2.0 / mWidgetImage.devicePixelRatioF() ), center.y() - ( mWheelImage.height() / 2.0 / mWidgetImage.devicePixelRatioF() ) ), mWheelImage );
510 const double length = mWheelImage.width() / 2.0 / mWidgetImage.devicePixelRatioF();
511 QLineF hueMarkerLine = QLineF( center.x(), center.y(), center.x() + length, center.y() );
512 hueMarkerLine.setAngle( h );
515 imagePainter.setCompositionMode( QPainter::CompositionMode_SourceIn );
517 pen.setWidthF( 2 * mWidgetImage.devicePixelRatioF() );
519 pen.setColor( h > 20 && h < 200 ? Qt::black : Qt::white );
520 imagePainter.setPen( pen );
521 imagePainter.drawLine( hueMarkerLine );
525 if ( mTriangleDirty )
529 imagePainter.drawImage( QPointF( center.x() - ( mWheelImage.width() / 2.0 / mWidgetImage.devicePixelRatioF() ), center.y() - ( mWheelImage.height() / 2.0 / mWidgetImage.devicePixelRatioF() ) ), mTriangleImage );
532 const double triangleRadius = length - ( mWheelThickness + 1 ) * mWheelImage.devicePixelRatioF();
536 const double hueRadians = ( h * M_PI / 180.0 );
537 const double hx = std::cos( hueRadians ) * triangleRadius;
538 const double hy = -std::sin( hueRadians ) * triangleRadius;
539 const double sx = -std::cos( -hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
540 const double sy = -std::sin( -hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
541 const double vx = -std::cos( hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
542 const double vy = std::sin( hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
543 const double mx = ( sx + vx ) / 2.0;
544 const double my = ( sy + vy ) / 2.0;
546 const double a = ( 1 - 2.0 * std::fabs( lightness - 0.5 ) ) *
mCurrentColor.hslSaturationF();
547 const double x = sx + ( vx - sx ) * lightness + ( hx - mx ) * a;
548 const double y = sy + ( vy - sy ) * lightness + ( hy - my ) * a;
551 pen.setColor( lightness > 0.7 ? Qt::black : Qt::white );
552 imagePainter.setPen( pen );
553 imagePainter.setBrush( Qt::NoBrush );
554 imagePainter.drawEllipse( QPointF( x + center.x(), y + center.y() ), 4.0 * mWheelImage.devicePixelRatioF(), 4.0 * mWheelImage.devicePixelRatioF() );
558 painter.drawImage( QRectF( 0, 0, width(), height() ), mWidgetImage );
567 mTriangleDirty =
true;
573void QgsColorWheel::createImages(
const QSizeF size )
575 const double wheelSize = std::min( size.width(), size.height() ) - mMargin * 2.0;
576 mWheelThickness = wheelSize / 15.0;
579 const double pixelRatio = devicePixelRatioF();
580 mWheelImage = QImage( wheelSize * pixelRatio, wheelSize * pixelRatio, QImage::Format_ARGB32 );
581 mWheelImage.setDevicePixelRatio( pixelRatio );
582 mTriangleImage = QImage( wheelSize * pixelRatio, wheelSize * pixelRatio, QImage::Format_ARGB32 );
583 mTriangleImage.setDevicePixelRatio( pixelRatio );
584 mWidgetImage = QImage( size.width() * pixelRatio, size.height() * pixelRatio, QImage::Format_ARGB32 );
585 mWidgetImage.setDevicePixelRatio( pixelRatio );
589 mTriangleDirty =
true;
598void QgsColorWheel::setColorFromPos(
const QPointF pos )
600 const QPointF center = QPointF( width() / 2.0, height() / 2.0 );
602 const QLineF line = QLineF( center.x(), center.y(), pos.x(), pos.y() );
604 QColor newColor = QColor();
611 if ( mClickedPart == QgsColorWheel::Triangle )
616 const double x = pos.x() - center.x();
617 const double y = pos.y() - center.y();
619 double eventAngleRadians = line.angle() * M_PI / 180.0;
620 const double hueRadians = h * 2 * M_PI;
621 double rad0 = std::fmod( eventAngleRadians + 2.0 * M_PI - hueRadians, 2.0 * M_PI );
622 double rad1 = std::fmod( rad0, ( ( 2.0 / 3.0 ) * M_PI ) ) - ( M_PI / 3.0 );
623 const double length = mWheelImage.width() / 2.0 / mWheelImage.devicePixelRatioF();
624 const double triangleLength = length - mWheelThickness - 1;
626 const double a = 0.5 * triangleLength;
627 double b = std::tan( rad1 ) * a;
628 double r = std::sqrt( x * x + y * y );
629 const double maxR = std::sqrt( a * a + b * b );
633 const double dx = std::tan( rad1 ) * r;
634 double rad2 = std::atan( dx / maxR );
635 rad2 = std::min( rad2, M_PI / 3.0 );
636 rad2 = std::max( rad2, -M_PI / 3.0 );
637 eventAngleRadians += rad2 - rad1;
638 rad0 = std::fmod( eventAngleRadians + 2.0 * M_PI - hueRadians, 2.0 * M_PI );
639 rad1 = std::fmod( rad0, ( ( 2.0 / 3.0 ) * M_PI ) ) - ( M_PI / 3.0 );
640 b = std::tan( rad1 ) * a;
641 r = std::sqrt( a * a + b * b );
644 const double triangleSideLength = std::sqrt( 3.0 ) * triangleLength;
645 const double newL = ( ( -std::sin( rad0 ) * r ) / triangleSideLength ) + 0.5;
646 const double widthShare = 1.0 - ( std::fabs( newL - 0.5 ) * 2.0 );
647 const double newS = ( ( ( std::cos( rad0 ) * r ) + ( triangleLength / 2.0 ) ) / ( 1.5 * triangleLength ) ) / widthShare;
648 s = std::min( std::max( 0.f,
static_cast<float>( newS ) ), 1.f );
649 l = std::min( std::max( 0.f,
static_cast<float>( newL ) ), 1.f );
650 newColor = QColor::fromHslF( h, s, l );
652 newColor.setHsvF( h, newColor.hsvSaturationF(), newColor.valueF(), alpha );
654 else if ( mClickedPart == QgsColorWheel::Wheel )
659 const qreal newHue = line.angle() /
HUE_MAX;
660 newColor = QColor::fromHsvF(
static_cast<float>( newHue ), s, v, alpha );
662 mTriangleDirty =
true;
684 setColorFromPos( event->pos() );
691 if ( event->button() == Qt::LeftButton )
697 const QLineF line = QLineF( width() / 2.0, height() / 2.0, event->pos().x(), event->pos().y() );
699 const double innerLength = mWheelImage.width() / 2.0 / mWheelImage.devicePixelRatioF() - mWheelThickness * mWheelImage.devicePixelRatioF();
700 if ( line.length() < innerLength )
702 mClickedPart = QgsColorWheel::Triangle;
706 mClickedPart = QgsColorWheel::Wheel;
708 setColorFromPos( event->pos() );
718 if ( event->button() == Qt::LeftButton )
721 mClickedPart = QgsColorWheel::None;
729void QgsColorWheel::invalidateImages()
732 mWidgetImage = QImage();
735void QgsColorWheel::createWheel()
737 if ( mWheelImage.isNull() )
742 const int maxSize = std::min( mWheelImage.width(), mWheelImage.height() );
743 const double wheelRadius = maxSize / 2.0 / mWheelImage.devicePixelRatioF();
745 mWheelImage.fill( Qt::transparent );
746 QPainter p( &mWheelImage );
747 p.setRenderHint( QPainter::Antialiasing );
748 p.setBrush( mWheelBrush );
749 p.setPen( Qt::NoPen );
752 p.translate( wheelRadius, wheelRadius );
753 p.drawEllipse( QPointF( 0, 0 ), wheelRadius, wheelRadius );
756 p.setCompositionMode( QPainter::CompositionMode_DestinationOut );
757 p.setBrush( QBrush( Qt::black ) );
758 p.drawEllipse( QPointF( 0, 0 ), wheelRadius - mWheelThickness * mWheelImage.devicePixelRatioF(), wheelRadius - mWheelThickness * mWheelImage.devicePixelRatioF() );
764void QgsColorWheel::createTriangle()
766 if ( mWheelImage.isNull() || mTriangleImage.isNull() )
771 const QPointF center = QPointF( mWheelImage.width() / 2.0 / mWheelImage.devicePixelRatioF(), mWheelImage.height() / 2.0 / mWheelImage.devicePixelRatioF() );
772 mTriangleImage.fill( Qt::transparent );
774 QPainter imagePainter( &mTriangleImage );
775 imagePainter.setRenderHint( QPainter::Antialiasing );
779 const double wheelRadius = mWheelImage.width() / 2.0 / mWheelImage.devicePixelRatioF();
780 const double triangleRadius = wheelRadius - mWheelThickness * mWheelImage.devicePixelRatioF() - 1;
783 const QColor pureColor = QColor::fromHsvF( angle, 1., 1. );
785 QColor alphaColor = QColor( pureColor );
786 alphaColor.setAlpha( 0 );
789 QLineF line1 = QLineF( center.x(), center.y(), center.x() - triangleRadius * std::cos( M_PI / 3.0 ), center.y() - triangleRadius * std::sin( M_PI / 3.0 ) );
790 QLineF line2 = QLineF( center.x(), center.y(), center.x() + triangleRadius, center.y() );
791 QLineF line3 = QLineF( center.x(), center.y(), center.x() - triangleRadius * std::cos( M_PI / 3.0 ), center.y() + triangleRadius * std::sin( M_PI / 3.0 ) );
792 QLineF line4 = QLineF( center.x(), center.y(), center.x() - triangleRadius * std::cos( M_PI / 3.0 ), center.y() );
793 QLineF line5 = QLineF( center.x(), center.y(), ( line2.p2().x() + line1.p2().x() ) / 2.0, ( line2.p2().y() + line1.p2().y() ) / 2.0 );
794 line1.setAngle( line1.angle() + angleDegree );
795 line2.setAngle( line2.angle() + angleDegree );
796 line3.setAngle( line3.angle() + angleDegree );
797 line4.setAngle( line4.angle() + angleDegree );
798 line5.setAngle( line5.angle() + angleDegree );
799 const QPointF p1 = line1.p2();
800 const QPointF p2 = line2.p2();
801 const QPointF p3 = line3.p2();
802 const QPointF p4 = line4.p2();
803 const QPointF p5 = line5.p2();
806 QLinearGradient colorGrad = QLinearGradient( p4.x(), p4.y(), p2.x(), p2.y() );
807 colorGrad.setColorAt( 0, alphaColor );
808 colorGrad.setColorAt( 1, pureColor );
809 QLinearGradient whiteGrad = QLinearGradient( p3.x(), p3.y(), p5.x(), p5.y() );
810 whiteGrad.setColorAt( 0, QColor( 255, 255, 255, 255 ) );
811 whiteGrad.setColorAt( 1, QColor( 255, 255, 255, 0 ) );
814 triangle << p2 << p1 << p3 << p2;
815 imagePainter.setPen( Qt::NoPen );
817 imagePainter.setBrush( QBrush( Qt::black ) );
818 imagePainter.drawPolygon( triangle );
820 imagePainter.setBrush( QBrush( colorGrad ) );
821 imagePainter.drawPolygon( triangle );
823 imagePainter.setCompositionMode( QPainter::CompositionMode_Plus );
824 imagePainter.setBrush( QBrush( whiteGrad ) );
825 imagePainter.drawPolygon( triangle );
830 imagePainter.setCompositionMode( QPainter::CompositionMode_Source );
831 imagePainter.setBrush( Qt::NoBrush );
832 imagePainter.setPen( QPen( Qt::transparent ) );
833 imagePainter.drawPolygon( triangle );
836 mTriangleDirty =
false;
847 setFocusPolicy( Qt::StrongFocus );
848 setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
850 mBoxImage = std::make_unique<QImage>( width() -
static_cast<int>( mMargin * 2 ), height() -
static_cast<int>( mMargin * 2 ), QImage::Format_RGB32 );
859 return QSize( size, size );
865 QPainter painter(
this );
867 QStyleOptionFrame option;
868 option.initFrom(
this );
869 option.state = hasFocus() ? QStyle::State_Active : QStyle::State_None;
870 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
878 painter.drawImage( QPoint( mMargin, mMargin ), *mBoxImage );
881 const double h = height();
882 const double w = width();
883 const double margin = mMargin;
884 const double xPos = ( mMargin + ( w - 2 * mMargin - 1 ) * xComponentValue() );
885 const double yPos = ( mMargin + ( h - 2 * mMargin - 1 ) - ( h - 2 * mMargin - 1 ) * yComponentValue() );
887 painter.setBrush( Qt::white );
888 painter.setPen( Qt::NoPen );
890 painter.drawRect( QRectF( xPos - 1, mMargin, 3, height() - 2 * margin - 1 ) );
891 painter.drawRect( QRectF( mMargin, yPos - 1, width() - 2 * margin - 1, 3 ) );
892 painter.setPen( Qt::black );
893 painter.drawLine( QLineF( xPos, mMargin, xPos, height() - margin - 1 ) );
894 painter.drawLine( QLineF( mMargin, yPos, width() - margin - 1, yPos ) );
912 mDirty |= ( (
mComponent ==
QgsColorWidget::Red && !
qgsDoubleNear(
mCurrentColor.redF(),
color.redF() ) ) || (
mComponent ==
QgsColorWidget::Green && !
qgsDoubleNear(
mCurrentColor.greenF(),
color.greenF() ) ) || (
mComponent ==
QgsColorWidget::Blue && !
qgsDoubleNear(
mCurrentColor.blueF(),
color.blueF() ) ) || (
mComponent ==
QgsColorWidget::Hue &&
color.hsvHueF() >= 0 && !
qgsDoubleNear(
hueF(),
color.hsvHueF() ) ) || (
mComponent ==
QgsColorWidget::Saturation && !
qgsDoubleNear(
mCurrentColor.hsvSaturationF(),
color.hsvSaturationF() ) ) || (
mComponent ==
QgsColorWidget::Value && !
qgsDoubleNear(
mCurrentColor.valueF(),
color.valueF() ) ) || (
mComponent ==
QgsColorWidget::Cyan && !
qgsDoubleNear(
mCurrentColor.cyanF(),
color.cyanF() ) ) || (
mComponent ==
QgsColorWidget::Magenta && !
qgsDoubleNear(
mCurrentColor.magentaF(),
color.magentaF() ) ) || (
mComponent ==
QgsColorWidget::Yellow && !
qgsDoubleNear(
mCurrentColor.yellowF(),
color.yellowF() ) ) || (
mComponent ==
QgsColorWidget::Black && !
qgsDoubleNear(
mCurrentColor.blackF(),
color.blackF() ) ) );
920 mBoxImage = std::make_unique<QImage>( event->size().width() -
static_cast<int>( mMargin * 2 ), event->size().height() -
static_cast<int>( mMargin * 2 ), QImage::Format_RGB32 );
922 QgsColorWidget::resizeEvent( event );
929 setColorFromPoint( event->pos() );
936 if ( event->button() == Qt::LeftButton )
939 setColorFromPoint( event->pos() );
949 if ( event->button() == Qt::LeftButton )
959void QgsColorBox::createBox()
961 const int maxValueX = mBoxImage->width();
962 const int maxValueY = mBoxImage->height();
966 float colorComponentValue;
968 for (
int y = 0; y < maxValueY; ++y )
970 QRgb *scanLine = ( QRgb * ) mBoxImage->scanLine( y );
972 colorComponentValue = 1.f -
static_cast<float>( y ) /
static_cast<float>( maxValueY );
973 alterColorF( currentColor, yComponent(), colorComponentValue );
974 for (
int x = 0; x < maxValueX; ++x )
976 colorComponentValue =
static_cast<float>( x ) /
static_cast<float>( maxValueY );
977 alterColorF( currentColor, xComponent(), colorComponentValue );
978 scanLine[x] = currentColor.rgb();
984float QgsColorBox::valueRangeX()
const
989float QgsColorBox::valueRangeY()
const
1022float QgsColorBox::yComponentValue()
const
1055float QgsColorBox::xComponentValue()
const
1060void QgsColorBox::setColorFromPoint( QPoint point )
1062 const float x =
static_cast<float>( point.x() );
1063 const float y =
static_cast<float>( point.y() );
1064 const float w =
static_cast<float>( width() );
1065 const float h =
static_cast<float>( height() );
1067 float valX = ( x - mMargin ) / ( w - 2 * mMargin - 1 );
1068 float valY = 1.f - ( y - mMargin ) / ( h - 2 * mMargin - 1 );
1079 if (
color.hueF() >= 0 )
1097 setFocusPolicy( Qt::StrongFocus );
1121 QPainter painter(
this );
1126 QStyleOptionFrame option;
1127 option.initFrom(
this );
1128 option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
1129 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
1135 QStyleOptionFocusRect option;
1136 option.initFrom(
this );
1137 option.state = QStyle::State_KeyboardFocusChange;
1138 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
1141 float w =
static_cast<float>( width() );
1142 float h =
static_cast<float>( height() );
1143 float margin =
static_cast<float>( mMargin );
1148 color.setAlphaF( 1.f );
1155 painter.setPen( pen );
1156 painter.setBrush( Qt::NoBrush );
1159 for (
int c = 0;
c <= maxValue; ++
c )
1161 float colorVal =
static_cast<float>(
c ) /
static_cast<float>( maxValue );
1165 colorVal = 1.f - colorVal;
1168 if (
color.hueF() < 0 )
1172 pen.setColor(
color );
1173 painter.setPen( pen );
1177 painter.drawLine( QLineF(
c + mMargin, mMargin,
c + mMargin, height() - mMargin - 1 ) );
1182 painter.drawLine( QLineF( mMargin,
c + mMargin, width() - mMargin - 1,
c + mMargin ) );
1191 painter.setBrush( checkBrush );
1192 painter.setPen( Qt::NoPen );
1193 painter.drawRect( QRectF( margin, margin, w - 2 * margin - 1, h - 2 * margin - 1 ) );
1194 QLinearGradient colorGrad;
1198 colorGrad = QLinearGradient( margin, 0, w - margin - 1, 0 );
1203 colorGrad = QLinearGradient( 0, margin, 0, h - margin - 1 );
1206 transparent.setAlpha( 0 );
1207 colorGrad.setColorAt( 0, transparent );
1209 opaque.setAlpha( 255 );
1210 colorGrad.setColorAt( 1, opaque );
1211 const QBrush colorBrush = QBrush( colorGrad );
1212 painter.setBrush( colorBrush );
1213 painter.drawRect( QRectF( margin, margin, w - 2 * margin - 1, h - 2 * margin - 1 ) );
1219 painter.setRenderHint( QPainter::Antialiasing );
1220 painter.setBrush( QBrush( Qt::black ) );
1221 painter.setPen( Qt::NoPen );
1222 painter.translate( margin + ( w - 2 * margin ) *
componentValueF(), margin - 1 );
1223 painter.drawPolygon( mTopTriangle );
1224 painter.translate( 0, h - margin - 2 );
1225 painter.setBrush( QBrush( Qt::white ) );
1226 painter.drawPolygon( mBottomTriangle );
1232 const double ypos = margin + ( h - 2 * margin - 1 ) - ( h - 2 * margin - 1 ) *
componentValueF();
1233 painter.setBrush( Qt::white );
1234 painter.setPen( Qt::NoPen );
1235 painter.drawRect( QRectF( margin, ypos - 1, w - 2 * margin - 1, 3 ) );
1236 painter.setPen( Qt::black );
1237 painter.drawLine( QLineF( margin, ypos, w - margin - 1, ypos ) );
1247 setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
1252 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
1259 if ( margin == mMargin )
1280 mTopTriangle << QPoint( -markerSize, 0 ) << QPoint( markerSize, 0 ) << QPoint( 0, markerSize );
1281 mBottomTriangle << QPoint( -markerSize, 0 ) << QPoint( markerSize, 0 ) << QPoint( 0, -markerSize );
1289 setColorFromPoint( event->pos() );
1298 const float delta = 1.f /
static_cast<float>(
componentRange() );
1299 if ( event->angleDelta().y() > 0 )
1323 if ( event->button() == Qt::LeftButton )
1326 setColorFromPoint( event->pos() );
1336 if ( event->button() == Qt::LeftButton )
1338 mIsDragging =
false;
1349 const float delta = 1.f /
static_cast<float>(
componentRange() );
1379 QgsColorWidget::keyPressEvent( event );
1394void QgsColorRampWidget::setColorFromPoint( QPointF point )
1398 const float margin =
static_cast<float>( mMargin );
1399 const float w =
static_cast<float>( width() );
1400 const float h =
static_cast<float>( height() );
1404 val = (
static_cast<float>( point.x() ) - margin ) / ( w - 2 * margin );
1408 val = 1.f - (
static_cast<float>( point.y() ) - margin ) / ( h - 2 * margin );
1431 QHBoxLayout *hLayout =
new QHBoxLayout();
1432 hLayout->setContentsMargins( 0, 0, 0, 0 );
1433 hLayout->setSpacing( 5 );
1437 hLayout->addWidget( mRampWidget, 1 );
1440 mSpinBox->setShowClearButton(
false );
1442 const int largestCharWidth = mSpinBox->fontMetrics().horizontalAdvance( u
"888.88%"_s );
1443 mSpinBox->setFixedWidth( largestCharWidth + 35 );
1444 mSpinBox->setMinimum( 0 );
1445 mSpinBox->setMaximum( convertRealToDisplay( 1.f ) );
1447 hLayout->addWidget( mSpinBox );
1448 setLayout( hLayout );
1452 connect( mSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsColorSliderWidget::spinChanged );
1459 mSpinBox->setMaximum( convertRealToDisplay(
static_cast<float>(
componentRange() ) ) );
1464 mSpinBox->setSuffix( QChar( 176 ) );
1468 mSpinBox->setSuffix( tr(
"%" ) );
1473 mSpinBox->setSuffix( QString() );
1480 mRampWidget->blockSignals(
true );
1481 mRampWidget->setComponentValueF( value );
1482 mRampWidget->blockSignals(
false );
1483 mSpinBox->blockSignals(
true );
1484 mSpinBox->setValue( convertRealToDisplay( value ) );
1485 mSpinBox->blockSignals(
false );
1491 mRampWidget->setColor(
color );
1492 mSpinBox->blockSignals(
true );
1494 mSpinBox->blockSignals(
false );
1497void QgsColorSliderWidget::rampColorChanged(
const QColor &color )
1502void QgsColorSliderWidget::spinChanged(
double value )
1504 const float convertedValue = convertDisplayToReal(
static_cast<float>( value ) );
1506 mRampWidget->setComponentValueF( convertedValue );
1510void QgsColorSliderWidget::rampChanged(
float value )
1512 mSpinBox->blockSignals(
true );
1513 mSpinBox->setValue( convertRealToDisplay( value ) );
1514 mSpinBox->blockSignals(
false );
1518float QgsColorSliderWidget::convertRealToDisplay(
const float realValue )
const
1523 return realValue * 100.f;
1529 return realValue * 255.f;
1535float QgsColorSliderWidget::convertDisplayToReal(
const float displayValue )
const
1540 return displayValue / 100.f;
1543 return displayValue /
HUE_MAX;
1546 return displayValue / 255.f;
1559 QHBoxLayout *hLayout =
new QHBoxLayout();
1560 hLayout->setContentsMargins( 0, 0, 0, 0 );
1561 hLayout->setSpacing( 0 );
1563 mLineEdit =
new QLineEdit(
nullptr );
1564 hLayout->addWidget( mLineEdit );
1566 mMenuButton =
new QToolButton( mLineEdit );
1568 mMenuButton->setCursor( Qt::ArrowCursor );
1569 mMenuButton->setFocusPolicy( Qt::NoFocus );
1570 mMenuButton->setStyleSheet( u
"QToolButton { border: none; padding: 0px; }"_s );
1572 setLayout( hLayout );
1574 const int frameWidth = mLineEdit->style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
1575 mLineEdit->setStyleSheet( u
"QLineEdit { padding-right: %1px; } "_s.arg( mMenuButton->sizeHint().width() + frameWidth + 1 ) );
1577 connect( mLineEdit, &QLineEdit::editingFinished,
this, &QgsColorTextWidget::textChanged );
1578 connect( mMenuButton, &QAbstractButton::clicked,
this, &QgsColorTextWidget::showMenu );
1595 const QSize sz = mMenuButton->sizeHint();
1596 const int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
1597 mMenuButton->move( mLineEdit->rect().right() - frameWidth - sz.width(), ( mLineEdit->rect().bottom() + 1 - sz.height() ) / 2 );
1600void QgsColorTextWidget::updateText()
1619void QgsColorTextWidget::textChanged()
1621 const QString testString = mLineEdit->text();
1624 if ( !
color.isValid() )
1635 if ( !containsAlpha )
1646void QgsColorTextWidget::showMenu()
1648 QMenu colorContextMenu;
1649 QAction *hexRgbaAction =
nullptr;
1650 QAction *rgbaAction =
nullptr;
1652 QAction *hexRgbAction =
new QAction( tr(
"#RRGGBB" ),
nullptr );
1653 colorContextMenu.addAction( hexRgbAction );
1656 hexRgbaAction =
new QAction( tr(
"#RRGGBBAA" ),
nullptr );
1657 colorContextMenu.addAction( hexRgbaAction );
1659 QAction *rgbAction =
new QAction( tr(
"rgb( r, g, b )" ),
nullptr );
1660 colorContextMenu.addAction( rgbAction );
1663 rgbaAction =
new QAction( tr(
"rgba( r, g, b, a )" ),
nullptr );
1664 colorContextMenu.addAction( rgbaAction );
1667 QAction *selectedAction = colorContextMenu.exec( QCursor::pos() );
1668 if ( selectedAction == hexRgbAction )
1672 else if ( hexRgbaAction && selectedAction == hexRgbaAction )
1676 else if ( selectedAction == rgbAction )
1680 else if ( rgbaAction && selectedAction == rgbaAction )
1693 mAllowAlpha = allowOpacity;
1702 , mColor2( QColor() )
1705void QgsColorPreviewWidget::drawColor(
const QColor &color, QRect rect, QPainter &painter )
1707 painter.setPen( Qt::NoPen );
1709 if (
color.alpha() < 255 )
1712 painter.setBrush( checkBrush );
1713 painter.drawRect( rect );
1718 const QBrush colorBrush = QBrush(
color );
1719 painter.setBrush( colorBrush );
1720 painter.drawRect( std::floor( rect.width() / 2.0 ) + rect.left(), rect.top(), rect.width() - std::floor( rect.width() / 2.0 ), rect.height() );
1722 QColor opaqueColor = QColor(
color );
1723 opaqueColor.setAlpha( 255 );
1724 const QBrush opaqueBrush = QBrush( opaqueColor );
1725 painter.setBrush( opaqueBrush );
1726 painter.drawRect( rect.left(), rect.top(), std::ceil( rect.width() / 2.0 ), rect.height() );
1731 const QBrush brush = QBrush(
color );
1732 painter.setBrush( brush );
1733 painter.drawRect( rect );
1740 QPainter painter(
this );
1742 if ( mColor2.isValid() )
1745 const int verticalSplit = std::round( height() / 2.0 );
1746 drawColor(
mCurrentColor, QRect( 0, 0, width(), verticalSplit ), painter );
1747 drawColor( mColor2, QRect( 0, verticalSplit, width(), height() - verticalSplit ), painter );
1751 drawColor(
mCurrentColor, QRect( 0, 0, width(), height() ), painter );
1764 if (
color == mColor2 )
1774 if ( e->button() == Qt::LeftButton )
1776 mDragStartPosition = e->pos();
1783 if ( ( e->pos() - mDragStartPosition ).manhattanLength() >= QApplication::startDragDistance() )
1792 if ( mColor2.isValid() )
1795 const int verticalSplit = std::round( height() / 2.0 );
1796 if ( mDragStartPosition.y() >= verticalSplit )
1798 clickedColor = mColor2;
1808 if ( !( e->buttons() & Qt::LeftButton ) )
1815 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
1826 if ( mColor2.isValid() )
1829 const int verticalSplit = std::round( height() / 2.0 );
1830 if ( mDragStartPosition.y() >= verticalSplit )
1832 dragColor = mColor2;
1836 QDrag *drag =
new QDrag(
this );
1839 drag->exec( Qt::CopyAction );
1848 : QWidgetAction( parent )
1852 setDefaultWidget( mColorWidget );
1855 connect(
this, &QAction::hovered,
this, &QgsColorWidgetAction::onHover );
1859void QgsColorWidgetAction::onHover()
1862 if ( mSuppressRecurse )
1869 mSuppressRecurse =
true;
1870 mMenu->setActiveAction(
this );
1871 mSuppressRecurse =
false;
1875void QgsColorWidgetAction::setColor(
const QColor &color )
1878 if ( mMenu && mDismissOnColorSelection )
static const double UI_SCALE_FACTOR
UI scaling factor.
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
QSize sizeHint() const override
void resizeEvent(QResizeEvent *event) override
void mouseReleaseEvent(QMouseEvent *event) override
void mousePressEvent(QMouseEvent *event) override
void setComponent(ColorComponent component) override
Sets the color component which the widget controls.
void setColor(const QColor &color, bool emitSignals=false) override
void mouseMoveEvent(QMouseEvent *event) override
void paintEvent(QPaintEvent *event) override
QgsColorBox(QWidget *parent=nullptr, ColorComponent component=Value)
Construct a new color box widget.
QgsColorTextWidget(QWidget *parent=nullptr)
Construct a new color line edit widget.
@ Rgba
Rgba( r, g, b, a ) format, with alpha.
@ Rgb
Rgb( r, g, b ) format.
@ HexRgbA
#RRGGBBAA in hexadecimal, with alpha
@ HexRgb
#RRGGBB in hexadecimal
void setColor(const QColor &color, bool emitSignals=false) override
Sets the color for the widget.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted.
static const QgsSettingsEntryEnumFlag< ColorTextFormat > * settingsTextFormat
void resizeEvent(QResizeEvent *event) override
void paintEvent(QPaintEvent *event) override
QgsColorWheel(QWidget *parent=nullptr)
Constructs a new color wheel widget.
void mousePressEvent(QMouseEvent *event) override
QSize sizeHint() const override
void mouseReleaseEvent(QMouseEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override
void resizeEvent(QResizeEvent *event) override
void setColor(const QColor &color, bool emitSignals=false) override
~QgsColorWheel() override
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Scoped object for saving and restoring a QPainter object's state.
void restore()
Performs a manual restore on the painter state, popping the latest state from the painter.
A utility class for dynamic handling of changes to screen properties.
void screenDpiChanged(double dpi)
Emitted whenever the screen dpi associated with the widget is changed.
A template class for enum and flag settings entry.
static QgsSettingsTreeNode * sTreeColorWidgets
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static std::unique_ptr< QMimeData > colorToMimeData(const QColor &color)
Creates mime data from a color.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored).
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define BUILTIN_UNREACHABLE
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).