#include "rangeslider.h" #include "qad_types.h" #include RangeSlider::RangeSlider(QWidget * parent) : QWidget(parent) , m_minimum(0) , m_maximum(100) , m_lowerValue(0) , m_upperValue(100) , mFirstHandlePressed(false) , mSecondHandlePressed(false) , orientation(Qt::Horizontal) , m_mode(DoubleHandles) { init(); } RangeSlider::RangeSlider(Qt::Orientation ori, Mode m, QWidget * parent) : QWidget(parent) , m_minimum(0) , m_maximum(100) , m_lowerValue(0) , m_upperValue(100) , mFirstHandlePressed(false) , mSecondHandlePressed(false) , orientation(ori) , m_mode(m) { init(); } void RangeSlider::init() { setMouseTracking(true); scHandleSideLength = 16 * lineThickness(this); scSliderBarHeight = 8 * lineThickness(this); scLeftRightMargin = 2 * lineThickness(this); } void RangeSlider::paintEvent(QPaintEvent *) { QPainter painter(this); // Background QRectF backgroundRect; if (orientation == Qt::Horizontal) backgroundRect = QRectF(scLeftRightMargin, (height() - scSliderBarHeight) / 2, width() - scLeftRightMargin * 2, scSliderBarHeight); else backgroundRect = QRectF((width() - scSliderBarHeight) / 2, scLeftRightMargin, scSliderBarHeight, height() - scLeftRightMargin * 2); QPen pen(palette().color(QPalette::Disabled, QPalette::Text)); painter.setPen(pen); if (isEnabled()) { painter.setBrush(palette().color(QPalette::Active, QPalette::Base)); } else { painter.setBrush(palette().color(QPalette::Disabled, QPalette::Base)); } painter.drawRect(backgroundRect); // First value handle rect painter.setPen(pen); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(palette().color(QPalette::Active, QPalette::Button)); QRectF leftHandleRect = firstHandleRect(); if (m_mode.testFlag(LeftHandle)) painter.drawEllipse(leftHandleRect); // Second value handle rect QRectF rightHandleRect = secondHandleRect(); if (m_mode.testFlag(RightHandle)) painter.drawEllipse(rightHandleRect); // Handles painter.setRenderHint(QPainter::Antialiasing, false); QRectF selectedRect(backgroundRect); if (orientation == Qt::Horizontal) { selectedRect.setLeft((m_mode.testFlag(LeftHandle) ? leftHandleRect.right() : leftHandleRect.left()) + 0.5); selectedRect.setRight((m_mode.testFlag(RightHandle) ? rightHandleRect.left() : rightHandleRect.right()) - 0.5); } else { selectedRect.setTop((m_mode.testFlag(LeftHandle) ? leftHandleRect.bottom() : leftHandleRect.top()) + 0.5); selectedRect.setBottom((m_mode.testFlag(RightHandle) ? rightHandleRect.top() : rightHandleRect.bottom()) - 0.5); } if (isEnabled()) { painter.setBrush(palette().color(QPalette::Active, QPalette::Highlight)); } else { painter.setBrush(palette().color(QPalette::Disabled, QPalette::Text)); } painter.drawRect(selectedRect); } QRectF RangeSlider::firstHandleRect() const { float percentage = (m_lowerValue - m_minimum) * 1.0 / interval(); return handleRect(percentage * validLength() + scLeftRightMargin); } QRectF RangeSlider::secondHandleRect() const { float percentage = (m_upperValue - m_minimum) * 1.0 / interval(); return handleRect(percentage * validLength() + scLeftRightMargin + (m_mode.testFlag(LeftHandle) ? scHandleSideLength : 0)); } QRectF RangeSlider::handleRect(int value) const { if (orientation == Qt::Horizontal) return QRect(value, (height() - scHandleSideLength) / 2, scHandleSideLength, scHandleSideLength); else return QRect((width() - scHandleSideLength) / 2, value, scHandleSideLength, scHandleSideLength); } void RangeSlider::mousePressEvent(QMouseEvent * e) { if (e->buttons() & Qt::LeftButton) { int posCheck, posMax, posValue, firstHandleRectPosValue, secondHandleRectPosValue; posCheck = (orientation == Qt::Horizontal) ? e->pos().y() : e->pos().x(); posMax = (orientation == Qt::Horizontal) ? height() : width(); posValue = (orientation == Qt::Horizontal) ? e->pos().x() : e->pos().y(); firstHandleRectPosValue = (orientation == Qt::Horizontal) ? firstHandleRect().x() : firstHandleRect().y(); secondHandleRectPosValue = (orientation == Qt::Horizontal) ? secondHandleRect().x() : secondHandleRect().y(); mSecondHandlePressed = secondHandleRect().contains(e->pos()); mFirstHandlePressed = !mSecondHandlePressed && firstHandleRect().contains(e->pos()); if (mFirstHandlePressed) { mDelta = posValue - (firstHandleRectPosValue + scHandleSideLength / 2); } else if (mSecondHandlePressed) { mDelta = posValue - (secondHandleRectPosValue + scHandleSideLength / 2); } if (posCheck >= 2 && posCheck <= posMax - 2) { int step = interval() / 10 < 1 ? 1 : interval() / 10; if (posValue < firstHandleRectPosValue) setLowerValue(m_lowerValue - step); else if (((posValue > firstHandleRectPosValue + scHandleSideLength) || !m_mode.testFlag(LeftHandle)) && ((posValue < secondHandleRectPosValue) || !m_mode.testFlag(RightHandle))) { if (m_mode.testFlag(DoubleHandles)) { if (posValue - (firstHandleRectPosValue + scHandleSideLength) < (secondHandleRectPosValue - (firstHandleRectPosValue + scHandleSideLength)) / 2) { setLowerValue((m_lowerValue + step < m_upperValue) ? m_lowerValue + step : m_upperValue); } else { setUpperValue((m_upperValue - step > m_lowerValue) ? m_upperValue - step : m_lowerValue); } } else if (m_mode.testFlag(LeftHandle)) { setLowerValue((m_lowerValue + step < m_upperValue) ? m_lowerValue + step : m_upperValue); } else if (m_mode.testFlag(RightHandle)) { setUpperValue((m_upperValue - step > m_lowerValue) ? m_upperValue - step : m_lowerValue); } } else if (posValue > secondHandleRectPosValue + scHandleSideLength) setUpperValue(m_upperValue + step); } } } void RangeSlider::mouseMoveEvent(QMouseEvent * e) { if (e->buttons() & Qt::LeftButton) { int posValue, firstHandleRectPosValue, secondHandleRectPosValue; posValue = (orientation == Qt::Horizontal) ? e->pos().x() : e->pos().y(); firstHandleRectPosValue = (orientation == Qt::Horizontal) ? firstHandleRect().x() : firstHandleRect().y(); secondHandleRectPosValue = (orientation == Qt::Horizontal) ? secondHandleRect().x() : secondHandleRect().y(); if (mFirstHandlePressed && m_mode.testFlag(LeftHandle)) { if (posValue - mDelta + scHandleSideLength / 2 <= secondHandleRectPosValue) { setLowerValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2) * 1.0 / validLength() * interval() + m_minimum); } else { setLowerValue(m_upperValue); } } else if (mSecondHandlePressed && m_mode.testFlag(RightHandle)) { if (firstHandleRectPosValue + scHandleSideLength * (m_mode.testFlag(DoubleHandles) ? 1.5 : 0.5) <= posValue - mDelta) { setUpperValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2 - (m_mode.testFlag(DoubleHandles) ? scHandleSideLength : 0)) * 1.0 / validLength() * interval() + m_minimum); } else { setUpperValue(m_lowerValue); } } } } void RangeSlider::mouseReleaseEvent(QMouseEvent *) { mFirstHandlePressed = false; mSecondHandlePressed = false; } void RangeSlider::changeEvent(QEvent * e) { if (e->type() == QEvent::EnabledChange) { update(); } } QSize RangeSlider::minimumSizeHint() const { return QSize(scHandleSideLength * 2 + scLeftRightMargin * 2, scHandleSideLength); } void RangeSlider::setLowerValue(int value) { if (value > m_maximum) value = m_maximum; if (value < m_minimum) value = m_minimum; m_lowerValue = value; emit lowerValueChanged(m_lowerValue); emit valueChanged(m_lowerValue, m_upperValue); update(); } void RangeSlider::setUpperValue(int value) { if (value > m_maximum) value = m_maximum; if (value < m_minimum) value = m_minimum; m_upperValue = value; emit upperValueChanged(m_upperValue); emit valueChanged(m_lowerValue, m_upperValue); update(); } void RangeSlider::setMinimum(int minimum) { if (minimum <= m_maximum) { m_minimum = minimum; } else { int oldMax = m_maximum; m_minimum = oldMax; m_maximum = minimum; } update(); setLowerValue(m_minimum); setUpperValue(m_maximum); emit minimumChanged(m_maximum); emit rangeChanged(m_minimum, m_maximum); } void RangeSlider::setMaximum(int maximum) { if (maximum >= m_minimum) { m_maximum = maximum; } else { int oldMin = m_minimum; m_maximum = oldMin; m_minimum = maximum; } update(); setLowerValue(m_minimum); setUpperValue(m_maximum); emit maximumChanged(m_maximum); emit rangeChanged(m_minimum, m_maximum); } int RangeSlider::validLength() const { int len = (orientation == Qt::Horizontal) ? width() : height(); return len - scLeftRightMargin * 2 - scHandleSideLength * (m_mode.testFlag(DoubleHandles) ? 2 : 1); } int RangeSlider::interval() const { return m_maximum - m_minimum; } void RangeSlider::setRange(int minimum, int maximum) { setMinimum(minimum); setMaximum(maximum); } void RangeSlider::setMode(Mode m) { m_mode = m; update(); emit modeChanged(m_mode); }