23#include "moc_qgsgradientstopeditor.cpp"
25#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
26#include <QStyleOptionFrameV3>
28#include <QStyleOptionFrame>
37 mStops = mGradient.
stops();
39 if ( sOuterTriangle.isEmpty() )
41 sOuterTriangle << QPointF( 0, MARKER_HEIGHT ) << QPointF( MARKER_WIDTH, MARKER_HEIGHT )
42 << QPointF( MARKER_WIDTH, MARKER_WIDTH / 2.0 )
43 << QPointF( MARKER_WIDTH / 2.0, 0 )
44 << QPointF( 0, MARKER_WIDTH / 2.0 )
45 << QPointF( 0, MARKER_HEIGHT );
47 if ( sInnerTriangle.isEmpty() )
49 sInnerTriangle << QPointF( MARKER_GAP, MARKER_HEIGHT - MARKER_GAP ) << QPointF( MARKER_WIDTH - MARKER_GAP, MARKER_HEIGHT - MARKER_GAP )
50 << QPointF( MARKER_WIDTH - MARKER_GAP, MARKER_WIDTH / 2.0 + 1 )
51 << QPointF( MARKER_WIDTH / 2.0, MARKER_GAP )
52 << QPointF( MARKER_GAP, MARKER_WIDTH / 2.0 + 1 )
53 << QPointF( MARKER_GAP, MARKER_HEIGHT - MARKER_GAP );
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(), rect().width() - 2 * MARGIN_X, rect().height() - MARGIN_BOTTOM );
83 QStyleOptionFrame option;
84 option.initFrom(
this );
85 option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
86 option.rect = frameRect;
87 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
92 QStyleOptionFocusRect option;
93 option.initFrom(
this );
94 option.state = QStyle::State_KeyboardFocusChange;
95 option.rect = frameRect;
96 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
100 QBrush checkBrush = QBrush( transparentBackground() );
101 painter.setBrush( checkBrush );
102 painter.setPen( Qt::NoPen );
104 QRect box( frameRect.x() + FRAME_MARGIN_PX, frameRect.y() + FRAME_MARGIN_PX, frameRect.width() - 2 * FRAME_MARGIN_PX, frameRect.height() - 2 * FRAME_MARGIN_PX );
106 painter.drawRect( box );
109 for (
int i = 0; i < box.width() + 1; ++i )
111 QPen pen( mGradient.color(
static_cast<double>( i ) / box.width() ) );
112 painter.setPen( pen );
113 painter.drawLine( box.left() + i, box.top(), box.left() + i, box.height() + 1 );
117 int markerTop = frameRect.bottom() + 1;
118 drawStopMarker( painter, QPoint( box.left(), markerTop ), mGradient.color1(), mSelectedStop == 0 );
119 drawStopMarker( painter, QPoint( box.right(), markerTop ), mGradient.color2(), mSelectedStop == mGradient.count() - 1 );
121 const auto constMStops = mStops;
124 int x = stop.offset * box.width() + box.left();
125 drawStopMarker( painter, QPoint( x, markerTop ), stop.color, mSelectedStop == i );
134 if ( index > 0 && index < mGradient.count() - 1 )
139 const auto constMStops = mStops;
150 mSelectedStop = index;
157 if ( mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1 )
159 return mStops.at( mSelectedStop - 1 );
161 else if ( mSelectedStop == 0 )
176 if ( mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1 )
178 mStops[mSelectedStop - 1].color = color;
179 mGradient.setStops( mStops );
181 else if ( mSelectedStop == 0 )
183 mGradient.setColor1( color );
187 mGradient.setColor2( color );
195 if ( mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1 )
197 mStops[mSelectedStop - 1].offset = offset;
198 mGradient.setStops( mStops );
206 if ( mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1 )
208 mStops[mSelectedStop - 1].setColorSpec( spec );
209 mGradient.setStops( mStops );
213 else if ( mSelectedStop == mGradient.count() - 1 )
215 mGradient.setColorSpec( spec );
223 if ( mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1 )
225 mStops[mSelectedStop - 1].setDirection( direction );
226 mGradient.setStops( mStops );
230 else if ( mSelectedStop == mGradient.count() - 1 )
232 mGradient.setDirection( direction );
240 if ( mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1 )
242 mStops[mSelectedStop - 1].color = color;
243 mStops[mSelectedStop - 1].offset = offset;
244 mGradient.setStops( mStops );
246 else if ( mSelectedStop == 0 )
248 mGradient.setColor1( color );
252 mGradient.setColor2( color );
261 if ( selectedStopIsMovable() )
264 double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
265 mStops.removeAt( mSelectedStop - 1 );
266 mGradient.setStops( mStops );
268 int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
278 mGradient.setColor1( color );
285 mGradient.setColor2( color );
292 if ( e->buttons() & Qt::LeftButton )
294 if ( selectedStopIsMovable() )
296 double offset = pointToRelativePosition( e->pos().x() );
300 mStops[mSelectedStop - 1].offset = offset;
302 mGradient.setStops( mStops );
310int QgsGradientStopEditor::findClosestStop(
int x,
int threshold )
const
312 int closestStop = -1;
313 int closestDiff = std::numeric_limits<int>::max();
314 int currentDiff = std::numeric_limits<int>::max();
320 const auto constStops = mGradient.
stops();
323 currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
324 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
327 closestDiff = currentDiff;
333 currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
334 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
337 closestDiff = currentDiff;
341 currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
342 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
344 closestStop = mGradient.count() - 1;
352 if ( e->pos().y() >= rect().height() - MARGIN_BOTTOM - 1 )
355 int closestStop = findClosestStop( e->pos().x(), CLICK_THRESHOLD );
356 if ( closestStop >= 0 )
367 if ( e->buttons() & Qt::LeftButton )
370 double offset = pointToRelativePosition( e->pos().x() );
372 mSelectedStop = mStops.length();
373 mGradient.setStops( mStops );
382 if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
388 else if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
390 if ( selectedStopIsMovable() )
393 double offsetDiff = pointToRelativePosition( rect().x() + MARGIN_X + FRAME_MARGIN_PX + 2 ) - pointToRelativePosition( rect().x() + MARGIN_X + FRAME_MARGIN_PX + 1 );
395 if ( e->modifiers() & Qt::ShiftModifier )
398 if ( e->key() == Qt::Key_Left )
401 mStops[mSelectedStop - 1].offset = std::clamp( mStops[mSelectedStop - 1].offset + offsetDiff, 0.0, 1.0 );
402 mGradient.setStops( mStops );
410 QWidget::keyPressEvent( e );
413QPixmap QgsGradientStopEditor::transparentBackground()
415 static QPixmap sTranspBkgrd;
417 if ( sTranspBkgrd.isNull() )
423void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle,
const QColor &color,
bool selected )
425 QgsScopedQPainterState painterState( &painter );
426 painter.setRenderHint( QPainter::Antialiasing );
427 painter.setBrush( selected ? QColor( 150, 150, 150 ) : Qt::white );
428 painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
430 painter.translate( std::round( topMiddle.x() - MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
431 painter.drawPolygon( sOuterTriangle );
434 painter.setBrush( QBrush( transparentBackground() ) );
435 painter.setPen( Qt::NoPen );
436 painter.drawPolygon( sInnerTriangle );
439 painter.setBrush( color );
440 painter.drawPolygon( sInnerTriangle );
443double QgsGradientStopEditor::pointToRelativePosition(
int x )
const
445 int left = rect().x() + MARGIN_X + FRAME_MARGIN_PX;
446 int right = left + rect().width() - 2 * MARGIN_X - 2 * FRAME_MARGIN_PX;
450 else if ( x >= right )
453 return static_cast<double>( x - left ) / ( right - left );
456int QgsGradientStopEditor::relativePositionToPoint(
double position )
const
458 int left = rect().x() + MARGIN_X + FRAME_MARGIN_PX;
459 int right = left + rect().width() - 2 * MARGIN_X - 2 * FRAME_MARGIN_PX;
463 else if ( position >= 1.0 )
466 return left + ( right - left ) * position;
469bool QgsGradientStopEditor::selectedStopIsMovable()
const
472 return mSelectedStop > 0 && mSelectedStop < mGradient.count() - 1;
482 if ( mimeColor.isValid() )
485 e->acceptProposedAction();
492 bool hasAlpha =
false;
495 if ( mimeColor.isValid() )
498 e->acceptProposedAction();
501 double offset = pointToRelativePosition( e->pos().x() );
503 mSelectedStop = mStops.length();
504 mGradient.setStops( mStops );
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 ...
QgsGradientStopsList stops() const
Returns the list of intermediate gradient stops for the ramp.
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...
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.