slider.cpp 5.71 KB
#include "slider.h"

#include <QMouseEvent>
#include <QPainter>
#include <QDebug>

Slider::Slider(QWidget *parent) : QWidget(parent),
    isSliderDown_(false),
    sliderPosition_(0), value_(0), minimum_(0), maximum_(1),
    subVisible_(true),
    focused(false), isSliderMoved_(false),
    tickInterval(0), bigTickInterval(0)
{
    groove.load(":/images/slider/groove.png");
    sub.load(":/images/slider/humidity.png");
    handle.load(":/images/slider/handle_big.png");
    updatePixmapPosition();
}

void Slider::setSubPixmap(const QPixmap &pixmap)
{
    sub = pixmap;
}

void Slider::setSubPixmap(const QString &fileName)
{
    setSubPixmap(QPixmap(fileName));
}

void Slider::setSubVisible(bool visible)
{
    if (subVisible_ == visible)
        return;

    subVisible_ = visible;

    update();
}

void Slider::setRange(int min, int max)
{
    if (minimum_ == min && maximum_ == max)
        return;

    minimum_ = min;
    maximum_ = max;

    if (value_ < min)
        setValue(min);
    else if (value_ > max)
        setValue(max);

    update();
}

void Slider::setMinimum(int min)
{
    if (minimum_ == min)
        return;

    minimum_ = min;

    if (value_ < min)
        setValue(min);

    update();
}

void Slider::setMaximum(int max)
{
    if (maximum_ == max)
        return;

    maximum_ = max;

    if (value_ > max)
        setValue(max);

    update();
}

int Slider::value()
{
    return value_;
}

bool Slider::isSliderDown()
{
    return isSliderDown_;
}

int Slider::sliderPosition()
{
    return sliderPosition_;
}

void Slider::setSliderPosition(int value)
{
    value = qBound(minimum_, value, maximum_);

    if (sliderPosition_ == value)
        return;

    sliderPosition_ = value;
    if (focused)
        isSliderMoved_ = true;

    emit sliderMoved(value);

    update();
}

bool Slider::isSliderMoved()
{
    return isSliderMoved_;
}

void Slider::focusInEvent(QFocusEvent */*event*/)
{
    focused = true;
}

void Slider::focusOutEvent(QFocusEvent *event)
{
    QWidget::focusOutEvent(event);

    focused = false;

    if (isSliderMoved_)
    {
        isSliderMoved_ = false;
        value_ = sliderPosition_;
        emit valueChanged(value_);
    }
}

void Slider::keyPressEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case 0x01000032:    // Turn left
        decrease();
        break;
    case 0x01000031:    // Push
        event->ignore();
        break;
    case 0x01000030:    // Turn right
        increase();
        break;
    }
}

void Slider::keyReleaseEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case 0x01000032:    // Turn left
        decrease();
        break;
    case 0x01000031:    // Push
        event->ignore();
        break;
    case 0x01000030:    // Turn right
        increase();
        break;
    }
}

void Slider::mouseMoveEvent(QMouseEvent *event)
{
    if (!isSliderDown_)
        return;

    setSliderPosition(calcSliderPosition(event->x()));
}

void Slider::mousePressEvent(QMouseEvent *event)
{
    isSliderDown_ = true;

    emit sliderPressed();

    setSliderPosition(calcSliderPosition(event->x()));
}

void Slider::mouseReleaseEvent(QMouseEvent */*event*/)
{
    isSliderDown_ = false;

    emit sliderReleased();
}

void Slider::paintEvent(QPaintEvent */*event*/)
{
    QPainter painter(this);
    painter.drawPixmap(groovePoint, groove);

    QPen tickPen(QColor(71, 71, 71));
    tickPen.setWidth(2);
    painter.setPen(tickPen);

    if (tickInterval)
        for (int tick = minimum_; tick <= maximum_; tick += tickInterval)
        {
            int x = subPoint.x() + calcSubLength(tick);
            painter.drawLine(x, groovePoint.y() + 22, x, groovePoint.y() + 28);
        }
    else
        foreach (int tick, ticks)
        {
            int x = subPoint.x() + calcSubLength(tick);
            painter.drawLine(x, groovePoint.y() + 22, x, groovePoint.y() + 28);
        }

    if (bigTickInterval)
        for (int tick = minimum_; tick <= maximum_; tick += bigTickInterval)
        {
            int x = subPoint.x() + calcSubLength(tick);
            painter.drawLine(x, groovePoint.y() + 22, x, groovePoint.y() + 33);
        }
    else
        foreach (int tick, bigTicks)
        {
            int x = subPoint.x() + calcSubLength(tick);
            painter.drawLine(x, groovePoint.y() + 22, x, groovePoint.y() + 33);
        }

    if (subVisible_)
    {
        int subLength = calcSubLength(sliderPosition_);
        if (subLength > 0)
            painter.drawPixmap(subPoint, sub, QRect(0, 0, subLength, sub.height()));

        QPoint handlePoint(subPoint.x() + subLength - handle.width() / 2, (height() - handle.height()) / 2);
        painter.drawPixmap(handlePoint, handle);
    }
}

void Slider::resizeEvent(QResizeEvent */*event*/)
{
    updatePixmapPosition();
}

int Slider::calcSliderPosition(int mouseX)
{
    int x = qBound(grooveMin, mouseX, grooveMax);
    qreal pos = (qreal) (x - grooveMin) / (grooveMax - grooveMin) * (maximum_ - minimum_) + minimum_;
    return qRound(pos);
}

int Slider::calcSubLength(int value)
{
    return handle.width() / 4 + (sub.width() - handle.width() / 2) * (value - minimum_) / (maximum_ - minimum_);
}

void Slider::updatePixmapPosition()
{
    grooveMin = (width() - sub.width()) / 2;
    grooveMax = width() - grooveMin;

    groovePoint = QPoint((width() - groove.width()) / 2, (height() - groove.height()) / 2);
    subPoint = QPoint((width() - sub.width()) / 2, (height() - sub.height()) / 2);
}

void Slider::setValue(int value)
{
    value = qBound(minimum_, value, maximum_);

    setSliderPosition(value);

    if (value == value_)
        return;

    value_ = value;

    emit valueChanged(value);
}

void Slider::increase()
{
    setSliderPosition(sliderPosition_ + 1);
}

void Slider::decrease()
{
    setSliderPosition(sliderPosition_ - 1);
}