1 #include <qstyle.h>
2 #if QT_VERSION >= 0x040000
3 #include <qstyleoption.h>
4 #endif
5 #include "scrollbar.h"
6 
ScrollBar(QWidget * parent)7 ScrollBar::ScrollBar(QWidget * parent):
8     QScrollBar(parent)
9 {
10     init();
11 }
12 
ScrollBar(Qt::Orientation o,QWidget * parent)13 ScrollBar::ScrollBar(Qt::Orientation o,
14         QWidget *parent):
15     QScrollBar(o, parent)
16 {
17     init();
18 }
19 
ScrollBar(double minBase,double maxBase,Qt::Orientation o,QWidget * parent)20 ScrollBar::ScrollBar(double minBase, double maxBase,
21         Qt::Orientation o, QWidget *parent):
22     QScrollBar(o, parent)
23 {
24     init();
25     setBase(minBase, maxBase);
26     moveSlider(minBase, maxBase);
27 }
28 
init()29 void ScrollBar::init()
30 {
31     d_inverted = orientation() == Qt::Vertical;
32     d_baseTicks = 1000000;
33     d_minBase = 0.0;
34     d_maxBase = 1.0;
35     moveSlider(d_minBase, d_maxBase);
36 
37     connect(this, SIGNAL(sliderMoved(int)), SLOT(catchSliderMoved(int)));
38     connect(this, SIGNAL(valueChanged(int)), SLOT(catchValueChanged(int)));
39 }
40 
setInverted(bool inverted)41 void ScrollBar::setInverted(bool inverted)
42 {
43     if ( d_inverted != inverted )
44     {
45         d_inverted = inverted;
46         moveSlider(minSliderValue(), maxSliderValue());
47     }
48 }
49 
isInverted() const50 bool ScrollBar::isInverted() const
51 {
52     return d_inverted;
53 }
54 
setBase(double min,double max)55 void ScrollBar::setBase(double min, double max)
56 {
57     if ( min != d_minBase || max != d_maxBase )
58     {
59         d_minBase = min;
60         d_maxBase = max;
61 
62         moveSlider(minSliderValue(), maxSliderValue());
63     }
64 }
65 
moveSlider(double min,double max)66 void ScrollBar::moveSlider(double min, double max)
67 {
68     const int sliderTicks = qRound((max - min) /
69         (d_maxBase - d_minBase) * d_baseTicks);
70 
71     // setRange initiates a valueChanged of the scrollbars
72     // in some situations. So we block
73     // and unblock the signals.
74 
75     blockSignals(true);
76 
77     setRange(sliderTicks / 2, d_baseTicks - sliderTicks / 2);
78     int steps = sliderTicks / 200;
79     if ( steps <= 0 )
80         steps = 1;
81 
82 #if QT_VERSION < 0x040000
83     setSteps(steps, sliderTicks);
84 #else
85     setSingleStep(steps);
86     setPageStep(sliderTicks);
87 #endif
88 
89     int tick = mapToTick(min + (max - min) / 2);
90     if ( isInverted() )
91         tick = d_baseTicks - tick;
92 
93 #if QT_VERSION < 0x040000
94     directSetValue(tick);
95     rangeChange();
96 #else
97     setSliderPosition(tick);
98 #endif
99     blockSignals(false);
100 }
101 
minBaseValue() const102 double ScrollBar::minBaseValue() const
103 {
104     return d_minBase;
105 }
106 
maxBaseValue() const107 double ScrollBar::maxBaseValue() const
108 {
109     return d_maxBase;
110 }
111 
sliderRange(int value,double & min,double & max) const112 void ScrollBar::sliderRange(int value, double &min, double &max) const
113 {
114     if ( isInverted() )
115         value = d_baseTicks - value;
116 
117     const int visibleTicks = pageStep();
118 
119     min = mapFromTick(value - visibleTicks / 2);
120     max = mapFromTick(value + visibleTicks / 2);
121 }
122 
minSliderValue() const123 double ScrollBar::minSliderValue() const
124 {
125     double min, dummy;
126     sliderRange(value(), min, dummy);
127 
128     return min;
129 }
130 
maxSliderValue() const131 double ScrollBar::maxSliderValue() const
132 {
133     double max, dummy;
134     sliderRange(value(), dummy, max);
135 
136     return max;
137 }
138 
mapToTick(double v) const139 int ScrollBar::mapToTick(double v) const
140 {
141     return (int) ( ( v - d_minBase) / (d_maxBase - d_minBase ) * d_baseTicks );
142 }
143 
mapFromTick(int tick) const144 double ScrollBar::mapFromTick(int tick) const
145 {
146     return d_minBase + ( d_maxBase - d_minBase ) * tick / d_baseTicks;
147 }
148 
catchValueChanged(int value)149 void ScrollBar::catchValueChanged(int value)
150 {
151     double min, max;
152     sliderRange(value, min, max);
153     emit valueChanged(orientation(), min, max);
154 }
155 
catchSliderMoved(int value)156 void ScrollBar::catchSliderMoved(int value)
157 {
158     double min, max;
159     sliderRange(value, min, max);
160     emit sliderMoved(orientation(), min, max);
161 }
162 
extent() const163 int ScrollBar::extent() const
164 {
165 #if QT_VERSION < 0x040000
166     return style().pixelMetric(QStyle::PM_ScrollBarExtent, this);
167 #else
168     QStyleOptionSlider opt;
169     opt.init(this);
170     opt.subControls = QStyle::SC_None;
171     opt.activeSubControls = QStyle::SC_None;
172     opt.orientation = orientation();
173     opt.minimum = minimum();
174     opt.maximum = maximum();
175     opt.sliderPosition = sliderPosition();
176     opt.sliderValue = value();
177     opt.singleStep = singleStep();
178     opt.pageStep = pageStep();
179     opt.upsideDown = invertedAppearance();
180     if (orientation() == Qt::Horizontal)
181         opt.state |= QStyle::State_Horizontal;
182     return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this);
183 #endif
184 }
185