1
/* This file is part of the KDE project
2
Copyright (C) 2012 Oleg Kukharchuk <oleg.kuh@gmail.com>
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Library General Public
6
License as published by the Free Software Foundation; either
7
version 2 of the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this program; see the file COPYING. If not, write to
16
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1301, USA.
20
#include "kexislider.h"
27
#include <QStyleOptionSlider>
30
class KexiSlider::Private
41
class Slider : public QSlider
45
explicit Slider(QWidget *parent) :
51
QSize sizeHint() const
53
if (tickPosition() == QSlider::NoTicks)
54
return QSlider::sizeHint();
56
// preserve space for labels
59
QFontMetrics fm(font());
61
int h = fm.height() + 3;
62
int w = fm.width(QString::number(maximum())) + 3;
64
if (orientation() == Qt::Horizontal) {
65
extra.setHeight(tickPosition() == QSlider::TicksBothSides ? h * 2 : h);
67
extra.setWidth(tickPosition() == QSlider::TicksBothSides ? w * 2 : w);
70
return QSlider::sizeHint() + extra;
74
virtual void paintEvent(QPaintEvent *ev)
76
if (tickPosition() == QSlider::NoTicks)
77
return QSlider::paintEvent(ev);
80
QStyleOptionSlider option;
81
initStyleOption(&option);
83
const QSlider::TickPosition ticks( option.tickPosition );
84
const int available(style()->proxy()->pixelMetric(QStyle::PM_SliderSpaceAvailable, &option, this));
85
int interval = option.tickInterval;
86
if( interval < 1 ) interval = option.pageStep;
87
if( interval < 1 ) return;
89
const QRect r(option.rect);
90
const QPalette palette(option.palette);
91
const int fudge(style()->proxy()->pixelMetric(QStyle::PM_SliderLength, &option, this) / 2);
92
int current(option.minimum);
93
int nextLabel = current;
95
const QFontMetrics fm(fontMetrics());
96
int h = fm.height() + 3;
97
int w = fm.width(QString::number(option.maximum)) + 3;
102
qreal i = qreal(available) / qreal(orientation() == Qt::Horizontal ? w : h);
103
qreal t = qreal(option.maximum)/qreal(interval);
104
int valStep = t/ i + 1;
106
// Since there is no subrect for tickmarks do a translation here.
108
p.translate(r.x(), r.y());
110
p.setPen(palette.color(QPalette::WindowText));
111
int extra = (option.tickPosition == QSlider::TicksBothSides ? 2 : 1);
112
int tickSize(option.orientation == Qt::Horizontal ? (r.height() - h*extra)/3:(r.width() - w*extra)/3);
114
while(current <= option.maximum)
117
const int position(QStyle::sliderPositionFromValue(option.minimum, option.maximum,
118
current, available, option.upsideDown) + fudge);
120
// calculate positions
121
if(option.orientation == Qt::Horizontal)
124
if (ticks & QSlider::TicksAbove) {
125
p.drawLine(position, h, position, tickSize + h);
126
if(current == nextLabel)
127
p.drawText(QRect(position - w/2, 0, w, h), Qt::AlignHCenter, QString::number(current));
129
if (ticks & QSlider::TicksBelow) {
130
p.drawLine( position, r.height() - h - tickSize, position, r.height() - h );
131
if(current == nextLabel)
132
p.drawText(QRect(position - w/2, r.height() - h + 3, w, h), Qt::AlignHCenter, QString::number(current));
135
if (ticks & QSlider::TicksAbove) {
136
p.drawLine(w, position, tickSize + w, position);
137
if(current == nextLabel)
138
p.drawText(QRect(0, position - h/2, w - 3, h), Qt::AlignRight | Qt::AlignVCenter, QString::number(current));
140
if (ticks & QSlider::TicksBelow) {
141
p.drawLine(r.width() - w - tickSize, position, r.width() - w, position );
142
if(current == nextLabel)
143
p.drawText(QRect(r.width() - w + 3, position - h/2, w, h), Qt::AlignVCenter, QString::number(current));
147
// go to next position
148
if (current == nextLabel)
149
nextLabel += interval*valStep;
154
option.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
156
style()->proxy()->drawComplexControl(QStyle::CC_Slider, &option, &p, this);
160
KexiSlider::KexiSlider(QWidget *parent)
164
init(Qt::Horizontal);
167
KexiSlider::KexiSlider(Qt::Orientation orientation, QWidget *parent)
174
void KexiSlider::init(Qt::Orientation orientation)
176
d->layout=new QBoxLayout(QBoxLayout::LeftToRight, this);
177
d->layout->setSpacing(2);
178
d->layout->setMargin(0);
179
d->slider = new Slider(this);
180
d->spinBox = new QSpinBox(this);
181
d->spinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
183
d->layout->addWidget(d->spinBox,0, Qt::AlignVCenter);
184
d->layout->addWidget(d->slider,0, Qt::AlignVCenter);
186
connect(d->slider, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
187
connect(d->slider, SIGNAL(sliderPressed()), this, SIGNAL(sliderPressed()));
188
connect(d->slider, SIGNAL(sliderReleased()), this, SIGNAL(sliderReleased()));
189
connect(d->slider, SIGNAL(valueChanged(int)), d->spinBox, SLOT(setValue(int)));
190
connect(d->spinBox, SIGNAL(valueChanged(int)), d->slider, SLOT(setValue(int)));
193
setOrientation(orientation);
194
setTickPosition(QSlider::TicksAbove);
197
KexiSlider::~KexiSlider()
202
void KexiSlider::setMinimum(int min)
204
d->spinBox->setMinimum(min);
205
d->slider->setMinimum(min);
208
void KexiSlider::setMaximum(int max)
210
d->spinBox->setMaximum(max);
211
d->slider->setMaximum(max);
214
void KexiSlider::setValue(int val)
216
d->slider->setValue(val);
219
int KexiSlider::minimum() const
221
return d->slider->minimum();
224
int KexiSlider::maximum() const
226
return d->slider->maximum();
229
int KexiSlider::value() const
231
return d->slider->value();
234
void KexiSlider::setPageStep(int step)
236
d->slider->setPageStep(step);
239
int KexiSlider::pageStep() const
241
return d->slider->pageStep();
244
void KexiSlider::setSingleStep(int step)
246
d->spinBox->setSingleStep(step);
247
d->slider->setSingleStep(step);
250
int KexiSlider::singleStep() const
252
return d->slider->singleStep();
255
void KexiSlider::setOrientation(Qt::Orientation o)
257
d->layout->removeWidget(d->spinBox);
258
d->slider->setOrientation(o);
259
if(o == Qt::Horizontal)
260
d->layout->insertWidget(0, d->spinBox);
262
d->layout->addWidget(d->spinBox);
266
Qt::Orientation KexiSlider::orientation() const
268
return d->slider->orientation();
271
void KexiSlider::setTickInterval(int ti)
273
d->slider->setTickInterval(ti);
276
int KexiSlider::tickInterval() const
278
return d->slider->tickInterval();
281
void KexiSlider::setTickPosition(QSlider::TickPosition pos)
283
d->slider->setTickPosition(pos);
287
QSlider::TickPosition KexiSlider::tickPosition() const
289
return d->slider->tickPosition();
292
void KexiSlider::setShowEditor(bool show)
294
d->spinBox->setVisible(show);
298
bool KexiSlider::showEditor() const
300
return d->spinBox->isVisible();
303
void KexiSlider::updateLayout()
305
d->layout->setDirection(orientation() == Qt::Horizontal ?
306
QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
308
if (tickPosition() == QSlider::TicksBothSides
309
|| tickPosition() == QSlider::NoTicks) {
310
d->layout->setAlignment(d->slider, orientation() == Qt::Horizontal ?
311
Qt::AlignVCenter :Qt::AlignHCenter);
312
d->layout->setAlignment(d->spinBox, orientation() == Qt::Horizontal ?
313
Qt::AlignVCenter :Qt::AlignHCenter);
315
if (orientation() == Qt::Horizontal) {
316
d->layout->setAlignment(d->slider,
317
tickPosition() == QSlider::TicksAbove ? Qt::AlignBottom : Qt::AlignTop);
318
d->layout->setAlignment(d->spinBox,
319
tickPosition() == QSlider::TicksAbove ? Qt::AlignBottom : Qt::AlignTop);
321
d->layout->setAlignment(d->slider,
322
tickPosition() == QSlider::TicksLeft ? Qt::AlignRight : Qt::AlignLeft);
323
d->layout->setAlignment(d->spinBox,
324
tickPosition() == QSlider::TicksLeft ? Qt::AlignRight : Qt::AlignLeft);
329
#include "kexislider.moc"