~ubuntu-branches/debian/sid/kexi/sid

« back to all changes in this revision

Viewing changes to src/widget/kexislider.cpp

  • Committer: Package Import Robot
  • Author(s): Pino Toscano
  • Date: 2017-06-24 20:10:10 UTC
  • Revision ID: package-import@ubuntu.com-20170624201010-5lrzd5r2vwthwifp
Tags: upstream-3.0.1.1
ImportĀ upstreamĀ versionĀ 3.0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2012 Oleg Kukharchuk <oleg.kuh@gmail.com>
 
3
 
 
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.
 
8
 
 
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.
 
13
 
 
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.
 
18
*/
 
19
 
 
20
#include "kexislider.h"
 
21
 
 
22
#include <QBoxLayout>
 
23
#include <QSpinBox>
 
24
#include <QPainter>
 
25
#include <QStyle>
 
26
#include <QSlider>
 
27
#include <QStyleOptionSlider>
 
28
 
 
29
 
 
30
class KexiSlider::Private
 
31
{
 
32
public:
 
33
    Private() {}
 
34
 
 
35
    Slider *slider;
 
36
    QSpinBox *spinBox;
 
37
    QBoxLayout *layout;
 
38
};
 
39
 
 
40
 
 
41
class Slider : public QSlider
 
42
{
 
43
    Q_OBJECT
 
44
public:
 
45
    explicit Slider(QWidget *parent) :
 
46
        QSlider(parent)
 
47
    {
 
48
 
 
49
    }
 
50
 
 
51
    QSize sizeHint() const
 
52
    {
 
53
        if (tickPosition() == QSlider::NoTicks)
 
54
            return QSlider::sizeHint();
 
55
 
 
56
        // preserve space for labels
 
57
        QSize extra(0,0);
 
58
 
 
59
        QFontMetrics fm(font());
 
60
 
 
61
        int h = fm.height() + 3;
 
62
        int w = fm.width(QString::number(maximum())) + 3;
 
63
 
 
64
        if (orientation() == Qt::Horizontal) {
 
65
            extra.setHeight(tickPosition() == QSlider::TicksBothSides ? h * 2 : h);
 
66
        } else {
 
67
            extra.setWidth(tickPosition() == QSlider::TicksBothSides ? w * 2 : w);
 
68
        }
 
69
 
 
70
        return QSlider::sizeHint() + extra;
 
71
    }
 
72
 
 
73
protected:
 
74
    virtual void paintEvent(QPaintEvent *ev)
 
75
    {
 
76
        if (tickPosition() == QSlider::NoTicks)
 
77
            return QSlider::paintEvent(ev);
 
78
 
 
79
        QPainter p(this);
 
80
        QStyleOptionSlider option;
 
81
        initStyleOption(&option);
 
82
 
 
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;
 
88
 
 
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;
 
94
 
 
95
        const QFontMetrics fm(fontMetrics());
 
96
        int h = fm.height() + 3;
 
97
        int w = fm.width(QString::number(option.maximum)) + 3;
 
98
 
 
99
        if(available<w)
 
100
            nextLabel = -1;
 
101
 
 
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;
 
105
 
 
106
        // Since there is no subrect for tickmarks do a translation here.
 
107
        p.save();
 
108
        p.translate(r.x(), r.y());
 
109
 
 
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);
 
113
 
 
114
        while(current <= option.maximum)
 
115
        {
 
116
 
 
117
            const int position(QStyle::sliderPositionFromValue(option.minimum, option.maximum,
 
118
                                                                 current, available, option.upsideDown) + fudge);
 
119
 
 
120
            // calculate positions
 
121
            if(option.orientation == Qt::Horizontal)
 
122
            {
 
123
 
 
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));
 
128
                }
 
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));
 
133
                }
 
134
            } else {
 
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));
 
139
                }
 
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));
 
144
                }
 
145
            }
 
146
 
 
147
            // go to next position
 
148
            if (current == nextLabel)
 
149
                nextLabel += interval*valStep;
 
150
            current += interval;
 
151
 
 
152
        }
 
153
        p.restore();
 
154
        option.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
 
155
 
 
156
        style()->proxy()->drawComplexControl(QStyle::CC_Slider, &option, &p, this);
 
157
    }
 
158
};
 
159
 
 
160
KexiSlider::KexiSlider(QWidget *parent)
 
161
    : QWidget(parent)
 
162
    , d(new Private)
 
163
{
 
164
    init(Qt::Horizontal);
 
165
}
 
166
 
 
167
KexiSlider::KexiSlider(Qt::Orientation orientation, QWidget *parent)
 
168
    : QWidget(parent)
 
169
    , d(new Private)
 
170
{
 
171
    init(orientation);
 
172
}
 
173
 
 
174
void KexiSlider::init(Qt::Orientation orientation)
 
175
{
 
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);
 
182
 
 
183
    d->layout->addWidget(d->spinBox,0, Qt::AlignVCenter);
 
184
    d->layout->addWidget(d->slider,0, Qt::AlignVCenter);
 
185
 
 
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)));
 
191
 
 
192
    setMaximum(100);
 
193
    setOrientation(orientation);
 
194
    setTickPosition(QSlider::TicksAbove);
 
195
}
 
196
 
 
197
KexiSlider::~KexiSlider()
 
198
{
 
199
    delete d;
 
200
}
 
201
 
 
202
void KexiSlider::setMinimum(int min)
 
203
{
 
204
    d->spinBox->setMinimum(min);
 
205
    d->slider->setMinimum(min);
 
206
}
 
207
 
 
208
void KexiSlider::setMaximum(int max)
 
209
{
 
210
    d->spinBox->setMaximum(max);
 
211
    d->slider->setMaximum(max);
 
212
}
 
213
 
 
214
void KexiSlider::setValue(int val)
 
215
{
 
216
    d->slider->setValue(val);
 
217
}
 
218
 
 
219
int KexiSlider::minimum() const
 
220
{
 
221
    return d->slider->minimum();
 
222
}
 
223
 
 
224
int KexiSlider::maximum() const
 
225
{
 
226
    return d->slider->maximum();
 
227
}
 
228
 
 
229
int KexiSlider::value() const
 
230
{
 
231
    return d->slider->value();
 
232
}
 
233
 
 
234
void KexiSlider::setPageStep(int step)
 
235
{
 
236
    d->slider->setPageStep(step);
 
237
}
 
238
 
 
239
int KexiSlider::pageStep() const
 
240
{
 
241
    return d->slider->pageStep();
 
242
}
 
243
 
 
244
void KexiSlider::setSingleStep(int step)
 
245
{
 
246
    d->spinBox->setSingleStep(step);
 
247
    d->slider->setSingleStep(step);
 
248
}
 
249
 
 
250
int KexiSlider::singleStep() const
 
251
{
 
252
    return d->slider->singleStep();
 
253
}
 
254
 
 
255
void KexiSlider::setOrientation(Qt::Orientation o)
 
256
{
 
257
    d->layout->removeWidget(d->spinBox);
 
258
    d->slider->setOrientation(o);
 
259
    if(o == Qt::Horizontal)
 
260
        d->layout->insertWidget(0, d->spinBox);
 
261
    else
 
262
        d->layout->addWidget(d->spinBox);
 
263
    updateLayout();
 
264
}
 
265
 
 
266
Qt::Orientation KexiSlider::orientation() const
 
267
{
 
268
    return d->slider->orientation();
 
269
}
 
270
 
 
271
void KexiSlider::setTickInterval(int ti)
 
272
{
 
273
    d->slider->setTickInterval(ti);
 
274
}
 
275
 
 
276
int KexiSlider::tickInterval() const
 
277
{
 
278
    return d->slider->tickInterval();
 
279
}
 
280
 
 
281
void KexiSlider::setTickPosition(QSlider::TickPosition pos)
 
282
{
 
283
    d->slider->setTickPosition(pos);
 
284
    updateLayout();
 
285
}
 
286
 
 
287
QSlider::TickPosition KexiSlider::tickPosition() const
 
288
{
 
289
    return d->slider->tickPosition();
 
290
}
 
291
 
 
292
void KexiSlider::setShowEditor(bool show)
 
293
{
 
294
    d->spinBox->setVisible(show);
 
295
 
 
296
}
 
297
 
 
298
bool KexiSlider::showEditor() const
 
299
{
 
300
    return d->spinBox->isVisible();
 
301
}
 
302
 
 
303
void KexiSlider::updateLayout()
 
304
{
 
305
    d->layout->setDirection(orientation() == Qt::Horizontal ?
 
306
                        QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
 
307
 
 
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);
 
314
    } else {
 
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);
 
320
        } else {
 
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);
 
325
        }
 
326
    }
 
327
}
 
328
 
 
329
#include "kexislider.moc"