KWidgetsAddons

kselector.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1997 Martin Jones <mjones@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kselector.h"
9
10#include <QPaintEvent>
11#include <QPainter>
12#include <QPixmap>
13#include <QStyle>
14#include <QStyleOption>
15
16//-----------------------------------------------------------------------------
17/*
18 * 1D value selector with contents drawn by derived class.
19 * See KColorDialog for example.
20 */
21
22#define ARROWSIZE 5
23
24class KSelectorPrivate
25{
26public:
27 bool m_indent = true;
29};
30
31class KGradientSelectorPrivate
32{
33public:
34 KGradientSelectorPrivate(KGradientSelector *qq)
35 : q(qq)
36 {
37 }
38
40 QLinearGradient gradient;
41 QString text1;
42 QString text2;
43};
44
46 : QAbstractSlider(parent)
47 , d(new KSelectorPrivate)
48{
50}
51
53 : QAbstractSlider(parent)
54 , d(new KSelectorPrivate)
55{
57 if (o == Qt::Horizontal) {
59 }
60}
61
62KSelector::~KSelector() = default;
63
65{
66 d->m_indent = i;
67}
68
69bool KSelector::indent() const
70{
71 return d->m_indent;
72}
73
75{
76 int w = indent() ? style()->pixelMetric(QStyle::PM_DefaultFrameWidth) : 0;
77 // TODO: is the height:width ratio of an indicator arrow always 2:1? hm.
78 int iw = (w < ARROWSIZE) ? ARROWSIZE : w;
79
80 if (orientation() == Qt::Vertical) {
81 if (arrowDirection() == Qt::RightArrow) {
82 return QRect(w + ARROWSIZE, //
83 iw,
84 width() - w * 2 - ARROWSIZE,
85 height() - iw * 2);
86 } else {
87 return QRect(w, //
88 iw,
89 width() - w * 2 - ARROWSIZE,
90 height() - iw * 2);
91 }
92 } else { // Qt::Horizontal
93 if (arrowDirection() == Qt::UpArrow) {
94 return QRect(iw, //
95 w,
96 width() - 2 * iw,
97 height() - w * 2 - ARROWSIZE);
98 } else {
99 return QRect(iw, //
100 w + ARROWSIZE,
101 width() - 2 * iw,
102 height() - w * 2 - ARROWSIZE);
103 }
104 }
105}
106
107void KSelector::paintEvent(QPaintEvent *)
108{
109 QPainter painter;
111 int iw = (w < ARROWSIZE) ? ARROWSIZE : w;
112
113 painter.begin(this);
114
115 if (indent()) {
117 opt.initFrom(this);
118 opt.state = QStyle::State_Sunken;
119 if (orientation() == Qt::Vertical) {
120 opt.rect.adjust(0, iw - w, -5, w - iw);
121 } else {
122 opt.rect.adjust(iw - w, 0, w - iw, -5);
123 }
124 QBrush oldBrush = painter.brush();
125 painter.setBrush(Qt::NoBrush);
126 style()->drawPrimitive(QStyle::PE_Frame, &opt, &painter, this);
127 painter.setBrush(oldBrush);
128 }
129
130 drawContents(&painter);
131
132 QPoint pos = calcArrowPos(value());
133 drawArrow(&painter, pos);
134
135 painter.end();
136}
137
138void KSelector::mousePressEvent(QMouseEvent *e)
139{
140 setSliderDown(true);
141 moveArrow(e->pos());
142}
143
144void KSelector::mouseMoveEvent(QMouseEvent *e)
145{
146 moveArrow(e->pos());
147}
148
149void KSelector::mouseReleaseEvent(QMouseEvent *e)
150{
151 moveArrow(e->pos());
152 setSliderDown(false);
153}
154
155void KSelector::wheelEvent(QWheelEvent *e)
156{
157 int val = value() + e->angleDelta().y() / 120;
158 setSliderDown(true);
159 setValue(val);
160 setSliderDown(false);
161}
162
163void KSelector::moveArrow(const QPoint &pos)
164{
165 int val;
167 int iw = (w < ARROWSIZE) ? ARROWSIZE : w;
168
169 if (orientation() == Qt::Vertical) {
170 val = (maximum() - minimum()) * (height() - pos.y() - iw) / (height() - iw * 2) + minimum();
171 } else {
172 val = (maximum() - minimum()) * (pos.x() - iw) / (width() - iw * 2) + minimum();
173 }
174
175 setValue(val);
176 update();
177}
178
179QPoint KSelector::calcArrowPos(int val)
180{
181 QPoint p;
183 int iw = (w < ARROWSIZE) ? ARROWSIZE : w;
184
185 if (orientation() == Qt::Vertical) {
186 p.setY(height() - iw - 1 - (height() - 2 * iw - 1) * val / (maximum() - minimum()));
187
188 if (d->arrowPE == QStyle::PE_IndicatorArrowRight) {
189 p.setX(0);
190 } else {
191 p.setX(width() - 5);
192 }
193 } else {
194 p.setX(iw + (width() - 2 * iw - 1) * val / (maximum() - minimum()));
195
196 if (d->arrowPE == QStyle::PE_IndicatorArrowDown) {
197 p.setY(0);
198 } else {
199 p.setY(height() - 5);
200 }
201 }
202
203 return p;
204}
205
207{
208 switch (direction) {
209 case Qt::UpArrow:
210 if (orientation() == Qt::Horizontal) {
211 d->arrowPE = QStyle::PE_IndicatorArrowUp;
212 } else {
214 }
215 break;
216 case Qt::DownArrow:
217 if (orientation() == Qt::Horizontal) {
219 } else {
221 }
222 break;
223 case Qt::LeftArrow:
224 if (orientation() == Qt::Vertical) {
226 } else {
228 }
229 break;
230 case Qt::RightArrow:
231 if (orientation() == Qt::Vertical) {
233 } else {
234 d->arrowPE = QStyle::PE_IndicatorArrowUp;
235 }
236 break;
237
238 case Qt::NoArrow:
239 break;
240 }
241}
242
243Qt::ArrowType KSelector::arrowDirection() const
244{
245 switch (d->arrowPE) {
247 return Qt::UpArrow;
249 return Qt::DownArrow;
251 return Qt::RightArrow;
253 default:
254 return Qt::LeftArrow;
255 }
256}
257
261
262void KSelector::drawArrow(QPainter *painter, const QPoint &pos)
263{
264 painter->setPen(QPen());
265 painter->setBrush(QBrush(palette().color(QPalette::ButtonText)));
266
267 QStyleOption o;
268
269 if (orientation() == Qt::Vertical) {
270 o.rect = QRect(pos.x(), pos.y() - ARROWSIZE / 2, ARROWSIZE, ARROWSIZE);
271 } else {
272 o.rect = QRect(pos.x() - ARROWSIZE / 2, pos.y(), ARROWSIZE, ARROWSIZE);
273 }
274 style()->drawPrimitive(d->arrowPE, &o, painter, this);
275}
276
277//----------------------------------------------------------------------------
278
280 : KSelector(parent)
281 , d(new KGradientSelectorPrivate(this))
282{
283}
284
286 : KSelector(o, parent)
287 , d(new KGradientSelectorPrivate(this))
288{
289}
290
292
294{
295 d->gradient.setStart(contentsRect().topLeft());
296 if (orientation() == Qt::Vertical) {
297 d->gradient.setFinalStop(contentsRect().bottomLeft());
298 } else {
299 d->gradient.setFinalStop(contentsRect().topRight());
300 }
301 QBrush gradientBrush(d->gradient);
302
303 if (!gradientBrush.isOpaque()) {
304 QPixmap chessboardPattern(16, 16);
305 QPainter patternPainter(&chessboardPattern);
306 patternPainter.fillRect(0, 0, 8, 8, Qt::black);
307 patternPainter.fillRect(8, 8, 8, 8, Qt::black);
308 patternPainter.fillRect(0, 8, 8, 8, Qt::white);
309 patternPainter.fillRect(8, 0, 8, 8, Qt::white);
310 patternPainter.end();
311 painter->fillRect(contentsRect(), QBrush(chessboardPattern));
312 }
313 painter->fillRect(contentsRect(), gradientBrush);
314
315 if (orientation() == Qt::Vertical) {
316 int yPos = contentsRect().top() + painter->fontMetrics().ascent() + 2;
317 int xPos = contentsRect().left() + (contentsRect().width() - painter->fontMetrics().horizontalAdvance(d->text2)) / 2;
318 QPen pen(qGray(firstColor().rgb()) > 180 ? Qt::black : Qt::white);
319 painter->setPen(pen);
320 painter->drawText(xPos, yPos, d->text2);
321
322 yPos = contentsRect().bottom() - painter->fontMetrics().descent() - 2;
323 xPos = contentsRect().left() + (contentsRect().width() - painter->fontMetrics().horizontalAdvance(d->text1)) / 2;
324 pen.setColor(qGray(secondColor().rgb()) > 180 ? Qt::black : Qt::white);
325 painter->setPen(pen);
326 painter->drawText(xPos, yPos, d->text1);
327 } else {
328 int yPos = contentsRect().bottom() - painter->fontMetrics().descent() - 2;
329
330 QPen pen(qGray(firstColor().rgb()) > 180 ? Qt::black : Qt::white);
331 painter->setPen(pen);
332 painter->drawText(contentsRect().left() + 2, yPos, d->text1);
333
334 pen.setColor(qGray(secondColor().rgb()) > 180 ? Qt::black : Qt::white);
335 painter->setPen(pen);
336 painter->drawText(contentsRect().right() - painter->fontMetrics().horizontalAdvance(d->text2) - 2, yPos, d->text2);
337 }
338}
339
340QSize KGradientSelector::minimumSize() const
341{
342 return sizeHint();
343}
344
345void KGradientSelector::setStops(const QGradientStops &stops)
346{
347 d->gradient.setStops(stops);
348 update();
349}
350
351QGradientStops KGradientSelector::stops() const
352{
353 return d->gradient.stops();
354}
355
356void KGradientSelector::setColors(const QColor &col1, const QColor &col2)
357{
358 d->gradient.setColorAt(0.0, col1);
359 d->gradient.setColorAt(1.0, col2);
360 update();
361}
362
363void KGradientSelector::setText(const QString &t1, const QString &t2)
364{
365 d->text1 = t1;
366 d->text2 = t2;
367 update();
368}
369
371{
372 d->gradient.setColorAt(0.0, col);
373 update();
374}
375
376void KGradientSelector::setSecondColor(const QColor &col)
377{
378 d->gradient.setColorAt(1.0, col);
379 update();
380}
381
383{
384 d->text1 = t;
385 update();
386}
387
388void KGradientSelector::setSecondText(const QString &t)
389{
390 d->text2 = t;
391 update();
392}
393
394QColor KGradientSelector::firstColor() const
395{
396 return d->gradient.stops().first().second;
397}
398
399QColor KGradientSelector::secondColor() const
400{
401 return d->gradient.stops().last().second;
402}
403
404QString KGradientSelector::firstText() const
405{
406 return d->text1;
407}
408
409QString KGradientSelector::secondText() const
410{
411 return d->text2;
412}
413
414#include "moc_kselector.cpp"
The KGradientSelector widget allows the user to choose from a one-dimensional range of colors which i...
Definition kselector.h:122
void setFirstText(const QString &t)
Set each description on its own.
void setStops(const QGradientStops &stops)
Sets the colors that make up the gradient.
void setColors(const QColor &col1, const QColor &col2)
Sets the two colors which span the gradient.
void setFirstColor(const QColor &col)
Set each color on its own.
QGradientStops stops() const
Get the colors that make up the gradient.
~KGradientSelector() override
Destructs the widget.
void drawContents(QPainter *) override
Override this function to draw the contents of the control.
KGradientSelector(QWidget *parent=nullptr)
Constructs a horizontal color selector which contains a gradient between white and black.
KSelector is the base class for other widgets which provides the ability to choose from a one-dimensi...
Definition kselector.h:33
KSelector(QWidget *parent=nullptr)
Constructs a horizontal one-dimensional selection widget.
Definition kselector.cpp:45
void setArrowDirection(Qt::ArrowType direction)
Sets the arrow direction.
virtual void drawContents(QPainter *)
Override this function to draw the contents of the control.
void setIndent(bool i)
Sets the indent option of the widget to i.
Definition kselector.cpp:64
QRect contentsRect() const
Definition kselector.cpp:74
virtual void drawArrow(QPainter *painter, const QPoint &pos)
Override this function to draw the cursor which indicates the current value.
void setOrientation(Qt::Orientation)
void setSliderDown(bool)
void setValue(int)
bool isOpaque() const const
int ascent() const const
int descent() const const
int horizontalAdvance(QChar ch) const const
QPoint pos() const const
bool begin(QPaintDevice *device)
const QBrush & brush() const const
void drawText(const QPoint &position, const QString &text)
bool end()
void fillRect(const QRect &rectangle, QGradient::Preset preset)
QFontMetrics fontMetrics() const const
void setBrush(Qt::BrushStyle style)
void setPen(Qt::PenStyle style)
void setColor(const QColor &color)
void setX(int x)
void setY(int y)
int y() const const
int bottom() const const
int left() const const
int top() const const
int width() const const
PM_DefaultFrameWidth
PrimitiveElement
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
void initFrom(const QWidget *widget)
Horizontal
QPoint angleDelta() const const
QStyle * style() const const
void update()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 25 2024 12:00:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.