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 );
88 QStyleOptionFrame option;
89 option.initFrom(
this );
90 option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
91 option.rect = frameRect;
92 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
97 QStyleOptionFocusRect option;
98 option.initFrom(
this );
99 option.state = QStyle::State_KeyboardFocusChange;
100 option.rect = frameRect;
101 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
105 QBrush checkBrush = QBrush( transparentBackground() );
106 painter.setBrush( checkBrush );
107 painter.setPen( Qt::NoPen );
111 painter.drawRect( box );
114 for (
int i = 0; i < box.width() + 1; ++i )
116 QPen pen( mGradient.
color(
static_cast<double>( i ) / box.width() ) );
117 painter.setPen( pen );
118 painter.drawLine( box.left() + i, box.top(), box.left() + i, box.height() + 1 );
122 int markerTop = frameRect.bottom() + 1;
123 drawStopMarker( painter, QPoint( box.left(), markerTop ), mGradient.
color1(), mSelectedStop == 0 );
124 drawStopMarker( painter, QPoint( box.right(), markerTop ), mGradient.
color2(), mSelectedStop == mGradient.
count() - 1 );
126 const auto constMStops = mStops;
129 int x = stop.offset * box.width() + box.left();
130 drawStopMarker( painter, QPoint( x, markerTop ), stop.color, mSelectedStop == i );
139 if ( index > 0 && index < mGradient.
count() - 1 )
144 const auto constMStops = mStops;
155 mSelectedStop = index;
162 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
164 return mStops.at( mSelectedStop - 1 );
166 else if ( mSelectedStop == 0 )
181 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
183 mStops[mSelectedStop - 1].color = color;
186 else if ( mSelectedStop == 0 )
200 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
202 mStops[mSelectedStop - 1].offset = offset;
211 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
213 mStops[mSelectedStop - 1].setColorSpec( spec );
218 else if ( mSelectedStop == mGradient.
count() - 1 )
228 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
230 mStops[mSelectedStop - 1].setDirection( direction );
235 else if ( mSelectedStop == mGradient.
count() - 1 )
245 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
247 mStops[mSelectedStop - 1].color = color;
248 mStops[mSelectedStop - 1].offset = offset;
251 else if ( mSelectedStop == 0 )
266 if ( selectedStopIsMovable() )
269 double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
270 mStops.removeAt( mSelectedStop - 1 );
273 int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
297 if ( e->buttons() & Qt::LeftButton )
299 if ( selectedStopIsMovable() )
301 double offset = pointToRelativePosition( e->pos().x() );
305 mStops[mSelectedStop - 1].offset = offset;
315int QgsGradientStopEditor::findClosestStop(
int x,
int threshold )
const
317 int closestStop = -1;
318 int closestDiff = std::numeric_limits<int>::max();
319 int currentDiff = std::numeric_limits<int>::max();
325 const auto constStops = mGradient.
stops();
328 currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
329 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
332 closestDiff = currentDiff;
338 currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
339 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
342 closestDiff = currentDiff;
346 currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
347 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
349 closestStop = mGradient.
count() - 1;
361 if ( closestStop >= 0 )
372 if ( e->buttons() & Qt::LeftButton )
375 double offset = pointToRelativePosition( e->pos().x() );
377 mSelectedStop = mStops.length();
387 if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
393 else if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
395 if ( selectedStopIsMovable() )
400 if ( e->modifiers() & Qt::ShiftModifier )
403 if ( e->key() == Qt::Key_Left )
406 mStops[mSelectedStop - 1].offset = std::clamp( mStops[mSelectedStop - 1].offset + offsetDiff, 0.0, 1.0 );
415 QWidget::keyPressEvent( e );
418QPixmap QgsGradientStopEditor::transparentBackground()
420 static QPixmap sTranspBkgrd;
422 if ( sTranspBkgrd.isNull() )
428void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle,
const QColor &color,
bool selected )
431 painter.setRenderHint( QPainter::Antialiasing );
432 painter.setBrush( selected ? QColor( 150, 150, 150 ) : Qt::white );
433 painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
435 painter.translate( std::round( topMiddle.x() -
MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
436 painter.drawPolygon( sOuterTriangle );
439 painter.setBrush( QBrush( transparentBackground() ) );
440 painter.setPen( Qt::NoPen );
441 painter.drawPolygon( sInnerTriangle );
444 painter.setBrush( color );
445 painter.drawPolygon( sInnerTriangle );
448double QgsGradientStopEditor::pointToRelativePosition(
int x )
const
455 else if ( x >= right )
458 return static_cast<double>( x - left ) / ( right - left );
461int QgsGradientStopEditor::relativePositionToPoint(
double position )
const
468 else if ( position >= 1.0 )
471 return left + ( right - left ) * position;
474bool QgsGradientStopEditor::selectedStopIsMovable()
const
477 return mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1;
487 if ( mimeColor.isValid() )
490 e->acceptProposedAction();
497 bool hasAlpha =
false;
500 if ( mimeColor.isValid() )
503 e->acceptProposedAction();
506 double offset = pointToRelativePosition( e->pos().x() );
508 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.