// %flair:license{ // This file is part of the Flair framework distributed under the // CECILL-C License, Version 1.0. // %flair:license} #include #include #include "Scrollbar.h" ScrollBar::ScrollBar(QWidget * parent): QScrollBar(parent) { init(); } ScrollBar::ScrollBar(Qt::Orientation o, QWidget *parent): QScrollBar(o, parent) { init(); } ScrollBar::ScrollBar(float minBase, float maxBase, Qt::Orientation o, QWidget *parent): QScrollBar(o, parent) { init(); setBase(minBase, maxBase); moveSlider(minBase, maxBase); } void ScrollBar::init(void) { 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(void) const { return d_inverted; } void ScrollBar::setBase(float min, float max) { if ( min != d_minBase || max != d_maxBase ) { d_minBase = min; d_maxBase = max; moveSlider(minSliderValue(), maxSliderValue()); } } void ScrollBar::moveSlider(float min, float 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; setSingleStep(steps); setPageStep(sliderTicks); int tick = mapToTick(min + (max - min) / 2); if ( isInverted() ) tick = d_baseTicks - tick; setSliderPosition(tick); blockSignals(false); } float ScrollBar::minBaseValue(void) const { return d_minBase; } float ScrollBar::maxBaseValue(void) const { return d_maxBase; } void ScrollBar::sliderRange(int value, float &min, float &max) const { if ( isInverted() ) value = d_baseTicks - value; const int visibleTicks = pageStep(); min = mapFromTick(value - visibleTicks / 2); max = mapFromTick(value + visibleTicks / 2); } float ScrollBar::minSliderValue(void) const { float min, dummy; sliderRange(value(), min, dummy); return min; } float ScrollBar::maxSliderValue(void) const { float max, dummy; sliderRange(value(), dummy, max); return max; } int ScrollBar::mapToTick(float v) const { return (int) ( ( v - d_minBase) / (d_maxBase - d_minBase ) * d_baseTicks ); } float ScrollBar::mapFromTick(int tick) const { return d_minBase + ( d_maxBase - d_minBase ) * tick / d_baseTicks; } void ScrollBar::catchValueChanged(int value) { float min, max; sliderRange(value, min, max); Q_EMIT valueChanged(orientation(), min, max); } void ScrollBar::catchSliderMoved(int value) { float min, max; sliderRange(value, min, max); Q_EMIT sliderMoved(orientation(), min, max); } int ScrollBar::extent(void) const { 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); }