KWidgetsAddons

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

KDE's Doxygen guidelines are available online.