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 right() 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 Jul 19 2024 11:51:03 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.