12#include <QStyleOptionSlider>
13#include <QApplication>
14#include <QStylePainter>
18#include "ctk3slider.h"
20class ctk3SliderPrivate
35 Q_DECLARE_FLAGS(Handles, Handle)
44 Handle handleAtPos(
const QPoint &pos,
QRect &handleRect)
const;
47 int pixelPosToRangeValue(
int pos)
const;
48 int pixelPosFromRangeValue(
int val)
const;
61 int m_MaximumPosition;
62 int m_MinimumPosition;
72 int m_SubclassClickOffset;
76 int m_SubclassPosition;
86 Q_DISABLE_COPY(ctk3SliderPrivate)
90ctk3SliderPrivate::ctk3SliderPrivate(
ctk3Slider &
object)
93 this->m_MinimumValue = 0;
94 this->m_MaximumValue = 100;
95 this->m_MidValue = 50;
96 this->m_MinimumPosition = 0;
97 this->m_MaximumPosition = 100;
98 this->m_MidPosition = 50;
102 this->m_SubclassClickOffset = 0;
103 this->m_SubclassPosition = 0;
104 this->m_SubclassWidth = 0;
105 this->m_SelectedHandles = ctk3SliderPrivate::NoHandle;
109void ctk3SliderPrivate::init()
112 this->m_MinimumValue = q->minimum();
113 this->m_MaximumValue = q->maximum();
114 this->m_MaximumValue = (q->minimum() + q->maximum()) / 2.0;
115 this->m_MinimumPosition = q->minimum();
116 this->m_MaximumPosition = q->maximum();
117 this->m_MidPosition = (q->minimum() + q->maximum()) / 2.0;
118 q->connect(q, SIGNAL(rangeChanged(
int,
int)), q, SLOT(onRangeChanged(
int,
int)));
122ctk3SliderPrivate::Handle ctk3SliderPrivate::handleAtPos(
const QPoint &pos,
QRect &handleRect)
const
127 q->initStyleOption( &option );
134 option.sliderPosition = this->m_MinimumPosition;
135 option.sliderValue = this->m_MinimumValue;
139 QRect minimumHandleRect = q->style()->subControlRect(
143 option.sliderPosition = this->m_MaximumPosition;
144 option.sliderValue = this->m_MaximumValue;
148 QRect maximumHandleRect = q->style()->subControlRect(
152 option.sliderPosition = this->m_MidPosition;
153 option.sliderValue = this->m_MidValue;
157 QRect midHandleRect = q->style()->subControlRect(
162 handleRect = minimumHandleRect;
163 return MinimumHandle;
167 handleRect = midHandleRect;
172 handleRect = maximumHandleRect;
173 return MaximumHandle;
175 handleRect = minimumHandleRect.
united(maximumHandleRect);
182int ctk3SliderPrivate::pixelPosToRangeValue(
int pos )
const
186 q->initStyleOption( &option );
196 int sliderMin, sliderMax, sliderLength;
199 sliderLength = sr.
width();
201 sliderMax = gr.
right() - sliderLength + 1;
205 sliderLength = sr.
height();
207 sliderMax = gr.
bottom() - sliderLength + 1;
213 sliderMax - sliderMin,
218int ctk3SliderPrivate::pixelPosFromRangeValue(
int val )
const
222 q->initStyleOption( &option );
232 int sliderMin, sliderMax, sliderLength;
235 sliderLength = sr.
width();
237 sliderMax = gr.
right() - sliderLength + 1;
241 sliderLength = sr.
height();
243 sliderMax = gr.
bottom() - sliderLength + 1;
249 sliderMax - sliderMin,
250 option.upsideDown ) + sliderMin;
255void ctk3SliderPrivate::drawMinimumSlider(
QStylePainter* painter )
const
259 q->initMinimumSliderStyleOption( &option );
262 option.sliderValue = m_MinimumValue;
263 option.sliderPosition = m_MinimumPosition;
264 if (q->isMinimumSliderDown())
280void ctk3SliderPrivate::drawMaximumSlider(
QStylePainter* painter )
const
284 q->initMaximumSliderStyleOption( &option );
287 option.sliderValue = m_MaximumValue;
288 option.sliderPosition = m_MaximumPosition;
289 if (q->isMaximumSliderDown())
304void ctk3SliderPrivate::drawMidSlider(
QStylePainter* painter )
const
308 q->initMidSliderStyleOption( &option );
311 option.sliderValue = m_MidValue;
312 option.sliderPosition = m_MidPosition;
313 if (q->isMidSliderDown())
330 , d_ptr(new ctk3SliderPrivate(*this))
340 , d_ptr(new ctk3SliderPrivate(*this))
366ctk3Slider::~ctk3Slider()
371int ctk3Slider::minimumValue()
const
374 return d->m_MinimumValue;
382 int newMin = qMin( qMin(min, d->m_MidValue), d->m_MaximumValue);
383 this->
setValues( newMin, d->m_MidValue, d->m_MaximumValue);
387int ctk3Slider::maximumValue()
const
390 return d->m_MaximumValue;
398 int newMax = qMax( qMax(max, d->m_MidValue), d->m_MinimumValue);
399 this->
setValues(d->m_MinimumValue, d->m_MidValue, newMax);
403int ctk3Slider::midValue()
const
406 return d->m_MidValue;
414 int newMid = qMax(d->m_MinimumValue, mid);
415 newMid = qMin(newMid, d->m_MaximumValue);
416 this->
setValues(d->m_MinimumValue, newMid, d->m_MaximumValue);
423void sortLMU(
int &l,
int &m,
int &u)
425 int kL = l, kM = m, kU = u;
426 if (l <= m && l <= u)
437 else if (m <= l && m <= u)
481 bool emitMinValChanged = (minValue != d->m_MinimumValue);
482 bool emitMaxValChanged = (maxValue != d->m_MaximumValue);
483 bool emitMidValChanged = (midValue != d->m_MidValue);
485 d->m_MinimumValue = minValue;
486 d->m_MaximumValue = maxValue;
487 d->m_MidValue = midValue;
489 bool emitMinPosChanged =
490 (minValue != d->m_MinimumPosition);
491 bool emitMaxPosChanged =
492 (maxValue != d->m_MaximumPosition);
493 bool emitMidPosChanged =
494 (midValue != d->m_MidPosition);
495 d->m_MinimumPosition = minValue;
496 d->m_MaximumPosition = maxValue;
497 d->m_MidPosition = midValue;
501 if (emitMinPosChanged || emitMaxPosChanged || emitMidPosChanged)
503 emit
positionsChanged(d->m_MinimumPosition, d->m_MidPosition, d->m_MaximumPosition);
505 if (emitMinPosChanged)
509 if (emitMaxPosChanged)
513 if (emitMidPosChanged)
518 if (emitMinValChanged || emitMaxValChanged || emitMidValChanged)
520 emit
valuesChanged(d->m_MinimumValue, d->m_MidValue, d->m_MaximumValue);
522 if (emitMinValChanged)
526 if (emitMaxValChanged)
530 if (emitMidValChanged)
534 if (emitMinPosChanged || emitMaxPosChanged || emitMidPosChanged ||
535 emitMinValChanged || emitMaxValChanged || emitMidValChanged)
542int ctk3Slider::minimumPosition()
const
545 return d->m_MinimumPosition;
549int ctk3Slider::maximumPosition()
const
552 return d->m_MaximumPosition;
555int ctk3Slider::midPosition()
const
558 return d->m_MidPosition;
562void ctk3Slider::setMinimumPosition(
int l)
566 int newMin = qMin( qMin(l, d->m_MidPosition), d->m_MaximumPosition);
567 this->
setPositions(newMin, d->m_MidPosition, d->m_MaximumPosition);
571void ctk3Slider::setMaximumPosition(
int u)
575 int newMax = qMax( qMax(u, d->m_MidPosition), d->m_MinimumPosition);
576 this->
setPositions(d->m_MinimumPosition, d->m_MidPosition, newMax);
579void ctk3Slider::setMidPosition(
int m)
583 int newMid = qMax(d->m_MinimumPosition, m);
584 newMid = qMin(newMid, d->m_MaximumPosition);
585 this->
setPositions(d->m_MinimumPosition, newMid, d->m_MaximumPosition);
592 sortLMU(min, mid, max);
593 const int minPosition =
595 const int maxPosition =
597 const int midPosition =
600 bool emitMinPosChanged = (minPosition != d->m_MinimumPosition);
601 bool emitMaxPosChanged = (maxPosition != d->m_MaximumPosition);
602 bool emitMidPosChanged = (midPosition != d->m_MidPosition);
604 if (!emitMinPosChanged && !emitMaxPosChanged && !emitMidPosChanged)
609 d->m_MinimumPosition = minPosition;
610 d->m_MaximumPosition = maxPosition;
611 d->m_MidPosition = midPosition;
619 if (emitMinPosChanged)
623 if (emitMaxPosChanged)
627 if (emitMidPosChanged)
631 if (emitMinPosChanged || emitMaxPosChanged || emitMidPosChanged)
633 emit
positionsChanged(d->m_MinimumPosition, d->m_MidPosition, d->m_MaximumPosition);
639 this->
setValues(d->m_MinimumPosition, d->m_MidPosition, d->m_MaximumPosition);
644void ctk3Slider::onRangeChanged(
int _minimum,
int _maximum)
649 this->
setValues(d->m_MinimumValue, d->m_MidValue, d->m_MaximumValue);
669 option.sliderPosition = d->m_MinimumPosition;
675 option.sliderPosition = d->m_MidPosition;
682 option.sliderPosition = d->m_MaximumPosition;
714 groove.
adjust(0, 0, -1, 0);
743 d->drawMaximumSlider( &painter );
744 d->drawMidSlider( &painter );
745 d->drawMinimumSlider( &painter );
749 d->drawMaximumSlider( &painter );
750 d->drawMinimumSlider( &painter );
751 d->drawMidSlider( &painter );
755 d->drawMinimumSlider( &painter );
756 d->drawMidSlider( &painter );
757 d->drawMaximumSlider( &painter );
763void ctk3Slider::mousePressEvent(
QMouseEvent* mouseEvent)
772 mouseEvent->
pos().
x() : mouseEvent->
pos().
y();
778 ctk3SliderPrivate::Handle handle_ = d->handleAtPos(mouseEvent->
pos(), handleRect);
780 if (handle_ != ctk3SliderPrivate::NoHandle)
782 if (handle_ == ctk3SliderPrivate::MinimumHandle)
783 d->m_SubclassPosition = d->m_MinimumPosition;
784 else if (handle_ == ctk3SliderPrivate::MaximumHandle)
785 d->m_SubclassPosition = d->m_MaximumPosition;
786 else if (handle_ == ctk3SliderPrivate::MidHandle)
787 d->m_SubclassPosition = d->m_MidPosition;
791 handleRect.
left() : handleRect.
top());
795 if (d->m_SelectedHandles != handle_)
797 d->m_SelectedHandles = handle_;
813 handleRect.
left() : handleRect.
top());
817 mepos > minCenter && mepos < maxCenter)
820 d->m_SubclassPosition = (d->m_MinimumPosition + d->m_MaximumPosition) / 2.;
821 d->m_SubclassClickOffset = mepos - d->pixelPosFromRangeValue(d->m_SubclassPosition);
822 d->m_SubclassWidth = (d->m_MaximumPosition - d->m_MinimumPosition) / 2;
823 qMax(d->m_SubclassPosition - d->m_MinimumPosition, d->m_MaximumPosition - d->m_SubclassPosition);
827 d->m_SelectedHandles =
840void ctk3Slider::mouseMoveEvent(
QMouseEvent* mouseEvent)
843 if (!d->m_SelectedHandles)
849 mouseEvent->
pos().
x() : mouseEvent->
pos().
y();
856 int newPosition = d->pixelPosToRangeValue(mepos - d->m_SubclassClickOffset);
863 newPosition = d->m_SubclassPosition;
873 if (newPosition < d->m_MidPosition)
874 this->
setPositions(newPosition, d->m_MidPosition, d->m_MaximumPosition);
876 this->
setPositions(d->m_MinimumPosition, newPosition, d->m_MaximumPosition);
882 if (newPosition < d->m_MaximumPosition)
883 this->
setPositions(d->m_MinimumPosition, newPosition, d->m_MaximumPosition);
885 this->
setPositions(d->m_MinimumPosition, d->m_MidPosition, newPosition);
889 double newMinPos = qMin(newPosition, d->m_MidPosition);
890 this->
setPositions(newMinPos, d->m_MidPosition, d->m_MaximumPosition);
895 double newMaxPos = qMax(d->m_MidPosition, newPosition);
896 this->
setPositions(d->m_MinimumPosition, d->m_MidPosition, newMaxPos);
901 double newMidPos = qMin(qMax(d->m_MinimumPosition, newPosition), d->m_MaximumPosition);
902 this->
setPositions(d->m_MinimumPosition, newMidPos, d->m_MaximumPosition);
909void ctk3Slider::mouseReleaseEvent(
QMouseEvent* mouseEvent)
915 d->m_SelectedHandles = ctk3SliderPrivate::NoHandle;
917 emit released(d->m_MinimumValue, d->m_MidValue, d->m_MaximumValue);
925 return d->m_SelectedHandles & ctk3SliderPrivate::MinimumHandle;
932 return d->m_SelectedHandles & ctk3SliderPrivate::MaximumHandle;
938 return d->m_SelectedHandles & ctk3SliderPrivate::MidHandle;
962 return d->m_HandleToolTip;
966void ctk3Slider::setHandleToolTip(
const QString &_toolTip)
969 d->m_HandleToolTip = _toolTip;
973bool ctk3Slider::event(
QEvent* _event)
976 switch(_event->
type())
983 opt.sliderPosition = d->m_MinimumPosition;
984 opt.sliderValue = d->m_MinimumValue;
989 if (!d->m_HandleToolTip.isEmpty() &&
997 opt.sliderPosition = d->m_MaximumPosition;
998 opt.sliderValue = d->m_MaximumValue;
1002 if (!d->m_HandleToolTip.isEmpty() &&
1010 opt.sliderPosition = d->m_MidPosition;
1011 opt.sliderValue = d->m_MidValue;
1015 if (!d->m_HandleToolTip.isEmpty() &&
A ctk3Slider is a slider that lets you input 2 values instead of one (see QSlider).
void maximumPositionChanged(int max)
This signal is emitted when sliderDown is true and the slider moves.
void setValues(int min, int mid, int max)
Utility function that set the minimum value and maximum value at once.
void setMaximumValue(int max)
This property holds the slider's current maximum value.
void minimumPositionChanged(int min)
This signal is emitted when sliderDown is true and the slider moves.
void maximumValueChanged(int max)
This signal is emitted when the slider maximum value has changed, with the new slider value as argume...
void minimumValueChanged(int min)
This signal is emitted when the slider minimum value has changed, with the new slider value as argume...
void positionsChanged(int min, int mid, int max)
Utility signal that is fired when minimum or maximum positions have changed.
bool isMaximumSliderDown() const
Returns true if the maximum value handle is down, false if it is up.
void setPositions(int min, int mid, int max)
Utility function that set the minimum, mid and maximum position at once.
ctk3Slider(Qt::Orientation o, QWidget *par=0)
Constructor, builds a ctk3Slider that ranges from 0 to 100 and has a lower and upper values of 0 and ...
void setMinimumValue(int min)
This property holds the slider's current minimum value.
void setMidValue(int mid)
This property holds the slider's current mid value.
bool isMidSliderDown() const
Returns true if the mid value handle is down, false if it is up.
void midValueChanged(int mid)
This signal is emitted when the slider mid value has changed, with the new slider value as argument.
void midPositionChanged(int max)
This signal is emitted when sliderDown is true and the slider moves.
void valuesChanged(int min, int mid, int max)
Utility signal that is fired when minimum, mid or maximum values have changed.
bool isMinimumSliderDown() const
Returns true if the minimum value handle is down, false if it is up.
bool isSliderDown() const const
bool hasTracking() const const
void triggerAction(SliderAction action)
QColor darker(int factor) const const
QColor lighter(int factor) const const
void setColorAt(qreal position, const QColor &color)
const QPoint & globalPos() const const
const QPoint & pos() const const
void drawRect(const QRect &rectangle)
void setBrush(Qt::BrushStyle style)
void setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
void setPen(Qt::PenStyle style)
void adjust(int dx1, int dy1, int dx2, int dy2)
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const const
QPoint center() const const
bool contains(const QPoint &point, bool proper) const const
QRect intersected(const QRect &rectangle) const const
QRect united(const QRect &rectangle) const const
virtual bool event(QEvent *event) override
virtual void initStyleOption(QStyleOptionSlider *option) const const
virtual void mouseReleaseEvent(QMouseEvent *ev) override
virtual SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget) const const=0
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
int sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown)
int sliderValueFromPosition(int min, int max, int position, int span, bool upsideDown)
virtual QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const const=0
void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex &option)
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)