18 #include <QMouseEvent>
28 mStyleOption.minimum = 0;
29 mStyleOption.maximum = 100;
32 setFocusPolicy( Qt::FocusPolicy( style()->styleHint( QStyle::SH_Button_FocusPolicy ) ) );
33 QSizePolicy sp( QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::Slider );
34 if ( mStyleOption.orientation == Qt::Vertical )
37 setAttribute( Qt::WA_WState_OwnSizePolicy,
false );
39 setAttribute( Qt::WA_Hover );
40 setMouseTracking(
true );
45 return mStyleOption.maximum;
50 if ( mStyleOption.maximum ==
maximum )
54 mStyleOption.minimum = std::min(
maximum, mStyleOption.minimum );
59 mUpperValue = std::min( mUpperValue,
maximum );
60 mLowerValue = std::min( mLowerValue,
maximum );
69 return mStyleOption.minimum;
74 if ( mStyleOption.minimum ==
minimum )
77 mStyleOption.maximum = std::max(
minimum, mStyleOption.maximum );
82 mUpperValue = std::max( mUpperValue,
minimum );
83 mLowerValue = std::max( mLowerValue,
minimum );
95 if ( mStyleOption.minimum ==
minimum && mStyleOption.maximum ==
maximum )
102 if ( mUpperValue <
minimum || mLowerValue < minimum || mUpperValue >
maximum || mLowerValue >
maximum )
104 mUpperValue = std::min(
maximum, std::max( mUpperValue,
minimum ) );
105 mLowerValue = std::min(
maximum, std::max( mLowerValue,
minimum ) );
122 mLowerValue = std::min( mStyleOption.maximum, std::max( mStyleOption.minimum,
lowerValue ) );
123 mUpperValue = std::max( mLowerValue, mUpperValue );
139 mUpperValue = std::max( mStyleOption.minimum, std::min( mStyleOption.maximum,
upperValue ) );
140 mLowerValue = std::min( mLowerValue, mUpperValue );
147 if (
lower == mLowerValue && upper == mUpperValue )
151 std::swap(
lower, upper );
153 mLowerValue = std::min( mStyleOption.maximum, std::max( mStyleOption.minimum,
lower ) );
154 mUpperValue = std::min( mStyleOption.maximum, std::max( mStyleOption.minimum, upper ) );
161 switch (
event->type() )
163 case QEvent::HoverEnter:
164 case QEvent::HoverLeave:
165 case QEvent::HoverMove:
166 if (
const QHoverEvent *he =
static_cast<const QHoverEvent *
>(
event ) )
167 updateHoverControl( he->pos() );
172 return QWidget::event(
event );
175 int QgsRangeSlider::pick(
const QPoint &pt )
const
177 return mStyleOption.orientation == Qt::Horizontal ? pt.x() : pt.y();
180 int QgsRangeSlider::pixelPosToRangeValue(
int pos )
const
182 const QRect gr = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderGroove,
this );
183 const QRect sr = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
184 int sliderMin, sliderMax, sliderLength;
185 if ( mStyleOption.orientation == Qt::Horizontal )
187 sliderLength = sr.width();
189 sliderMax = gr.right() - sliderLength + 1;
193 sliderLength = sr.height();
195 sliderMax = gr.bottom() - sliderLength + 1;
198 int value = QStyle::sliderValueFromPosition( mStyleOption.minimum, mStyleOption.maximum, pos - sliderMin,
199 sliderMax - sliderMin );
201 value = mStyleOption.maximum + mStyleOption.minimum - value;
205 bool QgsRangeSlider::updateHoverControl(
const QPoint &pos )
207 const QRect lastHoverRect = mHoverRect;
208 const bool doesHover = testAttribute( Qt::WA_Hover );
209 if ( doesHover && newHoverControl( pos ) )
211 update( lastHoverRect );
212 update( mHoverRect );
218 bool QgsRangeSlider::newHoverControl(
const QPoint &pos )
220 const Control lastHoverControl = mHoverControl;
221 const QStyle::SubControl lastHoverSubControl = mHoverSubControl;
223 mStyleOption.subControls = QStyle::SC_All;
225 mStyleOption.sliderPosition = unFlippedSliderPosition( mLowerValue );
226 const QRect lowerHandleRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
227 mStyleOption.sliderPosition = unFlippedSliderPosition( mUpperValue );
228 const QRect upperHandleRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
230 const QRect grooveRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderGroove,
this );
231 const QRect tickmarksRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderTickmarks,
this );
232 if ( lowerHandleRect.contains( pos ) )
234 mHoverRect = lowerHandleRect;
235 mHoverControl = Lower;
236 mHoverSubControl = QStyle::SC_SliderHandle;
237 setCursor( Qt::OpenHandCursor );
239 else if ( upperHandleRect.contains( pos ) )
241 mHoverRect = upperHandleRect;
242 mHoverControl = Upper;
243 mHoverSubControl = QStyle::SC_SliderHandle;
244 setCursor( Qt::OpenHandCursor );
246 else if ( grooveRect.contains( pos ) )
248 mHoverRect = grooveRect;
249 mHoverControl =
None;
250 mHoverSubControl = QStyle::SC_SliderGroove;
252 if ( selectedRangeRect().contains( pos ) )
253 setCursor( Qt::OpenHandCursor );
257 else if ( tickmarksRect.contains( pos ) )
259 mHoverRect = tickmarksRect;
260 mHoverControl =
None;
261 mHoverSubControl = QStyle::SC_SliderTickmarks;
266 mHoverRect = QRect();
267 mHoverControl =
None;
268 mHoverSubControl = QStyle::SC_None;
271 return mHoverSubControl != lastHoverSubControl || mHoverControl != lastHoverControl;
274 QRect QgsRangeSlider::selectedRangeRect()
278 mStyleOption.activeSubControls = mHoverControl == Lower || mActiveControl == Lower ? QStyle::SC_SliderHandle : QStyle::SC_None;
279 mStyleOption.sliderPosition = unFlippedSliderPosition( mLowerValue );
280 const QRect lowerHandleRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
nullptr );
282 mStyleOption.activeSubControls = mHoverControl == Upper || mActiveControl == Lower ? QStyle::SC_SliderHandle : QStyle::SC_None;
283 mStyleOption.sliderPosition = unFlippedSliderPosition( mUpperValue );
284 const QRect upperHandleRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
nullptr );
286 const QRect grooveRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderGroove,
nullptr );
288 switch ( mStyleOption.orientation )
291 selectionRect = mFlipped ? QRect( upperHandleRect.right(),
293 lowerHandleRect.left() - upperHandleRect.right(),
296 : QRect( lowerHandleRect.right(),
298 upperHandleRect.left() - lowerHandleRect.right(),
304 selectionRect = mFlipped ? QRect( grooveRect.x(),
305 lowerHandleRect.top(),
307 upperHandleRect.bottom() - lowerHandleRect.top()
309 : QRect( grooveRect.x(),
310 upperHandleRect.top(),
312 lowerHandleRect.bottom() - upperHandleRect.top()
317 return selectionRect.adjusted( -1, 1, 1, -1 );
320 void QgsRangeSlider::applyStep(
int step )
322 switch ( mFocusControl )
326 const int newLowerValue = std::min( mUpperValue, std::min( mStyleOption.maximum, std::max( mStyleOption.minimum, mLowerValue + step ) ) );
327 if ( newLowerValue != mLowerValue )
329 mLowerValue = newLowerValue;
338 const int newUpperValue = std::max( mLowerValue, std::min( mStyleOption.maximum, std::max( mStyleOption.minimum, mUpperValue + step ) ) );
339 if ( newUpperValue != mUpperValue )
341 mUpperValue = newUpperValue;
352 const int previousWidth = mUpperValue - mLowerValue;
353 const int newLowerValue = std::min( mUpperValue, std::min( mStyleOption.maximum, std::max( mStyleOption.minimum, mLowerValue + step ) ) );
354 if ( newLowerValue != mLowerValue )
356 mLowerValue = newLowerValue;
357 mUpperValue = std::min( mStyleOption.maximum, mLowerValue + previousWidth );
364 const int previousWidth = mUpperValue - mLowerValue;
365 const int newUpperValue = std::max( mLowerValue, std::min( mStyleOption.maximum, std::max( mStyleOption.minimum, mUpperValue + step ) ) );
366 if ( newUpperValue != mUpperValue )
368 mUpperValue = newUpperValue;
369 mLowerValue = std::max( mStyleOption.minimum, mUpperValue - previousWidth );
383 int QgsRangeSlider::unFlippedSliderPosition(
int value )
const
385 return mFlipped ? mStyleOption.maximum + mStyleOption.minimum - value : value;
410 mStyleOption.tickPosition = position;
416 return mStyleOption.tickPosition;
421 mStyleOption.tickInterval = interval;
427 return mStyleOption.tickInterval;
433 if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
435 setSizePolicy( sizePolicy().transposed() );
436 setAttribute( Qt::WA_WState_OwnSizePolicy,
false );
444 return mStyleOption.orientation;
460 QPainter painter(
this );
462 mStyleOption.initFrom(
this );
463 mStyleOption.rect = rect();
464 mStyleOption.sliderPosition = mStyleOption.minimum;
465 mStyleOption.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderTickmarks;
467 mStyleOption.activeSubControls = mHoverSubControl;
469 style()->drawComplexControl( QStyle::CC_Slider, &mStyleOption, &painter );
471 QColor color = palette().color( QPalette::Highlight );
472 color.setAlpha( 160 );
473 painter.setBrush( QBrush( color ) );
474 painter.setPen( Qt::NoPen );
475 painter.drawRect( selectedRangeRect() );
478 mStyleOption.subControls = QStyle::SC_SliderHandle;
479 mStyleOption.activeSubControls = mHoverControl == Lower || mActiveControl == Lower ? QStyle::SC_SliderHandle : QStyle::SC_None;
480 mStyleOption.sliderPosition = unFlippedSliderPosition( mLowerValue );
481 if ( mActiveControl == Lower )
482 mStyleOption.state |= QStyle::State_Sunken;
484 mStyleOption.state &= ~QStyle::State_Sunken;
485 style()->drawComplexControl( QStyle::CC_Slider, &mStyleOption, &painter );
488 mStyleOption.activeSubControls = mHoverControl == Upper || mActiveControl == Lower ? QStyle::SC_SliderHandle : QStyle::SC_None;
489 mStyleOption.sliderPosition = unFlippedSliderPosition( mUpperValue );
490 if ( mActiveControl == Upper )
491 mStyleOption.state |= QStyle::State_Sunken;
493 mStyleOption.state &= ~QStyle::State_Sunken;
494 style()->drawComplexControl( QStyle::CC_Slider, &mStyleOption, &painter );
496 if ( hasFocus() && mFocusControl !=
None )
499 QStyleOptionFocusRect option;
500 option.initFrom(
this );
501 option.state = QStyle::State_KeyboardFocusChange;
502 if ( mFocusControl == Lower )
504 mStyleOption.sliderPosition = unFlippedSliderPosition( mLowerValue );
505 option.rect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
507 else if ( mFocusControl == Upper )
509 mStyleOption.sliderPosition = unFlippedSliderPosition( mUpperValue );
510 option.rect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
512 else if ( mFocusControl == Range )
514 option.rect = selectedRangeRect();
515 if ( mStyleOption.orientation == Qt::Horizontal )
516 option.rect = option.rect.adjusted( 0, -1, 0, 1 );
518 option.rect = option.rect.adjusted( -1, 0, 1, 0 );
520 style()->drawPrimitive( QStyle::PE_FrameFocusRect, &option, &painter );
526 if ( mStyleOption.maximum == mStyleOption.minimum || (
event->buttons() ^
event->button() ) )
534 mStyleOption.sliderPosition = unFlippedSliderPosition( mLowerValue );
535 const bool overLowerControl = style()->hitTestComplexControl( QStyle::CC_Slider, &mStyleOption,
event->pos(),
this ) == QStyle::SC_SliderHandle;
536 const QRect lowerSliderRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
537 mStyleOption.sliderPosition = unFlippedSliderPosition( mUpperValue );
538 const bool overUpperControl = style()->hitTestComplexControl( QStyle::CC_Slider, &mStyleOption,
event->pos(),
this ) == QStyle::SC_SliderHandle;
539 const QRect upperSliderRect = style()->subControlRect( QStyle::CC_Slider, &mStyleOption, QStyle::SC_SliderHandle,
this );
541 const bool overSelectedRange = selectedRangeRect().contains(
event->pos() );
543 mLowerClickOffset = pick(
event->pos() - lowerSliderRect.topLeft() );
544 mUpperClickOffset = pick(
event->pos() - upperSliderRect.topLeft() );
546 mPreDragLowerValue = mLowerValue;
547 mPreDragUpperValue = mUpperValue;
548 mRangeDragOffset = 0;
550 if ( ( overLowerControl || overUpperControl ) &&
event->modifiers() & Qt::ShiftModifier )
552 mActiveControl = Range;
553 mRangeDragOffset = overUpperControl ? mUpperClickOffset : mLowerClickOffset;
554 mFocusControl = overUpperControl ? Upper : Lower;
556 else if ( overLowerControl && overUpperControl )
557 mActiveControl = Both;
558 else if ( overLowerControl )
560 mActiveControl = Lower;
561 mFocusControl = Lower;
563 else if ( overUpperControl )
565 mActiveControl = Upper;
566 mFocusControl = Upper;
568 else if ( overSelectedRange )
570 mActiveControl = Range;
571 mFocusControl = Range;
574 mActiveControl =
None;
576 if ( mActiveControl !=
None )
578 mStartDragPos = pixelPosToRangeValue( pick(
event->pos() ) - mRangeDragOffset );
584 if ( mActiveControl ==
None )
592 int newPosition = pixelPosToRangeValue( pick(
event->pos() ) );
594 bool changed =
false;
595 Control destControl = mActiveControl;
596 if ( destControl == Both )
599 if ( newPosition < mStartDragPos )
602 mFocusControl = Lower;
603 if ( mUpperValue != mPreDragUpperValue )
606 mUpperValue = mPreDragUpperValue;
609 else if ( newPosition > mStartDragPos )
612 mFocusControl = Upper;
613 if ( mLowerValue != mPreDragLowerValue )
616 mLowerValue = mPreDragLowerValue;
622 if ( mUpperValue != mPreDragUpperValue )
625 mUpperValue = mPreDragUpperValue;
627 if ( mLowerValue != mPreDragLowerValue )
630 mLowerValue = mPreDragLowerValue;
635 switch ( destControl )
644 newPosition = std::min( mUpperValue, pixelPosToRangeValue( pick(
event->pos() ) - mLowerClickOffset ) );
645 if ( mLowerValue != newPosition )
647 mLowerValue = newPosition;
656 newPosition = std::max( mLowerValue, pixelPosToRangeValue( pick(
event->pos() ) - mUpperClickOffset ) );
657 if ( mUpperValue != newPosition )
659 mUpperValue = newPosition;
667 newPosition = pixelPosToRangeValue( pick(
event->pos() ) - mRangeDragOffset ) ;
668 int delta = newPosition - mStartDragPos;
673 const int maxDelta = mStyleOption.maximum - mPreDragUpperValue;
674 delta = std::min( maxDelta, delta );
675 mLowerValue = mPreDragLowerValue + delta;
676 mUpperValue = mPreDragUpperValue + delta;
679 else if ( delta < 0 )
683 const int maxDelta = mPreDragLowerValue - mStyleOption.minimum ;
684 delta = std::min( maxDelta, delta );
685 mLowerValue = mPreDragLowerValue - delta;
686 mUpperValue = mPreDragUpperValue - delta;
703 if ( mActiveControl ==
None ||
event->buttons() )
710 mActiveControl =
None;
716 Control destControl = mFocusControl;
717 if ( ( destControl == Lower || destControl == Upper ) && mLowerValue == mUpperValue )
720 switch (
event->key() )
724 switch ( mStyleOption.orientation )
727 if ( destControl == Both )
728 mFocusControl = mFlipped ? Upper : Lower;
730 applyStep( mFlipped ? mSingleStep : -mSingleStep );
736 switch ( mFocusControl )
739 mFocusControl = Range;
742 mFocusControl = Upper;
747 mFocusControl = Lower;
753 switch ( mFocusControl )
758 mFocusControl = Upper;
761 mFocusControl = Lower;
764 mFocusControl = Range;
776 switch ( mStyleOption.orientation )
779 if ( destControl == Both )
780 mFocusControl = mFlipped ? Lower : Upper;
781 applyStep( mFlipped ? -mSingleStep : mSingleStep );
787 switch ( mFocusControl )
792 mFocusControl = Upper;
795 mFocusControl = Lower;
798 mFocusControl = Range;
804 switch ( mFocusControl )
807 mFocusControl = Range;
810 mFocusControl = Upper;
815 mFocusControl = Lower;
827 switch ( mStyleOption.orientation )
832 switch ( mFocusControl )
835 mFocusControl = Range;
838 mFocusControl = Upper;
843 mFocusControl = Lower;
849 switch ( mFocusControl )
852 mFocusControl = Upper;
857 mFocusControl = Lower;
860 mFocusControl = Range;
868 if ( destControl == Both )
869 mFocusControl = mFlipped ? Upper : Lower;
871 applyStep( mFlipped ? mSingleStep : -mSingleStep );
879 switch ( mStyleOption.orientation )
884 switch ( mFocusControl )
887 mFocusControl = Upper;
892 mFocusControl = Lower;
895 mFocusControl = Range;
901 switch ( mFocusControl )
904 mFocusControl = Range;
907 mFocusControl = Upper;
912 mFocusControl = Lower;
920 if ( destControl == Both )
921 mFocusControl = mFlipped ? Lower : Upper;
923 applyStep( mFlipped ? -mSingleStep : mSingleStep );
931 switch ( mStyleOption.orientation )
934 if ( destControl == Both )
935 mFocusControl = mFlipped ? Lower : Upper;
937 applyStep( mFlipped ? -mPageStep : mPageStep );
941 if ( destControl == Both )
942 mFocusControl = mFlipped ? Upper : Lower;
944 applyStep( mFlipped ? mPageStep : -mPageStep );
950 case Qt::Key_PageDown:
952 switch ( mStyleOption.orientation )
955 if ( destControl == Both )
956 mFocusControl = mFlipped ? Upper : Lower;
958 applyStep( mFlipped ? mPageStep : -mPageStep );
962 if ( destControl == Both )
963 mFocusControl = mFlipped ? Lower : Upper;
965 applyStep( mFlipped ? -mPageStep : mPageStep );
972 switch ( destControl )
975 applyStep( mFlipped ? mUpperValue - mLowerValue : mStyleOption.minimum - mLowerValue );
979 applyStep( mFlipped ? mStyleOption.maximum - mUpperValue : mLowerValue - mUpperValue );
983 applyStep( mFlipped ? mStyleOption.maximum - mUpperValue : mStyleOption.minimum - mLowerValue );
987 if ( destControl == Both )
988 mFocusControl = mFlipped ? Upper : Lower;
990 applyStep( mFlipped ? mStyleOption.maximum - mUpperValue : mStyleOption.minimum - mLowerValue );
1000 switch ( destControl )
1003 applyStep( mFlipped ? mStyleOption.minimum - mLowerValue : mUpperValue - mLowerValue );
1007 applyStep( mFlipped ? mLowerValue - mUpperValue : mStyleOption.maximum - mUpperValue );
1011 applyStep( mFlipped ? mStyleOption.minimum - mLowerValue : mStyleOption.maximum - mUpperValue );
1015 if ( destControl == Both )
1016 mFocusControl = mFlipped ? Lower : Upper;
1018 applyStep( mFlipped ? mStyleOption.minimum - mLowerValue : mStyleOption.maximum - mUpperValue );
1037 static constexpr
int SLIDER_LENGTH = 84;
1038 static constexpr
int TICK_SPACE = 5;
1040 int thick = style()->pixelMetric( QStyle::PM_SliderThickness, &mStyleOption,
this );
1041 if ( mStyleOption.tickPosition & QSlider::TicksAbove )
1042 thick += TICK_SPACE;
1043 if ( mStyleOption.tickPosition & QSlider::TicksBelow )
1044 thick += TICK_SPACE;
1045 int w = thick, h = SLIDER_LENGTH;
1046 if ( mStyleOption.orientation == Qt::Horizontal )
1050 return style()->sizeFromContents( QStyle::CT_Slider, &mStyleOption, QSize( w, h ),
this );
1056 const int length = style()->pixelMetric( QStyle::PM_SliderLength, &mStyleOption,
this );
1057 if ( mStyleOption.orientation == Qt::Horizontal )
1058 s.setWidth( length );
1060 s.setHeight( length );