/* * Copyright (C) 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "customslider.h" #include #include CustomSlider::Interpolator::~Interpolator() { } double CustomSlider::Interpolator::absolute(double relative, double minimum, double maximum) const { return relative * (maximum - minimum) + minimum; } double CustomSlider::Interpolator::relative(double absolute, double minimum, double maximum) const { return (absolute - minimum) / (maximum - minimum); } double CustomSlider::SqrtInterpolator::absolute( double relative, double minimum, double maximum) const { relative *= relative; return Interpolator::absolute(relative, minimum, maximum); } double CustomSlider::SqrtInterpolator::relative( double absolute, double minimum, double maximum) const { double value = Interpolator::relative(absolute, minimum, maximum); return std::sqrt(value); } const CustomSlider::Interpolator CustomSlider::lerp; CustomSlider::CustomSlider(QWidget *parent) : QSlider(parent), m_min(0.0), m_max(1.0), m_interpolator(&lerp) { setSingleStep(10); setPageStep(100); updateValue(); updateRange(size()); connect(this, SIGNAL(actionTriggered(int)), SLOT(updateValue())); } void CustomSlider::resizeEvent(QResizeEvent *e) { QSlider::resizeEvent(e); updateRange(e->size()); } const CustomSlider::Interpolator *CustomSlider::interpolator() const { return m_interpolator; } void CustomSlider::setInterpolator(const CustomSlider::Interpolator *v) { m_interpolator = v; } void CustomSlider::setDoubleMinimum(double v) { m_min = v; } double CustomSlider::doubleMinimum() const { return m_min; } void CustomSlider::setDoubleMaximum(double v) { m_max = v; } double CustomSlider::doubleMaximum() const { return m_max; } double CustomSlider::doubleValue() const { return qBound(m_min, m_value, m_max); } void CustomSlider::setDoubleValue(double v) { if (m_value == v) { return; } m_value = v; int oldIntValue = value(); moveSlider(); if (value() != oldIntValue) { Q_EMIT valueChanged(doubleValue()); } } double CustomSlider::intToDouble(int v) const { double relative = lerp.relative(v, minimum(), maximum()); return m_interpolator->absolute(relative, m_min, m_max); } void CustomSlider::updateValue() { m_value = intToDouble(sliderPosition()); Q_EMIT valueChanged(doubleValue()); } double CustomSlider::fixup(double v) const { return intToDouble(doubleToInt(v)); } int CustomSlider::doubleToInt(double v) const { double relative = m_interpolator->relative(v, m_min, m_max); double absolute = lerp.absolute(relative, minimum(), maximum()); return static_cast(std::floor(absolute + 0.5)); } void CustomSlider::moveSlider() { setValue(doubleToInt(doubleValue())); } void CustomSlider::updateRange(const QSize &s) { setRange(0, (orientation() == Qt::Horizontal) ? s.width() : s.height()); moveSlider(); }