271 lines
8.9 KiB
C++
271 lines
8.9 KiB
C++
#include "rangeslider.h"
|
|
|
|
#include "qad_types.h"
|
|
|
|
#include <QPalette>
|
|
|
|
|
|
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);
|
|
}
|