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();