17#include "moc_qgsgradientstopeditor.cpp"
22#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
23#include <QStyleOptionFrameV3>
25#include <QStyleOptionFrame>
29#define MARKER_WIDTH 11
30#define MARKER_HEIGHT 14
32#define MARGIN_BOTTOM ( MARKER_HEIGHT + 2 )
33#define MARGIN_X ( MARKER_WIDTH / 2 )
35#define CLICK_THRESHOLD ( MARKER_WIDTH / 2 + 3 )
42 mStops = mGradient.
stops();
44 if ( sOuterTriangle.isEmpty() )
52 if ( sInnerTriangle.isEmpty() )
61 setFocusPolicy( Qt::StrongFocus );
62 setAcceptDrops(
true );
68 mStops = mGradient.
stops();
77 return QSize( 200, 80 );
83 QPainter painter(
this );
85 QRect frameRect( rect().x() +
MARGIN_X, rect().y(),
90 QStyleOptionFrame option;
91 option.initFrom(
this );
92 option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
93 option.rect = frameRect;
94 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
99 QStyleOptionFocusRect option;
100 option.initFrom(
this );
101 option.state = QStyle::State_KeyboardFocusChange;
102 option.rect = frameRect;
103 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
107 QBrush checkBrush = QBrush( transparentBackground() );
108 painter.setBrush( checkBrush );
109 painter.setPen( Qt::NoPen );
115 painter.drawRect( box );
118 for (
int i = 0; i < box.width() + 1; ++i )
120 QPen pen( mGradient.
color(
static_cast< double >( i ) / box.width() ) );
121 painter.setPen( pen );
122 painter.drawLine( box.left() + i, box.top(), box.left() + i, box.height() + 1 );
126 int markerTop = frameRect.bottom() + 1;
127 drawStopMarker( painter, QPoint( box.left(), markerTop ), mGradient.
color1(), mSelectedStop == 0 );
128 drawStopMarker( painter, QPoint( box.right(), markerTop ), mGradient.
color2(), mSelectedStop == mGradient.
count() - 1 );
130 const auto constMStops = mStops;
133 int x = stop.offset * box.width() + box.left();
134 drawStopMarker( painter, QPoint( x, markerTop ), stop.color, mSelectedStop == i );
143 if ( index > 0 && index < mGradient.
count() - 1 )
148 const auto constMStops = mStops;
159 mSelectedStop = index;
166 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
168 return mStops.at( mSelectedStop - 1 );
170 else if ( mSelectedStop == 0 )
185 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
187 mStops[ mSelectedStop - 1 ].color = color;
190 else if ( mSelectedStop == 0 )
204 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
206 mStops[ mSelectedStop - 1 ].offset = offset;
215 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
217 mStops[ mSelectedStop - 1 ].setColorSpec( spec );
222 else if ( mSelectedStop == mGradient.
count() - 1 )
232 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
234 mStops[ mSelectedStop - 1 ].setDirection( direction );
239 else if ( mSelectedStop == mGradient.
count() - 1 )
249 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
251 mStops[ mSelectedStop - 1 ].color = color;
252 mStops[ mSelectedStop - 1 ].offset = offset;
255 else if ( mSelectedStop == 0 )
270 if ( selectedStopIsMovable() )
273 double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
274 mStops.removeAt( mSelectedStop - 1 );
277 int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
301 if ( e->buttons() & Qt::LeftButton )
303 if ( selectedStopIsMovable() )
305 double offset = pointToRelativePosition( e->pos().x() );
309 mStops[ mSelectedStop - 1 ].offset = offset;
319int QgsGradientStopEditor::findClosestStop(
int x,
int threshold )
const
321 int closestStop = -1;
322 int closestDiff = std::numeric_limits<int>::max();
323 int currentDiff = std::numeric_limits<int>::max();
329 const auto constStops = mGradient.
stops();
332 currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
333 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
336 closestDiff = currentDiff;
342 currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
343 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
346 closestDiff = currentDiff;
350 currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
351 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
353 closestStop = mGradient.
count() - 1;
365 if ( closestStop >= 0 )
376 if ( e->buttons() & Qt::LeftButton )
379 double offset = pointToRelativePosition( e->pos().x() );
381 mSelectedStop = mStops.length();
391 if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
397 else if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
399 if ( selectedStopIsMovable() )
404 if ( e->modifiers() & Qt::ShiftModifier )
407 if ( e->key() == Qt::Key_Left )
410 mStops[ mSelectedStop - 1 ].offset = std::clamp( mStops[ mSelectedStop - 1 ].offset + offsetDiff, 0.0, 1.0 );
419 QWidget::keyPressEvent( e );
422QPixmap QgsGradientStopEditor::transparentBackground()
424 static QPixmap sTranspBkgrd;
426 if ( sTranspBkgrd.isNull() )
432void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle,
const QColor &color,
bool selected )
435 painter.setRenderHint( QPainter::Antialiasing );
436 painter.setBrush( selected ? QColor( 150, 150, 150 ) : Qt::white );
437 painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
439 painter.translate( std::round( topMiddle.x() -
MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
440 painter.drawPolygon( sOuterTriangle );
443 painter.setBrush( QBrush( transparentBackground() ) );
444 painter.setPen( Qt::NoPen );
445 painter.drawPolygon( sInnerTriangle );
448 painter.setBrush( color );
449 painter.drawPolygon( sInnerTriangle );
452double QgsGradientStopEditor::pointToRelativePosition(
int x )
const
459 else if ( x >= right )
462 return static_cast< double >( x - left ) / ( right - left );
465int QgsGradientStopEditor::relativePositionToPoint(
double position )
const
472 else if ( position >= 1.0 )
475 return left + ( right - left ) * position;
478bool QgsGradientStopEditor::selectedStopIsMovable()
const
481 return mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1;
491 if ( mimeColor.isValid() )
494 e->acceptProposedAction();
501 bool hasAlpha =
false;
504 if ( mimeColor.isValid() )
507 e->acceptProposedAction();
510 double offset = pointToRelativePosition( e->pos().x() );
512 mSelectedStop = mStops.length();
AngularDirection
Angular directions.
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.
void setColorSpec(QColor::Spec spec)
Sets the color specification in which the color component interpolation will occur.
int count() const override
Returns number of defined colors, or -1 if undefined.
QColor::Spec colorSpec() const
Returns the color specification in which the color component interpolation will occur.
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.
void setDirection(Qgis::AngularDirection direction)
Sets the direction to traverse the color wheel using when interpolating hue-based color specification...
Qgis::AngularDirection direction() const
Returns the direction to traverse the color wheel using when interpolating hue-based color specificat...
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
void setSelectedStopColorSpec(QColor::Spec spec)
Sets the color spec for the current selected stop.
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 setSelectedStopDirection(Qgis::AngularDirection direction)
Sets the hue angular direction for the current selected 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.
void setColorSpec(QColor::Spec spec)
Sets the color specification in which the color component interpolation will occur.
void setDirection(Qgis::AngularDirection direction)
Sets the direction to traverse the color wheel using when interpolating hue-based color specification...
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.