Perceptual Color

gradientslider.cpp
1// SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR MIT
3
4// Own headers
5// First the interface, which forces the header to be self-contained.
6#include "gradientslider.h"
7// Second, the private implementation.
8#include "gradientslider_p.h" // IWYU pragma: associated
9
10#include "abstractdiagram.h"
11#include "constpropagatingrawpointer.h"
12#include "constpropagatinguniquepointer.h"
13#include "gradientimageparameters.h"
14#include "helperconstants.h"
15#include <helper.h>
16#include <qevent.h>
17#include <qguiapplication.h>
18#include <qimage.h>
19#include <qpainter.h>
20#include <qpen.h>
21#include <qpoint.h>
22#include <qsharedpointer.h>
23#include <qsizepolicy.h>
24#include <qtransform.h>
25#include <qwidget.h>
26
27namespace PerceptualColor
28{
29/** @brief Constructs a vertical slider.
30 * @param colorSpace The color space within which this widget should operate.
31 * Can be created with @ref RgbColorSpaceFactory.
32 * Can be created with @ref RgbColorSpaceFactory.
33 * @param parent parent widget (if any) */
35 : AbstractDiagram(parent)
36 , d_pointer(new GradientSliderPrivate(this))
37{
38 d_pointer->initialize(colorSpace, Qt::Orientation::Vertical);
39}
40
41/** @brief Constructs a slider.
42 * @param colorSpace The color space within which this widget should operate.
43 * Can be created with @ref RgbColorSpaceFactory.
44 * @param orientation The orientation parameter determines whether
45 * the slider is horizontal or vertical; the valid values
46 * are <tt>Qt::Vertical</tt> and <tt>Qt::Horizontal</tt>.
47 * @param parent parent widget (if any) */
49 : AbstractDiagram(parent)
50 , d_pointer(new GradientSliderPrivate(this))
51{
52 d_pointer->initialize(colorSpace, orientation);
53}
54
55/** @brief Default destructor */
59
60/** @brief Constructor
61 *
62 * @param backLink Pointer to the object from which <em>this</em> object
63 * is the private implementation. */
64GradientSliderPrivate::GradientSliderPrivate(GradientSlider *backLink)
65 : m_firstColorCieLchD50A{0, 0, 0, 0} // dummy value
66 , m_secondColorCieLchD50A{0, 0, 0, 0} // dummy value
67 , q_pointer(backLink)
68{
69}
70
71/** @brief Basic initialization.
72 *
73 * Code that is shared between the various overloaded constructors
74 * of @ref GradientSlider.
75 *
76 * @note This function requires that @ref q_pointer points to a completely
77 * initialized object. Therefore, this function may <em>not</em> be called
78 * within the constructor of @ref GradientSliderPrivate because in this
79 * moment the @ref GradientSlider object is still not fully initialized.
80 * However, a call from the <em>function body</em> of a constructor of
81 * @ref GradientSlider should be okay.
82 *
83 * @param colorSpace the color space
84 * @param orientation determines whether the slider is horizontal or
85 * vertical */
86void GradientSliderPrivate::initialize(const QSharedPointer<RgbColorSpace> &colorSpace, Qt::Orientation orientation)
87{
88 q_pointer->setFocusPolicy(Qt::StrongFocus);
89 m_gradientImageParameters.rgbColorSpace = colorSpace;
90 setOrientationWithoutSignalAndForceNewSizePolicy(orientation);
91 constexpr GenericColor first{75, 65, 90, 1};
92 constexpr GenericColor second{50, 75, 45, 1};
93 q_pointer->setColors(first, second);
94
95 // Connections
96 q_pointer->connect( //
97 &m_gradientImage, //
98 &AsyncImageProvider<GradientImageParameters>::interlacingPassCompleted, //
99 q_pointer,
101}
102
103// No documentation here (documentation of properties
104// and its getters are in the header)
106{
107 return d_pointer->m_firstColorCieLchD50A;
108}
109
110/** @brief Setter for @ref firstColorCieLchD50A property.
111 *
112 * @param newFirstColorCieLchD50A the new @ref firstColorCieLchD50A */
113void GradientSlider::setFirstColorCieLchD50A(const PerceptualColor::GenericColor &newFirstColorCieLchD50A)
114{
115 if (!(d_pointer->m_firstColorCieLchD50A == newFirstColorCieLchD50A)) {
116 d_pointer->m_firstColorCieLchD50A = newFirstColorCieLchD50A;
117 d_pointer->m_gradientImageParameters.setFirstColorCieLchD50A(newFirstColorCieLchD50A);
118 d_pointer->m_gradientImage.setImageParameters( //
119 d_pointer->m_gradientImageParameters);
120 update();
121 Q_EMIT firstColorCieLchD50AChanged(newFirstColorCieLchD50A);
122 }
123}
124
125// No documentation here (documentation of properties
126// and its getters are in the header)
128{
129 return d_pointer->m_secondColorCieLchD50A;
130}
131
132/** @brief Setter for @ref secondColorCieLchD50A property.
133 *
134 * @param newSecondColorCieLchD50A the new @ref secondColorCieLchD50A */
135void GradientSlider::setSecondColorCieLchD50A(const PerceptualColor::GenericColor &newSecondColorCieLchD50A)
136{
137 if (!(d_pointer->m_secondColorCieLchD50A == newSecondColorCieLchD50A)) {
138 d_pointer->m_secondColorCieLchD50A = newSecondColorCieLchD50A;
139 d_pointer->m_gradientImageParameters.setSecondColorCieLchD50A(newSecondColorCieLchD50A);
140 d_pointer->m_gradientImage.setImageParameters( //
141 d_pointer->m_gradientImageParameters);
142 update();
143 Q_EMIT secondColorCieLchD50AChanged(newSecondColorCieLchD50A);
144 }
145}
146
147/** @brief Setter for both, @ref firstColorCieLchD50A property and @ref secondColorCieLchD50A
148 * property.
149 *
150 * @param newFirstColorCieLchD50A the new @ref firstColorCieLchD50A
151 * @param newSecondColorCieLchD50A the new @ref secondColorCieLchD50A */
152void GradientSlider::setColors(const PerceptualColor::GenericColor &newFirstColorCieLchD50A, const PerceptualColor::GenericColor &newSecondColorCieLchD50A)
153{
154 setFirstColorCieLchD50A(newFirstColorCieLchD50A);
155 setSecondColorCieLchD50A(newSecondColorCieLchD50A);
156 update();
157}
158
159/** @brief React on a resize event.
160 *
161 * Reimplemented from base class.
162 *
163 * @param event The corresponding resize event */
165{
166 Q_UNUSED(event)
167 d_pointer->m_gradientImageParameters.setGradientLength( //
168 d_pointer->physicalPixelLength());
169 d_pointer->m_gradientImageParameters.setGradientThickness(
170 // Normally, this should not change, but maybe on Hight-DPI
171 // devices there might be some differences.
172 d_pointer->physicalPixelThickness());
173 d_pointer->m_gradientImage.setImageParameters( //
174 d_pointer->m_gradientImageParameters);
175 update();
176}
177
178/** @brief Recommended size for the widget
179 *
180 * Reimplemented from base class.
181 *
182 * @returns Recommended size for the widget.
183 *
184 * @sa @ref sizeHint() */
186{
187 QSize result = minimumSizeHint();
188 if (d_pointer->m_orientation == Qt::Orientation::Horizontal) {
189 result.setWidth( //
190 qRound(result.width() * scaleFromMinumumSizeHintToSizeHint));
191 } else {
192 result.setHeight( //
193 qRound(result.height() * scaleFromMinumumSizeHintToSizeHint));
194 }
195 return result;
196}
197
198/** @brief Recommended minimum size for the widget.
199 *
200 * Reimplemented from base class.
201 *
202 * @returns Recommended minimum size for the widget.
203 *
204 * @sa @ref minimumSizeHint() */
206{
207 QSize result;
208 if (d_pointer->m_orientation == Qt::Orientation::Horizontal) {
211 } else {
212 result.setWidth(gradientThickness());
214 }
215 return result;
216}
217
218// No documentation here (documentation of properties
219// and its getters are in the header)
221{
222 return d_pointer->m_singleStep;
223}
224
225/** @brief Setter for @ref singleStep property.
226 *
227 * @param newSingleStep the new @ref singleStep. Is bound to the valid
228 * range of the property. */
229void GradientSlider::setSingleStep(qreal newSingleStep)
230{
231 // Do not use negative value
232 const qreal boundedSingleStep = qBound<qreal>(0.0, newSingleStep, 1.0);
233 if (boundedSingleStep != d_pointer->m_singleStep) {
234 d_pointer->m_singleStep = boundedSingleStep;
235 Q_EMIT singleStepChanged(d_pointer->m_singleStep);
236 }
237}
238
239// No documentation here (documentation of properties
240// and its getters are in the header)
242{
243 return d_pointer->m_pageStep;
244}
245
246/** @brief Setter for @ref pageStep property.
247 *
248 * @param newPageStep the new @ref pageStep. Is bound to the valid
249 * range of the property. */
250void GradientSlider::setPageStep(qreal newPageStep)
251{
252 // Do not use negative altkluge
253 const qreal boundedNewPageStep = qBound<qreal>(0.0, newPageStep, 1.0);
254 if (boundedNewPageStep != d_pointer->m_pageStep) {
255 d_pointer->m_pageStep = boundedNewPageStep;
256 Q_EMIT pageStepChanged(d_pointer->m_pageStep);
257 }
258}
259
260// No documentation here (documentation of properties
261// and its getters are in the header)
263{
264 return d_pointer->m_value;
265}
266
267/** @brief Setter for @ref value property.
268 *
269 * @param newValue the new @ref value. Is bound to the valid
270 * range of the property. */
271void GradientSlider::setValue(qreal newValue)
272{
273 qreal temp = qBound<qreal>(0, newValue, 1);
274 if (d_pointer->m_value != temp) {
275 d_pointer->m_value = temp;
276 update();
277 Q_EMIT valueChanged(temp);
278 }
279}
280
281/** @brief React on a mouse press event.
282 *
283 * Reimplemented from base class.
284 *
285 * @param event The corresponding mouse event */
287{
288 setValue(d_pointer->fromWidgetPixelPositionToValue(event->pos()));
289}
290
291/** @brief React on a mouse release event.
292 *
293 * Reimplemented from base class.
294 *
295 * @param event The corresponding mouse event */
297{
298 setValue(d_pointer->fromWidgetPixelPositionToValue(event->pos()));
299}
300
301/** @brief React on a mouse move event.
302 *
303 * Reimplemented from base class.
304 *
305 * @param event The corresponding mouse event */
307{
308 setValue(d_pointer->fromWidgetPixelPositionToValue(event->pos()));
309}
310
311/** @brief React on a mouse wheel event.
312 *
313 * Reimplemented from base class.
314 *
315 * @param event The corresponding mouse event */
317{
318 qreal steps = standardWheelStepCount(event);
319 // Only react on good old vertical wheels, and not on horizontal wheels
320 if (steps != 0) {
321 qreal stepSize;
322 if ( //
325 ) {
326 stepSize = pageStep();
327 } else {
328 stepSize = singleStep();
329 }
330 setValue(d_pointer->m_value + steps * stepSize);
331 } else {
332 // Don’t accept the event and let it up to the default treatment:
333 event->ignore();
334 }
335}
336
337/** @brief React on key press events.
338 *
339 * Reimplemented from base class.
340 *
341 * The user can change the @ref value of this widget by the following
342 * key strokes:
343 *
344 * - Qt::Key_Up and Qt::Key_Plus increments a @ref singleStep.
345 * - Qt::Key_Down and Qt::Key_Minus decrements a @ref singleStep.
346 * - Qt::Key_Left increments and Qt::Key_Right increment or decrement
347 * a @ref singleStep, depending on the layout direction (LTR or RTL).
348 * - Qt::Key_PageUp increments a @ref pageStep
349 * - Qt::Key_PageDown decrements a @ref pageStep
350 * - Qt::Key_Home increments to the maximum @ref value
351 * - Qt::Key_End decrements to the minimum @ref value
352 *
353 * @param event the event */
355{
356 switch (event->key()) {
357 case Qt::Key_Up:
358 case Qt::Key_Plus:
359 setValue(d_pointer->m_value + d_pointer->m_singleStep);
360 break;
361 case Qt::Key_Down:
362 case Qt::Key_Minus:
363 setValue(d_pointer->m_value - d_pointer->m_singleStep);
364 break;
365 case Qt::Key_Left:
366 if (layoutDirection() == Qt::LayoutDirection::LeftToRight) {
367 setValue(d_pointer->m_value - d_pointer->m_singleStep);
368 } else {
369 setValue(d_pointer->m_value + d_pointer->m_singleStep);
370 }
371 break;
372 case Qt::Key_Right:
373 if (layoutDirection() == Qt::LayoutDirection::LeftToRight) {
374 setValue(d_pointer->m_value + d_pointer->m_singleStep);
375 } else {
376 setValue(d_pointer->m_value - d_pointer->m_singleStep);
377 }
378 break;
379 case Qt::Key_PageUp:
380 setValue(d_pointer->m_value + d_pointer->m_pageStep);
381 break;
382 case Qt::Key_PageDown:
383 setValue(d_pointer->m_value - d_pointer->m_pageStep);
384 break;
385 case Qt::Key_Home:
386 setValue(0);
387 break;
388 case Qt::Key_End:
389 setValue(1);
390 break;
391 default:
392 /* Quote from Qt documentation:
393 *
394 * “If you reimplement this handler, it is very important that
395 * you call the base class implementation if you do not act
396 * upon the key.
397 *
398 * The default implementation closes popup widgets if the
399 * user presses the key sequence for QKeySequence::Cancel
400 * (typically the Escape key). Otherwise the event is
401 * ignored, so that the widget’s parent can interpret it.“ */
403 }
404}
405
406// No documentation here (documentation of properties
407// and its getters are in the header)
409{
410 return d_pointer->m_orientation;
411}
412
413/** @brief Forces a new orientation and a corresponding size policy.
414 *
415 * @param newOrientation The new orientation for the widget.
416 *
417 * @post The new orientation is stored. The signal
418 * @ref GradientSlider::orientationChanged is <em>not</em> emitted.
419 * The <tt>sizePolicy</tt> property is updated corresponding to the
420 * <em>new</em> orientation; this happens even if the new
421 * orientation is identical to the old @ref m_orientation! */
422void GradientSliderPrivate::setOrientationWithoutSignalAndForceNewSizePolicy(Qt::Orientation newOrientation)
423{
424 if (newOrientation == Qt::Orientation::Vertical) {
425 q_pointer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
426 } else {
427 q_pointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
428 }
429 m_orientation = newOrientation;
430 m_gradientImageParameters.setGradientLength(physicalPixelLength());
431 m_gradientImageParameters.setGradientThickness(
432 // Normally, this should not change, but maybe on Hight-DPI
433 // devices there are some differences.
434 physicalPixelThickness());
435 m_gradientImage.setImageParameters(m_gradientImageParameters);
436 // Notify the layout system the the geometry has changed
437 q_pointer->updateGeometry();
438 q_pointer->update();
439}
440
441/** @brief Setter for @ref orientation property.
442 *
443 * @param newOrientation the new @ref orientation. */
445{
446 if (newOrientation != d_pointer->m_orientation) {
447 d_pointer->setOrientationWithoutSignalAndForceNewSizePolicy( //
448 newOrientation);
449 Q_EMIT orientationChanged(d_pointer->m_orientation);
450 }
451}
452
453/** @brief The rounded length of the widget
454 * measured in <em>physical pixels</em>.
455 *
456 * @returns The rounded length of the widget
457 * measured in <em>physical pixels</em>.
458 *
459 * This is a convenience function to access
460 * @ref GradientSlider::physicalPixelSize(). The length is the
461 * size of the widget in the direction of the gradient.
462 *
463 * @sa @ref physicalPixelThickness() */
464int GradientSliderPrivate::physicalPixelLength() const
465{
466 if (m_orientation == Qt::Orientation::Vertical) {
467 return q_pointer->physicalPixelSize().height();
468 } else {
469 return q_pointer->physicalPixelSize().width();
470 }
471}
472
473/** @brief The rounded thickness of the widget
474 * measured in <em>physical pixels</em>.
475 *
476 * @returns The rounded thickness of the widget
477 * measured in <em>physical pixels</em>.
478 *
479 * This is a convenience function to access
480 * @ref GradientSlider::physicalPixelSize(). The thickness is the
481 * size of the widget orthogonal to the direction of the gradient.
482 *
483 * @sa @ref physicalPixelLength() */
484int GradientSliderPrivate::physicalPixelThickness() const
485{
486 if (m_orientation == Qt::Orientation::Horizontal) {
487 return q_pointer->physicalPixelSize().height();
488 } else {
489 return q_pointer->physicalPixelSize().width();
490 }
491}
492
493/** @brief Converts widget pixel positions to @ref GradientSlider::value
494 * @param pixelPosition The position of a pixel of the widget coordinate
495 * system. The given value does not necessarily need to
496 * be within the actual displayed widget. It might even be negative.
497 * @returns The corresponding @ref GradientSlider::value for the (center of
498 * the) given widget pixel position.
499 * @sa @ref measurementdetails */
500qreal GradientSliderPrivate::fromWidgetPixelPositionToValue(QPoint pixelPosition)
501{
502 // We are interested in the point in the middle of the given pixel.
503 const QPointF coordinatePoint = pixelPosition + QPointF(0.5, 0.5);
504 qreal temp;
505 if (m_orientation == Qt::Orientation::Vertical) {
506 temp = (q_pointer->size().height() - coordinatePoint.y()) //
507 / static_cast<qreal>(q_pointer->size().height());
508 } else {
509 if (q_pointer->layoutDirection() == Qt::LayoutDirection::LeftToRight) {
510 temp = coordinatePoint.x() //
511 / static_cast<qreal>(q_pointer->size().width());
512 } else {
513 temp = (q_pointer->size().width() - coordinatePoint.x()) //
514 / static_cast<qreal>(q_pointer->size().width());
515 }
516 }
517 return qBound<qreal>(0, temp, 1);
518}
519
520/** @brief Paint the widget.
521 *
522 * Reimplemented from base class.
523 *
524 * @param event the paint event */
526{
527 Q_UNUSED(event)
528 // We do not paint directly on the widget, but on a QImage buffer first:
529 // Render anti-aliased looks better. But as Qt documentation says:
530 //
531 // “Renderhints are used to specify flags to QPainter that may or
532 // may not be respected by any given engine.”
533 //
534 // Painting here directly on the widget might lead to different
535 // anti-aliasing results depending on the underlying window system. This
536 // is especially problematic as anti-aliasing might shift or not a pixel
537 // to the left or to the right. So we paint on a QImage first. As QImage
538 // (at difference to QPixmap and a QWidget) is independent of native
539 // platform rendering, it guarantees identical anti-aliasing results on
540 // all platforms. Here the quote from QPainter class documentation:
541 //
542 // “To get the optimal rendering result using QPainter, you should
543 // use the platform independent QImage as paint device; i.e. using
544 // QImage will ensure that the result has an identical pixel
545 // representation on any platform.”
546 QImage paintBuffer;
547
548 // Paint the gradient itself.
549 // Make sure the image will be correct. We set length and thickness,
550 // just to be sure (we might have missed a resize event). Also,
551 // the device pixel ratio float might have changed because the
552 // window has been moved to another screen. We do not update the
553 // first and the second color because we have complete control
554 // about these values and are sure the any changes have yet been
555 // applied.
556 d_pointer->m_gradientImageParameters.setDevicePixelRatioF( //
558 d_pointer->m_gradientImageParameters.setGradientLength( //
559 d_pointer->physicalPixelLength());
560 d_pointer->m_gradientImageParameters.setGradientThickness(
561 // Normally, this should not change, but maybe on Hight-DPI
562 // devices there are some differences.
563 d_pointer->physicalPixelThickness());
564 d_pointer->m_gradientImage.setImageParameters( //
565 d_pointer->m_gradientImageParameters);
566 d_pointer->m_gradientImage.refreshAsync();
567 paintBuffer = d_pointer->m_gradientImage.getCache();
568 if (paintBuffer.isNull()) {
569 return;
570 }
571
572 // Draw slider handle
573 QPainter bufferPainter(&paintBuffer);
574 // We use antialiasing. As our current handle is just a horizontal or
575 // vertical line, it might be slightly sharper without antialiasing.
576 // But all other widgets of this library WILL USE antialiasing because
577 // their handles are not perfectly horizontal or vertical and without
578 // antialiasing they might look terrible. Now, when antialiasing is NOT
579 // used, the line thickness is rounded. This would lead to a different
580 // thickness in this widget compared to the other widgets. This is not
581 // a good idea. Therefore, we USE antialiasing here. Anyway, in practical
582 // tests, it seems almost as sharp as without antialiasing, and
583 // additionally the position is more exact!
584 bufferPainter.setRenderHint(QPainter::Antialiasing, true);
585 QPen pen;
586 const qreal handleCoordinatePoint = d_pointer->physicalPixelLength() //
587 / devicePixelRatioF() //
588 * d_pointer->m_value;
589 if (hasFocus()) {
592 bufferPainter.setPen(pen);
593 bufferPainter.drawLine(QPointF(handleCoordinatePoint, 0), //
594 QPointF(handleCoordinatePoint, gradientThickness()));
595 }
597 pen.setColor( //
599 d_pointer->m_gradientImageParameters
600 .colorFromValue( //
601 d_pointer->m_value)
602 .first));
603 bufferPainter.setPen(pen);
604 bufferPainter.drawLine(QPointF(handleCoordinatePoint, 0), //
605 QPointF(handleCoordinatePoint, gradientThickness()));
606
607 // Paint the buffer to the actual widget
608 QTransform transform;
609 // The m_gradientImageProvider contains the gradient always
610 // in a default form, independent of the actual orientation
611 // of this widget and independent of its actual layout direction:
612 // In the default form, the first color is always on the left, and the
613 // second color is always on the right. To paint it, we have to
614 // rotate it if our actual orientation is vertical. And we have to
615 // mirror it when our actual layout direction is RTL.
616 if (d_pointer->m_orientation == Qt::Orientation::Vertical) {
617 if (layoutDirection() == Qt::LayoutDirection::RightToLeft) {
618 // Even on vertical gradients, we mirror the image, so that
619 // the well-aligned edge of the transparency background is
620 // always aligned according to the writing direction.
621 transform.scale(-1, 1);
622 transform.rotate(270);
623 transform.translate(size().height() * (-1), size().width() * (-1));
624 } else {
625 transform.rotate(270);
626 transform.translate(size().height() * (-1), 0);
627 }
628 } else {
629 if (layoutDirection() == Qt::LayoutDirection::RightToLeft) {
630 transform.scale(-1, 1);
631 transform.translate(size().width() * (-1), 0);
632 }
633 }
634 QPainter widgetPainter(this);
635 widgetPainter.setTransform(transform);
636 widgetPainter.drawImage(0, 0, paintBuffer);
637
638 // // TODO Draw a focus rectangle like this?:
639 // widgetPainter.setTransform(QTransform());
640 // if (hasFocus()) {
641 // QStyleOptionFocusRect opt;
642 // opt.palette = palette();
643 // opt.rect = rect();
644 // opt.state = QStyle::State_None |
645 // QStyle::State_KeyboardFocusChange; style()->drawPrimitive(
646 // QStyle::PE_FrameFocusRect,
647 // &opt,
648 // &widgetPainter,
649 // this
650 // );
651 // }
652}
653
654} // namespace PerceptualColor
Base class for LCH diagrams.
QColor handleColorFromBackgroundLightness(qreal lightness) const
An appropriate color for a handle, depending on the background lightness.
int gradientMinimumLength() const
The minimum length of a color gradient.
void callUpdate()
An alternative to QWidget::update().
int handleOutlineThickness() const
The outline thickness of a handle.
int gradientThickness() const
The thickness of a color gradient.
QColor focusIndicatorColor() const
The color for painting focus indicators.
A slider who’s groove displays an LCH color gradient.
void setFirstColorCieLchD50A(const PerceptualColor::GenericColor &newFirstColorCieLchD50A)
Setter for firstColorCieLchD50A property.
virtual QSize minimumSizeHint() const override
Recommended minimum size for the widget.
qreal value
The slider’s current value.
Q_INVOKABLE GradientSlider(const QSharedPointer< PerceptualColor::RgbColorSpace > &colorSpace, QWidget *parent=nullptr)
Constructs a vertical slider.
virtual void mouseReleaseEvent(QMouseEvent *event) override
React on a mouse release event.
void singleStepChanged(const qreal newSingleStep)
Signal for singleStep property.
virtual void mouseMoveEvent(QMouseEvent *event) override
React on a mouse move event.
virtual ~GradientSlider() noexcept override
Default destructor.
virtual QSize sizeHint() const override
Recommended size for the widget.
virtual void keyPressEvent(QKeyEvent *event) override
React on key press events.
void setSecondColorCieLchD50A(const PerceptualColor::GenericColor &newSecondColorCieLchD50A)
Setter for secondColorCieLchD50A property.
void firstColorCieLchD50AChanged(const PerceptualColor::GenericColor &newFirstColorCieLchD50A)
Signal for firstColorCieLchD50A property.
void setValue(const qreal newValue)
Setter for value property.
virtual void wheelEvent(QWheelEvent *event) override
React on a mouse wheel event.
void setSingleStep(const qreal newSingleStep)
Setter for singleStep property.
void orientationChanged(const Qt::Orientation newOrientation)
Signal for orientation property.
virtual void resizeEvent(QResizeEvent *event) override
React on a resize event.
PerceptualColor::GenericColor firstColorCieLchD50A
First color (the one corresponding to a low value)
void valueChanged(const qreal newValue)
Signal for value property.
qreal singleStep
This property holds the single step.
virtual void mousePressEvent(QMouseEvent *event) override
React on a mouse press event.
void secondColorCieLchD50AChanged(const PerceptualColor::GenericColor &newSecondColorCieLchD50A)
Signal for secondColorCieLchD50A property.
void setPageStep(const qreal newPageStep)
Setter for pageStep property.
void setColors(const PerceptualColor::GenericColor &newFirstColorCieLchD50A, const PerceptualColor::GenericColor &newSecondColorCieLchD50A)
Setter for both, firstColorCieLchD50A property and secondColorCieLchD50A property.
void setOrientation(const Qt::Orientation newOrientation)
Setter for orientation property.
PerceptualColor::GenericColor secondColorCieLchD50A
Second color (the one corresponding to a high value)
qreal pageStep
This property holds the page step.
Qt::Orientation orientation
Orientation of the widget.
void pageStepChanged(const qreal newPageStep)
Signal for pageStep property.
virtual void paintEvent(QPaintEvent *event) override
Paint the widget.
The namespace of this library.
Qt::KeyboardModifiers keyboardModifiers()
bool isNull() const const
Q_EMITQ_EMIT
qreal devicePixelRatioF() const const
void drawImage(const QPoint &point, const QImage &image)
void drawLine(const QLine &line)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
void setTransform(const QTransform &transform, bool combine)
void setColor(const QColor &color)
void setWidthF(qreal width)
qreal x() const const
qreal y() const const
int height() const const
void setHeight(int height)
void setWidth(int width)
int width() const const
StrongFocus
ControlModifier
Orientation
virtual bool event(QEvent *event) override
bool hasFocus() const const
virtual void keyPressEvent(QKeyEvent *event)
void update()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:57:18 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.