17#include "moc_qgscolorwidgets.cpp" 
   25#include <QResizeEvent> 
   27#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) 
   28#include <QStyleOptionFrameV3> 
   30#include <QStyleOptionFrame> 
   35#include <QFontMetrics> 
   48#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) 
   61  , mCurrentColor( Qt::red )
 
   62  , mComponent( component )
 
   64  setAcceptDrops( 
true );
 
 
   81  QPixmap pixmap( iconSize, iconSize );
 
   82  pixmap.fill( Qt::transparent );
 
   84  painter.begin( &pixmap );
 
   86  painter.fillRect( QRect( 0, 0, iconSize, iconSize ), QBrush( QColor( 200, 200, 200 ) ) );
 
   88  QColor pixmapColor = 
color;
 
   89  pixmapColor.setAlpha( 255 );
 
   90  painter.setBrush( QBrush( pixmapColor ) );
 
   91  painter.setPen( QPen( Qt::white ) );
 
   92  painter.drawRect( QRect( 1, 1, iconSize - 2, iconSize - 2 ) );
 
 
  194  return static_cast<int>( std::round( 
hueF() * 
HUE_MAX ) );
 
 
  218  float_type clippedValue = std::clamp( newValue, 0.f, 1.f );
 
  223    color.getCmykF( &
c, &m, &y, &k, &a );
 
  228        color.setCmykF( clippedValue, m, y, k, a );
 
  231        color.setCmykF( 
c, clippedValue, y, k, a );
 
  234        color.setCmykF( 
c, m, clippedValue, k, a );
 
  237        color.setCmykF( 
c, m, y, clippedValue, a );
 
  246    color.getRgbF( &r, &g, &b, &a );
 
  248    color.getHsvF( &h, &s, &v );
 
  253        color.setRedF( clippedValue );
 
  256        color.setGreenF( clippedValue );
 
  259        color.setBlueF( clippedValue );
 
  262        color.setHsvF( clippedValue, s, v, a );
 
  265        color.setHsvF( h, clippedValue, v, a );
 
  268        color.setHsvF( h, s, clippedValue, a );
 
  271        color.setAlphaF( clippedValue );
 
 
  286      return QColor::Spec::Rgb;
 
  291      return QColor::Spec::Hsv;
 
  297      return QColor::Spec::Cmyk;
 
  300      return QColor::Spec::Invalid;
 
 
  311  static QPixmap sTranspBkgrd;
 
  313  if ( sTranspBkgrd.isNull() )
 
 
  325  if ( mimeColor.isValid() )
 
  328    e->acceptProposedAction();
 
 
  335  bool hasAlpha = 
false;
 
  338  if ( mimeColor.isValid() )
 
  341    e->acceptProposedAction();
 
 
  435  if ( 
color.hue() >= 0 )
 
 
  457  QConicalGradient wheelGradient = QConicalGradient( 0, 0, 0 );
 
  458  const int wheelStops = 20;
 
  459  QColor gradColor = QColor::fromHsvF( 1.0, 1.0, 1.0 );
 
  460  for ( 
int pos = 0; pos <= wheelStops; ++pos )
 
  462    const double relativePos = 
static_cast<double>( pos ) / wheelStops;
 
  463    gradColor.setHsvF( relativePos, 1, 1 );
 
  464    wheelGradient.setColorAt( relativePos, gradColor );
 
  466  mWheelBrush = QBrush( wheelGradient );
 
 
  474  return QSize( size, size );
 
 
  480  QPainter painter( 
this );
 
  482  if ( mWidgetImage.isNull() || mWheelImage.isNull() || mTriangleImage.isNull() )
 
  484    createImages( size() );
 
  488  mWidgetImage.fill( Qt::transparent );
 
  489  QPainter imagePainter( &mWidgetImage );
 
  490  imagePainter.setRenderHint( QPainter::Antialiasing );
 
  499  const QPointF center = QPointF( mWidgetImage.width() / 2.0, mWidgetImage.height() / 2.0 );
 
  500  imagePainter.drawImage( QPointF( center.x() - ( mWheelImage.width() / 2.0 ), center.y() - ( mWheelImage.height() / 2.0 ) ), mWheelImage );
 
  504  const double length = mWheelImage.width() / 2.0;
 
  505  QLineF hueMarkerLine = QLineF( center.x(), center.y(), center.x() + length, center.y() );
 
  506  hueMarkerLine.setAngle( h );
 
  509  imagePainter.setCompositionMode( QPainter::CompositionMode_SourceIn );
 
  511  pen.setWidthF( 2 * devicePixelRatioF() );
 
  513  pen.setColor( h > 20 && h < 200 ? Qt::black : Qt::white );
 
  514  imagePainter.setPen( pen );
 
  515  imagePainter.drawLine( hueMarkerLine );
 
  516  imagePainter.restore();
 
  519  if ( mTriangleDirty )
 
  523  imagePainter.drawImage( QPointF( center.x() - ( mWheelImage.width() / 2.0 ), center.y() - ( mWheelImage.height() / 2.0 ) ), mTriangleImage );
 
  526  const double triangleRadius = length - mWheelThickness * devicePixelRatioF() - 1;
 
  530  const double hueRadians = ( h * M_PI / 180.0 );
 
  531  const double hx = std::cos( hueRadians ) * triangleRadius;
 
  532  const double hy = -std::sin( hueRadians ) * triangleRadius;
 
  533  const double sx = -std::cos( -hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
 
  534  const double sy = -std::sin( -hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
 
  535  const double vx = -std::cos( hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
 
  536  const double vy = std::sin( hueRadians + ( M_PI / 3.0 ) ) * triangleRadius;
 
  537  const double mx = ( sx + vx ) / 2.0;
 
  538  const double my = ( sy + vy ) / 2.0;
 
  540  const double a = ( 1 - 2.0 * std::fabs( lightness - 0.5 ) ) * 
mCurrentColor.hslSaturationF();
 
  541  const double x = sx + ( vx - sx ) * lightness + ( hx - mx ) * a;
 
  542  const double y = sy + ( vy - sy ) * lightness + ( hy - my ) * a;
 
  545  pen.setColor( lightness > 0.7 ? Qt::black : Qt::white );
 
  546  imagePainter.setPen( pen );
 
  547  imagePainter.setBrush( Qt::NoBrush );
 
  548  imagePainter.drawEllipse( QPointF( x + center.x(), y + center.y() ), 4.0 * devicePixelRatioF(), 4.0 * devicePixelRatioF() );
 
  552  painter.drawImage( QRectF( 0, 0, width(), height() ), mWidgetImage );
 
 
  561    mTriangleDirty = 
true;
 
 
  567void QgsColorWheel::createImages( 
const QSizeF size )
 
  569  const double wheelSize = std::min( size.width(), size.height() ) - mMargin * 2.0;
 
  570  mWheelThickness = wheelSize / 15.0;
 
  573  const double pixelRatio = devicePixelRatioF();
 
  574  mWheelImage = QImage( wheelSize * pixelRatio, wheelSize * pixelRatio, QImage::Format_ARGB32 );
 
  575  mTriangleImage = QImage( wheelSize * pixelRatio, wheelSize * pixelRatio, QImage::Format_ARGB32 );
 
  576  mWidgetImage = QImage( size.width() * pixelRatio, size.height() * pixelRatio, QImage::Format_ARGB32 );
 
  580  mTriangleDirty = 
true;
 
  585  QgsColorWidget::resizeEvent( event );
 
  588  if ( event->size().width() > parentWidget()->size().width() )
 
  591      std::min( event->size().width(), parentWidget()->size().width() - 2 ),
 
  592      std::min( event->size().height(), parentWidget()->size().height() - 2 )
 
  595    createImages( newSize );
 
  599    createImages( event->size() );
 
  603  createImages( event->size() );
 
 
  607void QgsColorWheel::setColorFromPos( 
const QPointF pos )
 
  609  const QPointF center = QPointF( width() / 2.0, height() / 2.0 );
 
  611  const QLineF line = QLineF( center.x(), center.y(), pos.x(), pos.y() );
 
  613  QColor newColor = QColor();
 
  620  if ( mClickedPart == QgsColorWheel::Triangle )
 
  625    const double x = pos.x() - center.x();
 
  626    const double y = pos.y() - center.y();
 
  628    double eventAngleRadians = line.angle() * M_PI / 180.0;
 
  629    const double hueRadians = h * 2 * M_PI;
 
  630    double rad0 = std::fmod( eventAngleRadians + 2.0 * M_PI - hueRadians, 2.0 * M_PI );
 
  631    double rad1 = std::fmod( rad0, ( ( 2.0 / 3.0 ) * M_PI ) ) - ( M_PI / 3.0 );
 
  632    const double length = mWheelImage.width() / 2.0 / devicePixelRatioF();
 
  633    const double triangleLength = length - mWheelThickness - 1;
 
  635    const double a = 0.5 * triangleLength;
 
  636    double b = std::tan( rad1 ) * a;
 
  637    double r = std::sqrt( x * x + y * y );
 
  638    const double maxR = std::sqrt( a * a + b * b );
 
  642      const double dx = std::tan( rad1 ) * r;
 
  643      double rad2 = std::atan( dx / maxR );
 
  644      rad2 = std::min( rad2, M_PI / 3.0 );
 
  645      rad2 = std::max( rad2, -M_PI / 3.0 );
 
  646      eventAngleRadians += rad2 - rad1;
 
  647      rad0 = std::fmod( eventAngleRadians + 2.0 * M_PI - hueRadians, 2.0 * M_PI );
 
  648      rad1 = std::fmod( rad0, ( ( 2.0 / 3.0 ) * M_PI ) ) - ( M_PI / 3.0 );
 
  649      b = std::tan( rad1 ) * a;
 
  650      r = std::sqrt( a * a + b * b );
 
  653    const double triangleSideLength = std::sqrt( 3.0 ) * triangleLength;
 
  654    const double newL = ( ( -std::sin( rad0 ) * r ) / triangleSideLength ) + 0.5;
 
  655    const double widthShare = 1.0 - ( std::fabs( newL - 0.5 ) * 2.0 );
 
  656    const double newS = ( ( ( std::cos( rad0 ) * r ) + ( triangleLength / 2.0 ) ) / ( 1.5 * triangleLength ) ) / widthShare;
 
  657    s = std::min( std::max( 0.f, 
static_cast<float>( newS ) ), 1.f );
 
  658    l = std::min( std::max( 0.f, 
static_cast<float>( newL ) ), 1.f );
 
  659    newColor = QColor::fromHslF( h, s, l );
 
  661    newColor.setHsvF( h, newColor.hsvSaturationF(), newColor.valueF(), alpha );
 
  663  else if ( mClickedPart == QgsColorWheel::Wheel )
 
  668    const qreal newHue = line.angle() / 
HUE_MAX;
 
  669    newColor = QColor::fromHsvF( 
static_cast<float>( newHue ), s, v, alpha );
 
  671    mTriangleDirty = 
true;
 
  693    setColorFromPos( event->pos() );
 
 
  700  if ( event->button() == Qt::LeftButton )
 
  706    const QLineF line = QLineF( width() / 2.0, height() / 2.0, event->pos().x(), event->pos().y() );
 
  708    const double innerLength = mWheelImage.width() / 2.0 / devicePixelRatioF() - mWheelThickness;
 
  709    if ( line.length() < innerLength )
 
  711      mClickedPart = QgsColorWheel::Triangle;
 
  715      mClickedPart = QgsColorWheel::Wheel;
 
  717    setColorFromPos( event->pos() );
 
 
  727  if ( event->button() == Qt::LeftButton )
 
  730    mClickedPart = QgsColorWheel::None;
 
 
  738void QgsColorWheel::createWheel()
 
  740  if ( mWheelImage.isNull() )
 
  745  const int maxSize = std::min( mWheelImage.width(), mWheelImage.height() );
 
  746  const double wheelRadius = maxSize / 2.0;
 
  748  mWheelImage.fill( Qt::transparent );
 
  749  QPainter p( &mWheelImage );
 
  750  p.setRenderHint( QPainter::Antialiasing );
 
  751  p.setBrush( mWheelBrush );
 
  752  p.setPen( Qt::NoPen );
 
  755  p.translate( wheelRadius, wheelRadius );
 
  756  p.drawEllipse( QPointF( 0.0, 0.0 ), wheelRadius, wheelRadius );
 
  759  p.setCompositionMode( QPainter::CompositionMode_DestinationOut );
 
  760  p.setBrush( QBrush( Qt::black ) );
 
  761  p.drawEllipse( QPointF( 0, 0 ), wheelRadius - mWheelThickness * devicePixelRatioF(), wheelRadius - mWheelThickness * devicePixelRatioF() );
 
  767void QgsColorWheel::createTriangle()
 
  769  if ( mWheelImage.isNull() || mTriangleImage.isNull() )
 
  774  const QPointF center = QPointF( mWheelImage.width() / 2.0, mWheelImage.height() / 2.0 );
 
  775  mTriangleImage.fill( Qt::transparent );
 
  777  QPainter imagePainter( &mTriangleImage );
 
  778  imagePainter.setRenderHint( QPainter::Antialiasing );
 
  782  const double wheelRadius = mWheelImage.width() / 2.0;
 
  783  const double triangleRadius = wheelRadius - mWheelThickness * devicePixelRatioF() - 1;
 
  786  const QColor pureColor = QColor::fromHsvF( angle, 1., 1. );
 
  788  QColor alphaColor = QColor( pureColor );
 
  789  alphaColor.setAlpha( 0 );
 
  792  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 ) );
 
  793  QLineF line2 = QLineF( center.x(), center.y(), center.x() + triangleRadius, center.y() );
 
  794  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 ) );
 
  795  QLineF line4 = QLineF( center.x(), center.y(), center.x() - triangleRadius * std::cos( M_PI / 3.0 ), center.y() );
 
  796  QLineF line5 = QLineF( center.x(), center.y(), ( line2.p2().x() + line1.p2().x() ) / 2.0, ( line2.p2().y() + line1.p2().y() ) / 2.0 );
 
  797  line1.setAngle( line1.angle() + angleDegree );
 
  798  line2.setAngle( line2.angle() + angleDegree );
 
  799  line3.setAngle( line3.angle() + angleDegree );
 
  800  line4.setAngle( line4.angle() + angleDegree );
 
  801  line5.setAngle( line5.angle() + angleDegree );
 
  802  const QPointF p1 = line1.p2();
 
  803  const QPointF p2 = line2.p2();
 
  804  const QPointF p3 = line3.p2();
 
  805  const QPointF p4 = line4.p2();
 
  806  const QPointF p5 = line5.p2();
 
  809  QLinearGradient colorGrad = QLinearGradient( p4.x(), p4.y(), p2.x(), p2.y() );
 
  810  colorGrad.setColorAt( 0, alphaColor );
 
  811  colorGrad.setColorAt( 1, pureColor );
 
  812  QLinearGradient whiteGrad = QLinearGradient( p3.x(), p3.y(), p5.x(), p5.y() );
 
  813  whiteGrad.setColorAt( 0, QColor( 255, 255, 255, 255 ) );
 
  814  whiteGrad.setColorAt( 1, QColor( 255, 255, 255, 0 ) );
 
  817  triangle << p2 << p1 << p3 << p2;
 
  818  imagePainter.setPen( Qt::NoPen );
 
  820  imagePainter.setBrush( QBrush( Qt::black ) );
 
  821  imagePainter.drawPolygon( triangle );
 
  823  imagePainter.setBrush( QBrush( colorGrad ) );
 
  824  imagePainter.drawPolygon( triangle );
 
  826  imagePainter.setCompositionMode( QPainter::CompositionMode_Plus );
 
  827  imagePainter.setBrush( QBrush( whiteGrad ) );
 
  828  imagePainter.drawPolygon( triangle );
 
  833  imagePainter.setCompositionMode( QPainter::CompositionMode_Source );
 
  834  imagePainter.setBrush( Qt::NoBrush );
 
  835  imagePainter.setPen( QPen( Qt::transparent ) );
 
  836  imagePainter.drawPolygon( triangle );
 
  839  mTriangleDirty = 
false;
 
  850  setFocusPolicy( Qt::StrongFocus );
 
  851  setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
 
  853  mBoxImage = 
new QImage( width() - mMargin * 2, height() - mMargin * 2, QImage::Format_RGB32 );
 
 
  864  return QSize( size, size );
 
 
  870  QPainter painter( 
this );
 
  872  QStyleOptionFrame option;
 
  873  option.initFrom( 
this );
 
  874  option.state = hasFocus() ? QStyle::State_Active : QStyle::State_None;
 
  875  style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
 
  883  painter.drawImage( QPoint( mMargin, mMargin ), *mBoxImage );
 
  886  const double h = height();
 
  887  const double w = width();
 
  888  const double margin = mMargin;
 
  889  const double xPos = ( mMargin + ( w - 2 * mMargin - 1 ) * xComponentValue() );
 
  890  const double yPos = ( mMargin + ( h - 2 * mMargin - 1 ) - ( h - 2 * mMargin - 1 ) * yComponentValue() );
 
  892  painter.setBrush( Qt::white );
 
  893  painter.setPen( Qt::NoPen );
 
  895  painter.drawRect( QRectF( xPos - 1, mMargin, 3, height() - 2 * margin - 1 ) );
 
  896  painter.drawRect( QRectF( mMargin, yPos - 1, width() - 2 * margin - 1, 3 ) );
 
  897  painter.setPen( Qt::black );
 
  898  painter.drawLine( QLineF( xPos, mMargin, xPos, height() - margin - 1 ) );
 
  899  painter.drawLine( QLineF( mMargin, yPos, width() - margin - 1, yPos ) );
 
 
  917  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() ) ) );
 
 
  926  mBoxImage = 
new QImage( event->size().width() - mMargin * 2, event->size().height() - mMargin * 2, QImage::Format_RGB32 );
 
  927  QgsColorWidget::resizeEvent( event );
 
 
  934    setColorFromPoint( event->pos() );
 
 
  941  if ( event->button() == Qt::LeftButton )
 
  944    setColorFromPoint( event->pos() );
 
 
  954  if ( event->button() == Qt::LeftButton )
 
 
  964void QgsColorBox::createBox()
 
  966  const int maxValueX = mBoxImage->width();
 
  967  const int maxValueY = mBoxImage->height();
 
  971  float colorComponentValue;
 
  973  for ( 
int y = 0; y < maxValueY; ++y )
 
  975    QRgb *scanLine = ( QRgb * ) mBoxImage->scanLine( y );
 
  977    colorComponentValue = 1.f - 
static_cast<float>( y ) / 
static_cast<float>( maxValueY );
 
  978    alterColorF( currentColor, yComponent(), colorComponentValue );
 
  979    for ( 
int x = 0; x < maxValueX; ++x )
 
  981      colorComponentValue = 
static_cast<float>( x ) / 
static_cast<float>( maxValueY );
 
  982      alterColorF( currentColor, xComponent(), colorComponentValue );
 
  983      scanLine[x] = currentColor.rgb();
 
  989float QgsColorBox::valueRangeX()
 const 
  994float QgsColorBox::valueRangeY()
 const 
 1027float QgsColorBox::yComponentValue()
 const 
 1060float QgsColorBox::xComponentValue()
 const 
 1065void QgsColorBox::setColorFromPoint( QPoint point )
 
 1067  const float x = 
static_cast<float>( point.x() );
 
 1068  const float y = 
static_cast<float>( point.y() );
 
 1069  const float w = 
static_cast<float>( width() );
 
 1070  const float h = 
static_cast<float>( height() );
 
 1072  float valX = ( x - mMargin ) / ( w - 2 * mMargin - 1 );
 
 1073  float valY = 1.f - ( y - mMargin ) / ( h - 2 * mMargin - 1 );
 
 1084  if ( 
color.hueF() >= 0 )
 
 1102  setFocusPolicy( Qt::StrongFocus );
 
 
 1126  QPainter painter( 
this );
 
 1131    QStyleOptionFrame option;
 
 1132    option.initFrom( 
this );
 
 1133    option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
 
 1134    style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
 
 1140    QStyleOptionFocusRect option;
 
 1141    option.initFrom( 
this );
 
 1142    option.state = QStyle::State_KeyboardFocusChange;
 
 1143    style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
 
 1146  float w = 
static_cast<float>( width() );
 
 1147  float h = 
static_cast<float>( height() );
 
 1148  float margin = 
static_cast<float>( mMargin );
 
 1153    color.setAlphaF( 1.f );
 
 1160    painter.setPen( pen );
 
 1161    painter.setBrush( Qt::NoBrush );
 
 1164    for ( 
int c = 0; 
c <= maxValue; ++
c )
 
 1166      float colorVal = 
static_cast<float>( 
c ) / 
static_cast<float>( maxValue );
 
 1170        colorVal = 1.f - colorVal;
 
 1173      if ( 
color.hueF() < 0 )
 
 1177      pen.setColor( 
color );
 
 1178      painter.setPen( pen );
 
 1182        painter.drawLine( QLineF( 
c + mMargin, mMargin, 
c + mMargin, height() - mMargin - 1 ) );
 
 1187        painter.drawLine( QLineF( mMargin, 
c + mMargin, width() - mMargin - 1, 
c + mMargin ) );
 
 1196    painter.setBrush( checkBrush );
 
 1197    painter.setPen( Qt::NoPen );
 
 1198    painter.drawRect( QRectF( margin, margin, w - 2 * margin - 1, h - 2 * margin - 1 ) );
 
 1199    QLinearGradient colorGrad;
 
 1203      colorGrad = QLinearGradient( margin, 0, w - margin - 1, 0 );
 
 1208      colorGrad = QLinearGradient( 0, margin, 0, h - margin - 1 );
 
 1211    transparent.setAlpha( 0 );
 
 1212    colorGrad.setColorAt( 0, transparent );
 
 1214    opaque.setAlpha( 255 );
 
 1215    colorGrad.setColorAt( 1, opaque );
 
 1216    const QBrush colorBrush = QBrush( colorGrad );
 
 1217    painter.setBrush( colorBrush );
 
 1218    painter.drawRect( QRectF( margin, margin, w - 2 * margin - 1, h - 2 * margin - 1 ) );
 
 1224    painter.setRenderHint( QPainter::Antialiasing );
 
 1225    painter.setBrush( QBrush( Qt::black ) );
 
 1226    painter.setPen( Qt::NoPen );
 
 1227    painter.translate( margin + ( w - 2 * margin ) * 
componentValueF(), margin - 1 );
 
 1228    painter.drawPolygon( mTopTriangle );
 
 1229    painter.translate( 0, h - margin - 2 );
 
 1230    painter.setBrush( QBrush( Qt::white ) );
 
 1231    painter.drawPolygon( mBottomTriangle );
 
 1237    const double ypos = margin + ( h - 2 * margin - 1 ) - ( h - 2 * margin - 1 ) * 
componentValueF();
 
 1238    painter.setBrush( Qt::white );
 
 1239    painter.setPen( Qt::NoPen );
 
 1240    painter.drawRect( QRectF( margin, ypos - 1, w - 2 * margin - 1, 3 ) );
 
 1241    painter.setPen( Qt::black );
 
 1242    painter.drawLine( QLineF( margin, ypos, w - margin - 1, ypos ) );
 
 
 1252    setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
 
 1257    setSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
 
 
 1264  if ( margin == mMargin )
 
 
 1285  mTopTriangle << QPoint( -markerSize, 0 ) << QPoint( markerSize, 0 ) << QPoint( 0, markerSize );
 
 1286  mBottomTriangle << QPoint( -markerSize, 0 ) << QPoint( markerSize, 0 ) << QPoint( 0, -markerSize );
 
 
 1294    setColorFromPoint( event->pos() );
 
 
 1303  const float delta = 1.f / 
static_cast<float>( 
componentRange() );
 
 1304  if ( event->angleDelta().y() > 0 )
 
 
 1328  if ( event->button() == Qt::LeftButton )
 
 1331    setColorFromPoint( event->pos() );
 
 
 1341  if ( event->button() == Qt::LeftButton )
 
 1343    mIsDragging = 
false;
 
 
 1354  const float delta = 1.f / 
static_cast<float>( 
componentRange() );
 
 1388    QgsColorWidget::keyPressEvent( event );
 
 
 1403void QgsColorRampWidget::setColorFromPoint( QPointF point )
 
 1407  const float margin = 
static_cast<float>( mMargin );
 
 1408  const float w = 
static_cast<float>( width() );
 
 1409  const float h = 
static_cast<float>( height() );
 
 1413    val = ( 
static_cast<float>( point.x() ) - margin ) / ( w - 2 * margin );
 
 1417    val = 1.f - ( 
static_cast<float>( point.y() ) - margin ) / ( h - 2 * margin );
 
 1440  QHBoxLayout *hLayout = 
new QHBoxLayout();
 
 1441  hLayout->setContentsMargins( 0, 0, 0, 0 );
 
 1442  hLayout->setSpacing( 5 );
 
 1446  hLayout->addWidget( mRampWidget, 1 );
 
 1451  const int largestCharWidth = mSpinBox->fontMetrics().horizontalAdvance( QStringLiteral( 
"888%" ) );
 
 1452  mSpinBox->setMinimumWidth( largestCharWidth + 35 );
 
 1453  mSpinBox->setMinimum( 0 );
 
 1454  mSpinBox->setMaximum( convertRealToDisplay( 1.f ) );
 
 1456  hLayout->addWidget( mSpinBox );
 
 1457  setLayout( hLayout );
 
 1461  connect( mSpinBox, 
static_cast<void ( QDoubleSpinBox::* )( 
double )
>( &QDoubleSpinBox::valueChanged ), 
this, &QgsColorSliderWidget::spinChanged );
 
 
 1468  mSpinBox->setMaximum( convertRealToDisplay( 
static_cast<float>( 
componentRange() ) ) );
 
 1473      mSpinBox->setSuffix( QChar( 176 ) );
 
 1477      mSpinBox->setSuffix( tr( 
"%" ) );
 
 1482      mSpinBox->setSuffix( QString() );
 
 
 1489  mRampWidget->blockSignals( 
true );
 
 1491  mRampWidget->blockSignals( 
false );
 
 1492  mSpinBox->blockSignals( 
true );
 
 1493  mSpinBox->setValue( convertRealToDisplay( value ) );
 
 1494  mSpinBox->blockSignals( 
false );
 
 
 1501  mSpinBox->blockSignals( 
true );
 
 1503  mSpinBox->blockSignals( 
false );
 
 
 1506void QgsColorSliderWidget::rampColorChanged( 
const QColor &color )
 
 1511void QgsColorSliderWidget::spinChanged( 
double value )
 
 1513  const float convertedValue = convertDisplayToReal( 
static_cast<float>( value ) );
 
 1519void QgsColorSliderWidget::rampChanged( 
float value )
 
 1521  mSpinBox->blockSignals( 
true );
 
 1522  mSpinBox->setValue( convertRealToDisplay( value ) );
 
 1523  mSpinBox->blockSignals( 
false );
 
 1527float QgsColorSliderWidget::convertRealToDisplay( 
const float realValue )
 const 
 1532      return realValue * 100.f;
 
 1538      return realValue * 255.f;
 
 1544float QgsColorSliderWidget::convertDisplayToReal( 
const float displayValue )
 const 
 1549      return displayValue / 100.f;
 
 1552      return displayValue / 
HUE_MAX;
 
 1555      return displayValue / 255.f;
 
 1568  QHBoxLayout *hLayout = 
new QHBoxLayout();
 
 1569  hLayout->setContentsMargins( 0, 0, 0, 0 );
 
 1570  hLayout->setSpacing( 0 );
 
 1572  mLineEdit = 
new QLineEdit( 
nullptr );
 
 1573  hLayout->addWidget( mLineEdit );
 
 1575  mMenuButton = 
new QToolButton( mLineEdit );
 
 1577  mMenuButton->setCursor( Qt::ArrowCursor );
 
 1578  mMenuButton->setFocusPolicy( Qt::NoFocus );
 
 1579  mMenuButton->setStyleSheet( QStringLiteral( 
"QToolButton { border: none; padding: 0px; }" ) );
 
 1581  setLayout( hLayout );
 
 1583  const int frameWidth = mLineEdit->style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
 
 1584  mLineEdit->setStyleSheet( QStringLiteral( 
"QLineEdit { padding-right: %1px; } " )
 
 1585                              .arg( mMenuButton->sizeHint().width() + frameWidth + 1 ) );
 
 1587  connect( mLineEdit, &QLineEdit::editingFinished, 
this, &QgsColorTextWidget::textChanged );
 
 1588  connect( mMenuButton, &QAbstractButton::clicked, 
this, &QgsColorTextWidget::showMenu );
 
 1592  mFormat = settings.
enumValue( QStringLiteral( 
"ColorWidgets/textWidgetFormat" ), 
HexRgb );
 
 
 1606  const QSize sz = mMenuButton->sizeHint();
 
 1607  const int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
 
 1608  mMenuButton->move( mLineEdit->rect().right() - frameWidth - sz.width(), ( mLineEdit->rect().bottom() + 1 - sz.height() ) / 2 );
 
 
 1611void QgsColorTextWidget::updateText()
 
 1630void QgsColorTextWidget::textChanged()
 
 1632  const QString testString = mLineEdit->text();
 
 1635  if ( !
color.isValid() )
 
 1646    if ( !containsAlpha )
 
 1657void QgsColorTextWidget::showMenu()
 
 1659  QMenu colorContextMenu;
 
 1660  QAction *hexRgbaAction = 
nullptr;
 
 1661  QAction *rgbaAction = 
nullptr;
 
 1663  QAction *hexRgbAction = 
new QAction( tr( 
"#RRGGBB" ), 
nullptr );
 
 1664  colorContextMenu.addAction( hexRgbAction );
 
 1667    hexRgbaAction = 
new QAction( tr( 
"#RRGGBBAA" ), 
nullptr );
 
 1668    colorContextMenu.addAction( hexRgbaAction );
 
 1670  QAction *rgbAction = 
new QAction( tr( 
"rgb( r, g, b )" ), 
nullptr );
 
 1671  colorContextMenu.addAction( rgbAction );
 
 1674    rgbaAction = 
new QAction( tr( 
"rgba( r, g, b, a )" ), 
nullptr );
 
 1675    colorContextMenu.addAction( rgbaAction );
 
 1678  QAction *selectedAction = colorContextMenu.exec( QCursor::pos() );
 
 1679  if ( selectedAction == hexRgbAction )
 
 1683  else if ( hexRgbaAction && selectedAction == hexRgbaAction )
 
 1687  else if ( selectedAction == rgbAction )
 
 1691  else if ( rgbaAction && selectedAction == rgbaAction )
 
 1698  settings.
setEnumValue( QStringLiteral( 
"ColorWidgets/textWidgetFormat" ), mFormat );
 
 1705  mAllowAlpha = allowOpacity;
 
 
 1714  , mColor2( QColor() )
 
 
 1718void QgsColorPreviewWidget::drawColor( 
const QColor &color, QRect rect, QPainter &painter )
 
 1720  painter.setPen( Qt::NoPen );
 
 1722  if ( 
color.alpha() < 255 )
 
 1725    painter.setBrush( checkBrush );
 
 1726    painter.drawRect( rect );
 
 1731    const QBrush colorBrush = QBrush( 
color );
 
 1732    painter.setBrush( colorBrush );
 
 1733    painter.drawRect( std::floor( rect.width() / 2.0 ) + rect.left(), rect.top(), rect.width() - std::floor( rect.width() / 2.0 ), rect.height() );
 
 1735    QColor opaqueColor = QColor( 
color );
 
 1736    opaqueColor.setAlpha( 255 );
 
 1737    const QBrush opaqueBrush = QBrush( opaqueColor );
 
 1738    painter.setBrush( opaqueBrush );
 
 1739    painter.drawRect( rect.left(), rect.top(), std::ceil( rect.width() / 2.0 ), rect.height() );
 
 1744    const QBrush brush = QBrush( 
color );
 
 1745    painter.setBrush( brush );
 
 1746    painter.drawRect( rect );
 
 1753  QPainter painter( 
this );
 
 1755  if ( mColor2.isValid() )
 
 1758    const int verticalSplit = std::round( height() / 2.0 );
 
 1759    drawColor( 
mCurrentColor, QRect( 0, 0, width(), verticalSplit ), painter );
 
 1760    drawColor( mColor2, QRect( 0, verticalSplit, width(), height() - verticalSplit ), painter );
 
 1764    drawColor( 
mCurrentColor, QRect( 0, 0, width(), height() ), painter );
 
 
 1777  if ( 
color == mColor2 )
 
 
 1787  if ( e->button() == Qt::LeftButton )
 
 1789    mDragStartPosition = e->pos();
 
 
 1796  if ( ( e->pos() - mDragStartPosition ).manhattanLength() >= QApplication::startDragDistance() )
 
 1805  if ( mColor2.isValid() )
 
 1808    const int verticalSplit = std::round( height() / 2.0 );
 
 1809    if ( mDragStartPosition.y() >= verticalSplit )
 
 1811      clickedColor = mColor2;
 
 
 1821  if ( !( e->buttons() & Qt::LeftButton ) )
 
 1828  if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
 
 1839  if ( mColor2.isValid() )
 
 1842    const int verticalSplit = std::round( height() / 2.0 );
 
 1843    if ( mDragStartPosition.y() >= verticalSplit )
 
 1845      dragColor = mColor2;
 
 1849  QDrag *drag = 
new QDrag( 
this );
 
 1852  drag->exec( Qt::CopyAction );
 
 
 1861  : QWidgetAction( parent )
 
 1863  , mColorWidget( colorWidget )
 
 1864  , mSuppressRecurse( false )
 
 1865  , mDismissOnColorSelection( true )
 
 1867  setDefaultWidget( mColorWidget );
 
 1870  connect( 
this, &QAction::hovered, 
this, &QgsColorWidgetAction::onHover );
 
 
 1874void QgsColorWidgetAction::onHover()
 
 1877  if ( mSuppressRecurse )
 
 1884    mSuppressRecurse = 
true;
 
 1885    mMenu->setActiveAction( 
this );
 
 1886    mSuppressRecurse = 
false;
 
 1890void QgsColorWidgetAction::setColor( 
const QColor &color )
 
 1893  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.
 
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.
 
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
 
Stores settings for use within QGIS.
 
void setEnumValue(const QString &key, const T &value, const Section section=NoSection)
Set the value of a setting based on an enum.
 
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
 
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 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)