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 )
184 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
186 mStops[ mSelectedStop - 1 ].color = color;
189 else if ( mSelectedStop == 0 )
203 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
205 mStops[ mSelectedStop - 1 ].offset = offset;
214 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
216 mStops[ mSelectedStop - 1 ].setColorSpec( spec );
221 else if ( mSelectedStop == mGradient.
count() - 1 )
231 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
233 mStops[ mSelectedStop - 1 ].setDirection( direction );
238 else if ( mSelectedStop == mGradient.
count() - 1 )
248 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
250 mStops[ mSelectedStop - 1 ].color = color;
251 mStops[ mSelectedStop - 1 ].offset = offset;
254 else if ( mSelectedStop == 0 )
269 if ( selectedStopIsMovable() )
272 double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
273 mStops.removeAt( mSelectedStop - 1 );
276 int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
300 if ( e->buttons() & Qt::LeftButton )
302 if ( selectedStopIsMovable() )
304 double offset = pointToRelativePosition( e->pos().x() );
308 mStops[ mSelectedStop - 1 ].offset = offset;
318 int QgsGradientStopEditor::findClosestStop(
int x,
int threshold )
const
320 int closestStop = -1;
321 int closestDiff = std::numeric_limits<int>::max();
322 int currentDiff = std::numeric_limits<int>::max();
328 const auto constStops = mGradient.
stops();
331 currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
332 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
335 closestDiff = currentDiff;
341 currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
342 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
345 closestDiff = currentDiff;
349 currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
350 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
352 closestStop = mGradient.
count() - 1;
364 if ( closestStop >= 0 )
375 if ( e->buttons() & Qt::LeftButton )
378 double offset = pointToRelativePosition( e->pos().x() );
380 mSelectedStop = mStops.length();
390 if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
396 else if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
398 if ( selectedStopIsMovable() )
403 if ( e->modifiers() & Qt::ShiftModifier )
406 if ( e->key() == Qt::Key_Left )
409 mStops[ mSelectedStop - 1 ].offset = std::clamp( mStops[ mSelectedStop - 1 ].offset + offsetDiff, 0.0, 1.0 );
418 QWidget::keyPressEvent( e );
421 QPixmap QgsGradientStopEditor::transparentBackground()
423 static QPixmap sTranspBkgrd;
425 if ( sTranspBkgrd.isNull() )
431 void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle,
const QColor &color,
bool selected )
434 painter.setRenderHint( QPainter::Antialiasing );
435 painter.setBrush( selected ? QColor( 150, 150, 150 ) : Qt::white );
436 painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
438 painter.translate( std::round( topMiddle.x() -
MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
439 painter.drawPolygon( sOuterTriangle );
442 painter.setBrush( QBrush( transparentBackground() ) );
443 painter.setPen( Qt::NoPen );
444 painter.drawPolygon( sInnerTriangle );
447 painter.setBrush( color );
448 painter.drawPolygon( sInnerTriangle );
451 double QgsGradientStopEditor::pointToRelativePosition(
int x )
const
458 else if ( x >= right )
461 return static_cast< double >( x - left ) / ( right - left );
464 int QgsGradientStopEditor::relativePositionToPoint(
double position )
const
471 else if ( position >= 1.0 )
474 return left + ( right - left ) * position;
477 bool QgsGradientStopEditor::selectedStopIsMovable()
const
480 return mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1;
490 if ( mimeColor.isValid() )
493 e->acceptProposedAction();
500 bool hasAlpha =
false;
503 if ( mimeColor.isValid() )
506 e->acceptProposedAction();
509 double offset = pointToRelativePosition( e->pos().x() );
511 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.