21 #include <QStyleOptionFrameV3>
22 #include <QMouseEvent>
24 #define MARKER_WIDTH 11
25 #define MARKER_HEIGHT 14
26 #define MARKER_GAP 1.5
27 #define MARGIN_BOTTOM ( MARKER_HEIGHT + 2 )
28 #define MARGIN_X ( MARKER_WIDTH / 2 )
29 #define FRAME_MARGIN 2
30 #define CLICK_THRESHOLD ( MARKER_WIDTH / 2 + 3 )
37 mStops = mGradient.
stops();
39 if ( sOuterTriangle.isEmpty() )
47 if ( sInnerTriangle.isEmpty() )
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(),
85 QStyleOptionFrame option;
86 option.initFrom(
this );
87 option.state = hasFocus() ? QStyle::State_KeyboardFocusChange : QStyle::State_None;
88 option.rect = frameRect;
89 style()->drawPrimitive( QStyle::PE_Frame, &option, &painter );
94 QStyleOptionFocusRect option;
95 option.initFrom(
this );
96 option.state = QStyle::State_KeyboardFocusChange;
97 option.rect = frameRect;
98 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
102 QBrush checkBrush = QBrush( transparentBackground() );
103 painter.setBrush( checkBrush );
104 painter.setPen( Qt::NoPen );
110 painter.drawRect( box );
113 for (
int i = 0; i < box.width() + 1; ++i )
115 QPen pen( mGradient.
color(
static_cast< double >( i ) / box.width() ) );
116 painter.setPen( pen );
117 painter.drawLine( box.left() + i, box.top(), box.left() + i, box.height() + 1 );
121 int markerTop = frameRect.bottom() + 1;
122 drawStopMarker( painter, QPoint( box.left(), markerTop ), mGradient.
color1(), mSelectedStop == 0 );
123 drawStopMarker( painter, QPoint( box.right(), markerTop ), mGradient.
color2(), mSelectedStop == mGradient.
count() - 1 );
125 const auto constMStops = mStops;
128 int x = stop.offset * box.width() + box.left();
129 drawStopMarker( painter, QPoint( x, markerTop ), stop.color, mSelectedStop == i );
138 if ( index > 0 && index < mGradient.
count() - 1 )
143 const auto constMStops = mStops;
154 mSelectedStop = index;
161 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
163 return mStops.at( mSelectedStop - 1 );
165 else if ( mSelectedStop == 0 )
177 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
179 mStops[ mSelectedStop - 1 ].color = color;
182 else if ( mSelectedStop == 0 )
196 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
198 mStops[ mSelectedStop - 1 ].offset = offset;
207 if ( mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1 )
209 mStops[ mSelectedStop - 1 ].color = color;
210 mStops[ mSelectedStop - 1 ].offset = offset;
213 else if ( mSelectedStop == 0 )
228 if ( selectedStopIsMovable() )
231 double stopOffset = mStops.at( mSelectedStop - 1 ).offset;
232 mStops.removeAt( mSelectedStop - 1 );
235 int closest = findClosestStop( relativePositionToPoint( stopOffset ) );
259 if ( e->buttons() & Qt::LeftButton )
261 if ( selectedStopIsMovable() )
263 double offset = pointToRelativePosition( e->pos().x() );
267 mStops[ mSelectedStop - 1 ].offset = offset;
277 int QgsGradientStopEditor::findClosestStop(
int x,
int threshold )
const
279 int closestStop = -1;
280 int closestDiff = std::numeric_limits<int>::max();
281 int currentDiff = std::numeric_limits<int>::max();
287 const auto constStops = mGradient.
stops();
290 currentDiff = std::abs( relativePositionToPoint( stop.offset ) + 1 - x );
291 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
294 closestDiff = currentDiff;
300 currentDiff = std::abs( relativePositionToPoint( 0.0 ) + 1 - x );
301 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
304 closestDiff = currentDiff;
308 currentDiff = std::abs( relativePositionToPoint( 1.0 ) + 1 - x );
309 if ( ( threshold < 0 || currentDiff < threshold ) && currentDiff < closestDiff )
311 closestStop = mGradient.
count() - 1;
323 if ( closestStop >= 0 )
334 if ( e->buttons() & Qt::LeftButton )
337 double offset = pointToRelativePosition( e->pos().x() );
339 mSelectedStop = mStops.length();
349 if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
355 else if ( e->key() == Qt::Key_Left || e->key() == Qt::Key_Right )
357 if ( selectedStopIsMovable() )
362 if ( e->modifiers() & Qt::ShiftModifier )
365 if ( e->key() == Qt::Key_Left )
368 mStops[ mSelectedStop - 1 ].offset = qBound( 0.0, mStops[ mSelectedStop - 1 ].offset + offsetDiff, 1.0 );
377 QWidget::keyPressEvent( e );
380 QPixmap QgsGradientStopEditor::transparentBackground()
382 static QPixmap sTranspBkgrd;
384 if ( sTranspBkgrd.isNull() )
390 void QgsGradientStopEditor::drawStopMarker( QPainter &painter, QPoint topMiddle,
const QColor &color,
bool selected )
393 painter.setRenderHint( QPainter::Antialiasing );
394 painter.setBrush( selected ? QColor( 150, 150, 150 ) : Qt::white );
395 painter.setPen( selected ? Qt::black : QColor( 150, 150, 150 ) );
397 painter.translate( std::round( topMiddle.x() -
MARKER_WIDTH / 2.0 ) + 0.5, topMiddle.y() + 0.5 );
398 painter.drawPolygon( sOuterTriangle );
401 painter.setBrush( QBrush( transparentBackground() ) );
402 painter.setPen( Qt::NoPen );
403 painter.drawPolygon( sInnerTriangle );
406 painter.setBrush( color );
407 painter.drawPolygon( sInnerTriangle );
410 double QgsGradientStopEditor::pointToRelativePosition(
int x )
const
417 else if ( x >= right )
420 return static_cast< double >( x - left ) / ( right - left );
423 int QgsGradientStopEditor::relativePositionToPoint(
double position )
const
430 else if ( position >= 1.0 )
433 return left + ( right - left ) * position;
436 bool QgsGradientStopEditor::selectedStopIsMovable()
const
439 return mSelectedStop > 0 && mSelectedStop < mGradient.
count() - 1;
449 if ( mimeColor.isValid() )
452 e->acceptProposedAction();
459 bool hasAlpha =
false;
462 if ( mimeColor.isValid() )
465 e->acceptProposedAction();
468 double offset = pointToRelativePosition( e->pos().x() );
470 mSelectedStop = mStops.length();