21 #include <QStyleOptionFrameV3> 
   22 #include <QMouseEvent> 
   24 #define MARKER_WIDTH 11 
   25 #define MARKER_HEIGHT 14 
   26 #define MARKER_GAP 1.5 
   27 #define MARGIN_BOTTOM ( MARKER_HEIGHT + 2 ) 
   28 #define MARGIN_X ( MARKER_WIDTH / 2 ) 
   29 #define FRAME_MARGIN 2 
   30 #define CLICK_THRESHOLD ( MARKER_WIDTH / 2 + 3 ) 
   37   mStops = mGradient.
stops();
 
   39   if ( sOuterTriangle.isEmpty() )
 
   47   if ( sInnerTriangle.isEmpty() )
 
   56   setFocusPolicy( Qt::StrongFocus );
 
   57   setAcceptDrops( 
true );
 
   63   mStops = mGradient.
stops();
 
   72   return QSize( 200, 80 );
 
   78   QPainter painter( 
this );
 
   80   QRect frameRect( rect().x() + 
MARGIN_X, rect().y(),
 
   85   QStyleOptionFrame option;
 
   86   option.initFrom( 
this );
 
   87   option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
 
   88   option.rect = frameRect;
 
   89   style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
 
   94     QStyleOptionFocusRect option;
 
   95     option.initFrom( 
this );
 
   96     option.state = QStyle::State_KeyboardFocusChange;
 
   97     option.rect = frameRect;
 
   98     style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
 
  102   QBrush checkBrush = QBrush( transparentBackground() );
 
  103   painter.setBrush( checkBrush );
 
  104   painter.setPen( Qt::NoPen );
 
  110   painter.drawRect( box );
 
  113   for ( 
int i = 0; i < box.width() + 1; ++i )
 
  115     QPen pen( mGradient.
color( 
static_cast< double >( i ) / box.width() ) );
 
  116     painter.setPen( pen );
 
  117     painter.drawLine( box.left() + i, box.top(), box.left() + i, box.height() + 1 );
 
  121   int markerTop = frameRect.bottom() + 1;
 
  122   drawStopMarker( painter, QPoint( box.left(), markerTop ), mGradient.
color1(), mSelectedStop == 0 );
 
  123   drawStopMarker( painter, QPoint( box.right(), markerTop ), mGradient.
color2(), mSelectedStop == mGradient.
count() - 1 );
 
  125   const auto constMStops = mStops;
 
  128     int x = stop.offset * box.width() + box.left();
 
  129     drawStopMarker( painter, QPoint( x, markerTop ), stop.color, mSelectedStop == i );
 
  138   if ( index > 0 && index < mGradient.
count() - 1 )
 
  143     const auto constMStops = mStops;
 
  154   mSelectedStop = index;
 
  161   if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
 
  163     return mStops.at( mSelectedStop - 1 );
 
  165   else if ( mSelectedStop == 0 )
 
  177   if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
 
  179     mStops[ mSelectedStop - 1 ].color = color;
 
  182   else if ( mSelectedStop == 0 )
 
  196   if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
 
  198     mStops[ mSelectedStop - 1 ].offset = offset;
 
  207   if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
 
  209     mStops[ mSelectedStop - 1 ].color = color;
 
  210     mStops[ mSelectedStop - 1 ].offset = offset;
 
  213   else if ( mSelectedStop == 0 )
 
  228   if ( selectedStopIsMovable() )
 
  231     double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
 
  232     mStops.removeAt( mSelectedStop - 1 );
 
  235     int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
 
  259   if ( e->buttons() & Qt::LeftButton )
 
  261     if ( selectedStopIsMovable() )
 
  263       double offset = pointToRelativePosition( e->pos().x() );
 
  267       mStops[ mSelectedStop - 1 ].offset = offset;
 
  277 int QgsGradientStopEditor::findClosestStop( 
int x, 
int threshold )
 const 
  279   int closestStop = -1;
 
  280   int closestDiff = std::numeric_limits<int>::max();
 
  281   int currentDiff = std::numeric_limits<int>::max();
 
  287   const auto constStops = mGradient.
stops();
 
  290     currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
 
  291     if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
 
  294       closestDiff = currentDiff;
 
  300   currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
 
  301   if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
 
  304     closestDiff = currentDiff;
 
  308   currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
 
  309   if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
 
  311     closestStop = mGradient.
count() - 1;
 
  323     if ( closestStop >= 0 )
 
  334   if ( e->buttons() & Qt::LeftButton )
 
  337     double offset = pointToRelativePosition( e->pos().x() );
 
  339     mSelectedStop = mStops.length();
 
  349   if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
 
  355   else if ( e->key() == Qt::Key_Left ||  e->key() == Qt::Key_Right )
 
  357     if ( selectedStopIsMovable() )
 
  362       if ( e->modifiers() & Qt::ShiftModifier )
 
  365       if ( e->key() == Qt::Key_Left )
 
  368       mStops[ mSelectedStop - 1 ].offset = std::clamp( mStops[ mSelectedStop - 1 ].offset + offsetDiff, 0.0, 1.0 );
 
  377   QWidget::keyPressEvent( e );
 
  380 QPixmap QgsGradientStopEditor::transparentBackground()
 
  382   static QPixmap sTranspBkgrd;
 
  384   if ( sTranspBkgrd.isNull() )
 
  390 void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle, 
const QColor &color, 
bool selected )
 
  393   painter.setRenderHint( QPainter::Antialiasing );
 
  394   painter.setBrush( selected ?  QColor( 150, 150, 150 ) : Qt::white );
 
  395   painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
 
  397   painter.translate( std::round( topMiddle.x() - 
MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
 
  398   painter.drawPolygon( sOuterTriangle );
 
  401   painter.setBrush( QBrush( transparentBackground() ) );
 
  402   painter.setPen( Qt::NoPen );
 
  403   painter.drawPolygon( sInnerTriangle );
 
  406   painter.setBrush( color );
 
  407   painter.drawPolygon( sInnerTriangle );
 
  410 double QgsGradientStopEditor::pointToRelativePosition( 
int x )
 const 
  417   else if ( x >= right )
 
  420   return static_cast< double >( x - left ) / ( right - left );
 
  423 int QgsGradientStopEditor::relativePositionToPoint( 
double position )
 const 
  430   else if ( position >= 1.0 )
 
  433   return left + ( right - left ) * position;
 
  436 bool QgsGradientStopEditor::selectedStopIsMovable()
 const 
  439   return mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1;
 
  449   if ( mimeColor.isValid() )
 
  452     e->acceptProposedAction();
 
  459   bool hasAlpha = 
false;
 
  462   if ( mimeColor.isValid() )
 
  465     e->acceptProposedAction();
 
  468     double offset = pointToRelativePosition( e->pos().x() );
 
  470     mSelectedStop = mStops.length();
 
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.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
void setColor1(const QColor &color)
Sets the gradient start color.
void setColor2(const QColor &color)
Sets the gradient end color.
int count() const override
Returns number of defined colors, or -1 if undefined.
QColor color(double value) const override
Returns the color corresponding to a specified value.
void setStops(const QgsGradientStopsList &stops)
Sets the list of intermediate gradient stops for the ramp.
QColor color1() const
Returns the gradient start color.
QgsGradientStopsList stops() const
Returns the list of intermediate gradient stops for the ramp.
QColor color2() const
Returns the gradient end color.
void setSelectedStopOffset(double offset)
Sets the offset for the current selected stop.
void setColor2(const QColor &color)
Sets the color for the last stop.
void setSelectedStopColor(const QColor &color)
Sets the color for the current selected stop.
void changed()
Emitted when the gradient ramp is changed by a user.
void mousePressEvent(QMouseEvent *event) override
void mouseDoubleClickEvent(QMouseEvent *event) override
QgsGradientStop selectedStop() const
Returns details about the currently selected stop.
void keyPressEvent(QKeyEvent *event) override
void setSelectedStopDetails(const QColor &color, double offset)
Sets the color and offset for the current selected stop.
void deleteSelectedStop()
Deletes the current selected stop.
void paintEvent(QPaintEvent *event) override
void selectStop(int index)
Sets the currently selected stop.
QSize sizeHint() const override
void setColor1(const QColor &color)
Sets the color for the first stop.
void selectedStopChanged(const QgsGradientStop &stop)
Emitted when the current selected stop changes.
QgsGradientStopEditor(QWidget *parent=nullptr, QgsGradientColorRamp *ramp=nullptr)
Constructor for QgsGradientStopEditor.
void dropEvent(QDropEvent *e) override
void mouseMoveEvent(QMouseEvent *event) override
void setGradientRamp(const QgsGradientColorRamp &ramp)
Sets the current ramp shown in the editor.
void dragEnterEvent(QDragEnterEvent *e) override
Represents a color stop within a QgsGradientColorRamp color ramp.
Scoped object for saving and restoring a QPainter object's state.
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.