21 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
22 #include <QStyleOptionFrameV3>
24 #include <QStyleOptionFrame>
26 #include <QMouseEvent>
28 #define MARKER_WIDTH 11
29 #define MARKER_HEIGHT 14
30 #define MARKER_GAP 1.5
31 #define MARGIN_BOTTOM ( MARKER_HEIGHT + 2 )
32 #define MARGIN_X ( MARKER_WIDTH / 2 )
33 #define FRAME_MARGIN 2
34 #define CLICK_THRESHOLD ( MARKER_WIDTH / 2 + 3 )
41 mStops = mGradient.
stops();
43 if ( sOuterTriangle.isEmpty() )
51 if ( sInnerTriangle.isEmpty() )
60 setFocusPolicy( Qt::StrongFocus );
61 setAcceptDrops(
true );
67 mStops = mGradient.
stops();
76 return QSize( 200, 80 );
82 QPainter painter(
this );
84 QRect frameRect( rect().x() +
MARGIN_X, rect().y(),
89 QStyleOptionFrame option;
90 option.initFrom(
this );
91 option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
92 option.rect = frameRect;
93 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
98 QStyleOptionFocusRect option;
99 option.initFrom(
this );
100 option.state = QStyle::State_KeyboardFocusChange;
101 option.rect = frameRect;
102 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
106 QBrush checkBrush = QBrush( transparentBackground() );
107 painter.setBrush( checkBrush );
108 painter.setPen( Qt::NoPen );
114 painter.drawRect( box );
117 for (
int i = 0; i < box.width() + 1; ++i )
119 QPen pen( mGradient.
color(
static_cast< double >( i ) / box.width() ) );
120 painter.setPen( pen );
121 painter.drawLine( box.left() + i, box.top(), box.left() + i, box.height() + 1 );
125 int markerTop = frameRect.bottom() + 1;
126 drawStopMarker( painter, QPoint( box.left(), markerTop ), mGradient.
color1(), mSelectedStop == 0 );
127 drawStopMarker( painter, QPoint( box.right(), markerTop ), mGradient.
color2(), mSelectedStop == mGradient.
count() - 1 );
129 const auto constMStops = mStops;
132 int x = stop.offset * box.width() + box.left();
133 drawStopMarker( painter, QPoint( x, markerTop ), stop.color, mSelectedStop == i );
142 if ( index > 0 && index < mGradient.
count() - 1 )
147 const auto constMStops = mStops;
158 mSelectedStop = index;
165 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
167 return mStops.at( mSelectedStop - 1 );
169 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 ].color = color;
214 mStops[ mSelectedStop - 1 ].offset = offset;
217 else if ( mSelectedStop == 0 )
232 if ( selectedStopIsMovable() )
235 double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
236 mStops.removeAt( mSelectedStop - 1 );
239 int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
263 if ( e->buttons() & Qt::LeftButton )
265 if ( selectedStopIsMovable() )
267 double offset = pointToRelativePosition( e->pos().x() );
271 mStops[ mSelectedStop - 1 ].offset = offset;
281 int QgsGradientStopEditor::findClosestStop(
int x,
int threshold )
const
283 int closestStop = -1;
284 int closestDiff = std::numeric_limits<int>::max();
285 int currentDiff = std::numeric_limits<int>::max();
291 const auto constStops = mGradient.
stops();
294 currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
295 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
298 closestDiff = currentDiff;
304 currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
305 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
308 closestDiff = currentDiff;
312 currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
313 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
315 closestStop = mGradient.
count() - 1;
327 if ( closestStop >= 0 )
338 if ( e->buttons() & Qt::LeftButton )
341 double offset = pointToRelativePosition( e->pos().x() );
343 mSelectedStop = mStops.length();
353 if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
359 else if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
361 if ( selectedStopIsMovable() )
366 if ( e->modifiers() & Qt::ShiftModifier )
369 if ( e->key() == Qt::Key_Left )
372 mStops[ mSelectedStop - 1 ].offset = std::clamp( mStops[ mSelectedStop - 1 ].offset + offsetDiff, 0.0, 1.0 );
381 QWidget::keyPressEvent( e );
384 QPixmap QgsGradientStopEditor::transparentBackground()
386 static QPixmap sTranspBkgrd;
388 if ( sTranspBkgrd.isNull() )
394 void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle,
const QColor &color,
bool selected )
397 painter.setRenderHint( QPainter::Antialiasing );
398 painter.setBrush( selected ? QColor( 150, 150, 150 ) : Qt::white );
399 painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
401 painter.translate( std::round( topMiddle.x() -
MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
402 painter.drawPolygon( sOuterTriangle );
405 painter.setBrush( QBrush( transparentBackground() ) );
406 painter.setPen( Qt::NoPen );
407 painter.drawPolygon( sInnerTriangle );
410 painter.setBrush( color );
411 painter.drawPolygon( sInnerTriangle );
414 double QgsGradientStopEditor::pointToRelativePosition(
int x )
const
421 else if ( x >= right )
424 return static_cast< double >( x - left ) / ( right - left );
427 int QgsGradientStopEditor::relativePositionToPoint(
double position )
const
434 else if ( position >= 1.0 )
437 return left + ( right - left ) * position;
440 bool QgsGradientStopEditor::selectedStopIsMovable()
const
443 return mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1;
453 if ( mimeColor.isValid() )
456 e->acceptProposedAction();
463 bool hasAlpha =
false;
466 if ( mimeColor.isValid() )
469 e->acceptProposedAction();
472 double offset = pointToRelativePosition( e->pos().x() );
474 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.