Skip to content
Snippets Groups Projects
Scrollbar.cc 3.92 KiB
Newer Older
  • Learn to ignore specific revisions
  • pixhawk's avatar
    pixhawk committed
    #include <qstyle.h>
    #include <qstyleoption.h>
    #include "Scrollbar.h"
    
    ScrollBar::ScrollBar(QWidget * parent):
        QScrollBar(parent)
    {
        init();
    }
    
    ScrollBar::ScrollBar(Qt::Orientation o, 
            QWidget *parent):
        QScrollBar(o, parent)
    {
        init();
    }
    
    ScrollBar::ScrollBar(double minBase, double maxBase, 
            Qt::Orientation o, QWidget *parent):
        QScrollBar(o, parent)
    {
        init();
        setBase(minBase, maxBase);
        moveSlider(minBase, maxBase);
    }
    
    void ScrollBar::init()
    {
        d_inverted = orientation() == Qt::Vertical;
        d_baseTicks = 1000000;
        d_minBase = 0.0;
        d_maxBase = 1.0;
        moveSlider(d_minBase, d_maxBase);
    
        connect(this, SIGNAL(sliderMoved(int)), SLOT(catchSliderMoved(int)));
        connect(this, SIGNAL(valueChanged(int)), SLOT(catchValueChanged(int)));
    }
    
    void ScrollBar::setInverted(bool inverted)
    {
        if ( d_inverted != inverted )
        {
            d_inverted = inverted;
            moveSlider(minSliderValue(), maxSliderValue());
        }
    }
    
    bool ScrollBar::isInverted() const
    {
        return d_inverted;
    }
    
    void ScrollBar::setBase(double min, double max)
    {
        if ( min != d_minBase || max != d_maxBase )
        {
            d_minBase = min;
            d_maxBase = max;
    
            moveSlider(minSliderValue(), maxSliderValue());
        }
    }
    
    void ScrollBar::moveSlider(double min, double max)
    {
        const int sliderTicks = qRound((max - min) / 
            (d_maxBase - d_minBase) * d_baseTicks);
    
        // setRange initiates a valueChanged of the scrollbars
        // in some situations. So we block
        // and unblock the signals.
    
        blockSignals(true);
    
        setRange(sliderTicks / 2, d_baseTicks - sliderTicks / 2);
        int steps = sliderTicks / 200;
        if ( steps <= 0 )
            steps = 1;
    
    #if QT_VERSION < 0x040000
        setSteps(steps, sliderTicks);
    #else
        setSingleStep(steps);
        setPageStep(sliderTicks);
    #endif
    
        int tick = mapToTick(min + (max - min) / 2);
        if ( isInverted() )
            tick = d_baseTicks - tick;
    
    #if QT_VERSION < 0x040000
        directSetValue(tick);
        rangeChange();
    #else
        setSliderPosition(tick);
    #endif
        blockSignals(false);
    }
    
    double ScrollBar::minBaseValue() const
    {
        return d_minBase;
    }
    
    double ScrollBar::maxBaseValue() const
    {
        return d_maxBase;
    }
    
    void ScrollBar::sliderRange(int value, double &min, double &max) const
    {
        if ( isInverted() )
            value = d_baseTicks - value;
    
        const int visibleTicks = pageStep();
    
        min = mapFromTick(value - visibleTicks / 2);
        max = mapFromTick(value + visibleTicks / 2);
    }
    
    double ScrollBar::minSliderValue() const
    {
        double min, dummy;
        sliderRange(value(), min, dummy);
    
        return min;
    }
    
    double ScrollBar::maxSliderValue() const
    {
        double max, dummy;
        sliderRange(value(), dummy, max);
    
        return max;
    }
    
    int ScrollBar::mapToTick(double v) const
    {   
        return (int) ( ( v - d_minBase) / (d_maxBase - d_minBase ) * d_baseTicks );
    }
    
    double ScrollBar::mapFromTick(int tick) const
    {   
        return d_minBase + ( d_maxBase - d_minBase ) * tick / d_baseTicks;
    }
    
    void ScrollBar::catchValueChanged(int value)
    {
        double min, max;
        sliderRange(value, min, max);
        emit valueChanged(orientation(), min, max);
    }
    
    void ScrollBar::catchSliderMoved(int value)
    {
        double min, max;
        sliderRange(value, min, max);
        emit sliderMoved(orientation(), min, max);
    }
    
    int ScrollBar::extent() const
    {
    #if QT_VERSION < 0x040000
        return style().pixelMetric(QStyle::PM_ScrollBarExtent, this);
    #else
        QStyleOptionSlider opt;
        opt.init(this);
        opt.subControls = QStyle::SC_None;
        opt.activeSubControls = QStyle::SC_None;
        opt.orientation = orientation();
        opt.minimum = minimum();
        opt.maximum = maximum();
        opt.sliderPosition = sliderPosition();
        opt.sliderValue = value();
        opt.singleStep = singleStep();
        opt.pageStep = pageStep();
        opt.upsideDown = invertedAppearance();
        if (orientation() == Qt::Horizontal)
            opt.state |= QStyle::State_Horizontal;
        return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this);
    #endif
    }