10#include <QStyleOptionSlider>
11#include <QApplication>
12#include <QStylePainter>
17#include "ctkrangeslider.h"
19class ctkRangeSliderPrivate
32 Q_DECLARE_FLAGS(Handles, Handle)
41 Handle handleAtPos(
const QPoint& pos,
QRect& handleRect)
const;
44 int pixelPosToRangeValue(
int pos)
const;
45 int pixelPosFromRangeValue(
int val)
const;
56 int m_MaximumPosition;
57 int m_MinimumPosition;
65 int m_SubclassClickOffset;
69 int m_SubclassPosition;
78 bool m_SymmetricMoves;
83 Q_DISABLE_COPY(ctkRangeSliderPrivate)
87ctkRangeSliderPrivate::ctkRangeSliderPrivate(
ctkRangeSlider&
object)
90 this->m_MinimumValue = 0;
91 this->m_MaximumValue = 100;
92 this->m_MinimumPosition = 0;
93 this->m_MaximumPosition = 100;
96 this->m_SubclassClickOffset = 0;
97 this->m_SubclassPosition = 0;
98 this->m_SubclassWidth = 0;
99 this->m_SelectedHandles = ctkRangeSliderPrivate::NoHandle;
100 this->m_SymmetricMoves =
false;
104void ctkRangeSliderPrivate::init()
107 this->m_MinimumValue = q->minimum();
108 this->m_MaximumValue = q->maximum();
109 this->m_MinimumPosition = q->minimum();
110 this->m_MaximumPosition = q->maximum();
111 q->connect(q, SIGNAL(rangeChanged(
int,
int)), q, SLOT(onRangeChanged(
int,
int)));
115ctkRangeSliderPrivate::Handle ctkRangeSliderPrivate::handleAtPos(
const QPoint& pos,
QRect& handleRect)
const
120 q->initStyleOption( &option );
127 option.sliderPosition = this->m_MinimumPosition;
128 option.sliderValue = this->m_MinimumValue;
132 QRect minimumHandleRect = q->style()->subControlRect(
136 option.sliderPosition = this->m_MaximumPosition;
137 option.sliderValue = this->m_MaximumValue;
141 QRect maximumHandleRect = q->style()->subControlRect(
152 minDist = pos.
x() - minimumHandleRect.
left();
153 maxDist = maximumHandleRect.
right() - pos.
x();
157 minDist = minimumHandleRect.
bottom() - pos.
y();
158 maxDist = pos.
y() - maximumHandleRect.
top();
160 Q_ASSERT( minDist >= 0 && maxDist >= 0);
166 handleRect = minimumHandleRect;
167 return MinimumHandle;
171 handleRect = maximumHandleRect;
172 return MaximumHandle;
174 handleRect = minimumHandleRect.
united(maximumHandleRect);
181int ctkRangeSliderPrivate::pixelPosToRangeValue(
int pos )
const
185 q->initStyleOption( &option );
195 int sliderMin, sliderMax, sliderLength;
198 sliderLength = sr.
width();
200 sliderMax = gr.
right() - sliderLength + 1;
204 sliderLength = sr.
height();
206 sliderMax = gr.
bottom() - sliderLength + 1;
212 sliderMax - sliderMin,
217int ctkRangeSliderPrivate::pixelPosFromRangeValue(
int val )
const
221 q->initStyleOption( &option );
231 int sliderMin, sliderMax, sliderLength;
234 sliderLength = sr.
width();
236 sliderMax = gr.
right() - sliderLength + 1;
240 sliderLength = sr.
height();
242 sliderMax = gr.
bottom() - sliderLength + 1;
248 sliderMax - sliderMin,
249 option.upsideDown ) + sliderMin;
254void ctkRangeSliderPrivate::drawMinimumSlider(
QStylePainter* painter )
const
258 q->initMinimumSliderStyleOption( &option );
261 option.sliderValue = m_MinimumValue;
262 option.sliderPosition = m_MinimumPosition;
263 if (q->isMinimumSliderDown())
279void ctkRangeSliderPrivate::drawMaximumSlider(
QStylePainter* painter )
const
283 q->initMaximumSliderStyleOption( &option );
286 option.sliderValue = m_MaximumValue;
287 option.sliderPosition = m_MaximumPosition;
288 if (q->isMaximumSliderDown())
305 , d_ptr(new ctkRangeSliderPrivate(*this))
315 , d_ptr(new ctkRangeSliderPrivate(*this))
341ctkRangeSlider::~ctkRangeSlider()
346int ctkRangeSlider::minimumValue()
const
349 return d->m_MinimumValue;
356 this->
setValues( min, qMax(d->m_MaximumValue,min) );
360int ctkRangeSlider::maximumValue()
const
363 return d->m_MaximumValue;
370 this->
setValues( qMin(d->m_MinimumValue, max), max );
381 bool emitMinValChanged = (minValue != d->m_MinimumValue);
382 bool emitMaxValChanged = (maxValue != d->m_MaximumValue);
384 d->m_MinimumValue = minValue;
385 d->m_MaximumValue = maxValue;
387 bool emitMinPosChanged =
388 (minValue != d->m_MinimumPosition);
389 bool emitMaxPosChanged =
390 (maxValue != d->m_MaximumPosition);
391 d->m_MinimumPosition = minValue;
392 d->m_MaximumPosition = maxValue;
396 if (emitMinPosChanged || emitMaxPosChanged)
400 if (emitMinPosChanged)
404 if (emitMaxPosChanged)
409 if (emitMinValChanged || emitMaxValChanged)
414 if (emitMinValChanged)
418 if (emitMaxValChanged)
422 if (emitMinPosChanged || emitMaxPosChanged ||
423 emitMinValChanged || emitMaxValChanged)
430int ctkRangeSlider::minimumPosition()
const
433 return d->m_MinimumPosition;
437int ctkRangeSlider::maximumPosition()
const
440 return d->m_MaximumPosition;
444void ctkRangeSlider::setMinimumPosition(
int l)
451void ctkRangeSlider::setMaximumPosition(
int u)
461 const int minPosition =
463 const int maxPosition =
466 bool emitMinPosChanged = (minPosition != d->m_MinimumPosition);
467 bool emitMaxPosChanged = (maxPosition != d->m_MaximumPosition);
469 if (!emitMinPosChanged && !emitMaxPosChanged)
474 d->m_MinimumPosition = minPosition;
475 d->m_MaximumPosition = maxPosition;
483 if (emitMinPosChanged)
487 if (emitMaxPosChanged)
491 if (emitMinPosChanged || emitMaxPosChanged)
499 this->
setValues(d->m_MinimumPosition, d->m_MaximumPosition);
504void ctkRangeSlider::setSymmetricMoves(
bool symmetry)
507 d->m_SymmetricMoves = symmetry;
511bool ctkRangeSlider::symmetricMoves()
const
514 return d->m_SymmetricMoves;
518void ctkRangeSlider::onRangeChanged(
int _minimum,
int _maximum)
523 this->
setValues(d->m_MinimumValue, d->m_MaximumValue);
543 option.sliderPosition = d->m_MinimumPosition;
548 option.sliderPosition = d->m_MaximumPosition;
580 groove.
adjust(0, 0, -1, 0);
613 d->drawMaximumSlider( &painter );
614 d->drawMinimumSlider( &painter );
618 d->drawMinimumSlider( &painter );
619 d->drawMaximumSlider( &painter );
625void ctkRangeSlider::mousePressEvent(
QMouseEvent* mouseEvent)
634 mouseEvent->
pos().
x() : mouseEvent->
pos().
y();
640 ctkRangeSliderPrivate::Handle handle_ = d->handleAtPos(mouseEvent->
pos(), handleRect);
642 if (handle_ != ctkRangeSliderPrivate::NoHandle)
644 d->m_SubclassPosition = (handle_ == ctkRangeSliderPrivate::MinimumHandle)?
645 d->m_MinimumPosition : d->m_MaximumPosition;
649 handleRect.
left() : handleRect.
top());
653 if (d->m_SelectedHandles != handle_)
655 d->m_SelectedHandles = handle_;
671 handleRect.
left() : handleRect.
top());
675 mepos > minCenter && mepos < maxCenter)
678 d->m_SubclassPosition = (d->m_MinimumPosition + d->m_MaximumPosition) / 2.;
679 d->m_SubclassClickOffset = mepos - d->pixelPosFromRangeValue(d->m_SubclassPosition);
680 d->m_SubclassWidth = (d->m_MaximumPosition - d->m_MinimumPosition) / 2;
681 qMax(d->m_SubclassPosition - d->m_MinimumPosition, d->m_MaximumPosition - d->m_SubclassPosition);
685 d->m_SelectedHandles =
698void ctkRangeSlider::mouseMoveEvent(
QMouseEvent* mouseEvent)
701 if (!d->m_SelectedHandles)
707 mouseEvent->
pos().
x() : mouseEvent->
pos().
y();
714 int newPosition = d->pixelPosToRangeValue(mepos - d->m_SubclassClickOffset);
721 newPosition = d->m_SubclassPosition;
728 double newMinPos = qMin(newPosition,d->m_MaximumPosition);
730 (d->m_SymmetricMoves ? d->m_MinimumPosition - newMinPos : 0));
735 double newMaxPos = qMax(d->m_MinimumPosition, newPosition);
737 (d->m_SymmetricMoves ? newMaxPos - d->m_MaximumPosition: 0),
744 newPosition + d->m_SubclassWidth );
751void ctkRangeSlider::mouseReleaseEvent(
QMouseEvent* mouseEvent)
757 d->m_SelectedHandles = ctkRangeSliderPrivate::NoHandle;
766 return d->m_SelectedHandles & ctkRangeSliderPrivate::MinimumHandle;
773 return d->m_SelectedHandles & ctkRangeSliderPrivate::MaximumHandle;
792 return d->m_HandleToolTip;
796void ctkRangeSlider::setHandleToolTip(
const QString& _toolTip)
799 d->m_HandleToolTip = _toolTip;
803bool ctkRangeSlider::event(
QEvent* _event)
806 switch(_event->
type())
813 opt.sliderPosition = d->m_MinimumPosition;
814 opt.sliderValue = d->m_MinimumValue;
819 if (!d->m_HandleToolTip.isEmpty() &&
827 opt.sliderPosition = d->m_MaximumPosition;
828 opt.sliderValue = d->m_MaximumValue;
832 if (!d->m_HandleToolTip.isEmpty() &&
A ctkRangeSlider is a slider that lets you input 2 values instead of one (see QSlider).
void setPositions(int min, int max)
Utility function that set the minimum position and maximum position at once.
void minimumPositionChanged(int min)
This signal is emitted when sliderDown is true and the slider moves.
void setMaximumValue(int max)
This property holds the slider's current maximum value.
void minimumValueChanged(int min)
This signal is emitted when the slider minimum value has changed, with the new slider value as argume...
ctkRangeSlider(Qt::Orientation o, QWidget *par=0)
Constructor, builds a ctkRangeSlider that ranges from 0 to 100 and has a lower and upper values of 0 ...
bool isMinimumSliderDown() const
Returns true if the minimum value handle is down, false if it is up.
void maximumValueChanged(int max)
This signal is emitted when the slider maximum value has changed, with the new slider value as argume...
void maximumPositionChanged(int max)
This signal is emitted when sliderDown is true and the slider moves.
void positionsChanged(int min, int max)
Utility signal that is fired when minimum or maximum positions have changed.
void setValues(int min, int max)
Utility function that set the minimum value and maximum value at once.
bool isMaximumSliderDown() const
Returns true if the maximum value handle is down, false if it is up.
void valuesChanged(int min, int max)
Utility signal that is fired when minimum or maximum values have changed.
void setMinimumValue(int min)
This property holds the slider's current minimum value.
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)