Krita Source Code Documentation
Loading...
Searching...
No Matches
KisLevelsSlider Class Referenceabstract

A base class for levels slider like widgets: a slider with a gradient and multiple handles. More...

#include <KisLevelsSlider.h>

+ Inheritance diagram for KisLevelsSlider:

Classes

struct  Handle
 

Public Slots

virtual void setHandleColor (int handleIndex, const QColor &newColor)
 Sets the color associated with the given handle.
 
virtual void setHandlePosition (int handleIndex, qreal newPosition)
 Sets the normalized position of the given handle.
 

Signals

void handleColorChanged (int handleIndex, const QColor &color)
 Signal emitted when the color associated with a handle changes.
 
void handlePositionChanged (int handleIndex, qreal position)
 Signal emitted when the position of a handle changes.
 

Public Member Functions

virtual QRect gradientRect () const
 Gets the rect where the gradient will be painted.
 
QColor handleColor (int handleIndex) const
 Gets the color associated with a given handle.
 
qreal handlePosition (int handleIndex) const
 Gets the normalized position of a given handle.
 
 KisLevelsSlider (QWidget *parent)
 
QSize minimumSizeHint () const override
 
QSize sizeHint () const override
 
 ~KisLevelsSlider ()
 

Protected Member Functions

int closestHandleToPosition (qreal position) const
 Given a normalized position, this function returns the closest handle to that position.
 
int closestHandleToX (int x) const
 Given a widget-relative x position, this function returns the closest handle to that position.
 
void handleIncrementInput (int direction, Qt::KeyboardModifiers modifiers)
 
void keyPressEvent (QKeyEvent *e) override
 
void leaveEvent (QEvent *e) override
 
void mouseMoveEvent (QMouseEvent *e) override
 
void mousePressEvent (QMouseEvent *e) override
 
void paintEvent (QPaintEvent *e) override
 
virtual void paintGradient (QPainter &painter, const QRect &rect)=0
 Derived classes must override this function to draw the gradient inside the given rect. A border is automatically drawn after.
 
virtual void paintHandle (QPainter &painter, const QRect &rect, const Handle &handle)
 Override this function to paint custom handles.
 
qreal positionFromX (int x) const
 Given a widget-relative x position in pixels, this function returns the normalized position relative to the gradient rect.
 
QVector< HandlesortedHandles () const
 Regardless the index of a handle, they can be unordered in terms of the position. This returns a sorted vector with the handles that have a smaller position first. If two handles have the same position then the index is used for sorting.
 
void wheelEvent (QWheelEvent *e) override
 
int xFromPosition (qreal position) const
 Given a gradient rect relative position, this function returns the x position in pixels relative to the widget.
 

Protected Attributes

int m_constrainPositions
 This variable indicates if the handles can have unordered positions. If it is set to true then the user won't be able to move a handle pass another one. If it is set to false then the ser will be able to move the handles freely.
 
QVector< Handlem_handles
 The collection of handles.
 
int m_hoveredHandle
 
int m_selectedHandle
 

Static Protected Attributes

static constexpr int handleHeight {11}
 
static constexpr int handleWidth {11}
 
static constexpr qreal minimumSpaceBetweenHandles {0.001}
 
static constexpr qreal normalPositionIncrement {0.01}
 
static constexpr qreal slowPositionIncrement {0.001}
 

Detailed Description

A base class for levels slider like widgets: a slider with a gradient and multiple handles.

Definition at line 21 of file KisLevelsSlider.h.

Constructor & Destructor Documentation

◆ KisLevelsSlider()

KisLevelsSlider::KisLevelsSlider ( QWidget * parent)

Definition at line 19 of file KisLevelsSlider.cpp.

20 : QWidget(parent)
23 , m_hoveredHandle(-1)
24{
25 setFocusPolicy(Qt::WheelFocus);
26 setMouseTracking(true);
27}
int m_constrainPositions
This variable indicates if the handles can have unordered positions. If it is set to true then the us...

◆ ~KisLevelsSlider()

KisLevelsSlider::~KisLevelsSlider ( )

Definition at line 29 of file KisLevelsSlider.cpp.

30{}

Member Function Documentation

◆ closestHandleToPosition()

int KisLevelsSlider::closestHandleToPosition ( qreal position) const
protected

Given a normalized position, this function returns the closest handle to that position.

Definition at line 113 of file KisLevelsSlider.cpp.

114{
115 const QVector<Handle> sortedHandles_ = sortedHandles();
116 int handleIndex = -1;
117
118 if (position <= sortedHandles_.first().position) {
119 handleIndex = sortedHandles_.first().index;
120 } else if (position >= sortedHandles_.last().position) {
121 handleIndex = sortedHandles_.last().index;
122 } else {
123 for (int i = 0; i < sortedHandles_.size() - 1; ++i) {
124 if (position >= sortedHandles_[i + 1].position) {
125 continue;
126 }
127 const qreal middlePoint = (sortedHandles_[i].position + sortedHandles_[i + 1].position) / 2.0;
128 handleIndex = position <= middlePoint ? sortedHandles_[i].index : sortedHandles_[i + 1].index;
129 break;
130 }
131 }
132
133 return handleIndex;
134}
QVector< Handle > sortedHandles() const
Regardless the index of a handle, they can be unordered in terms of the position. This returns a sort...

References sortedHandles().

◆ closestHandleToX()

int KisLevelsSlider::closestHandleToX ( int x) const
protected

Given a widget-relative x position, this function returns the closest handle to that position.

Definition at line 142 of file KisLevelsSlider.cpp.

143{
145}
int closestHandleToPosition(qreal position) const
Given a normalized position, this function returns the closest handle to that position.
qreal positionFromX(int x) const
Given a widget-relative x position in pixels, this function returns the normalized position relative ...

References closestHandleToPosition(), and positionFromX().

◆ gradientRect()

QRect KisLevelsSlider::gradientRect ( ) const
virtual

Gets the rect where the gradient will be painted.

Definition at line 95 of file KisLevelsSlider.cpp.

96{
97 const int margin = handleWidth / 2;
98 return rect().adjusted(margin, 0, -margin, -handleHeight);
99}
static constexpr int handleHeight
static constexpr int handleWidth

References handleHeight, and handleWidth.

◆ handleColor()

QColor KisLevelsSlider::handleColor ( int handleIndex) const

Gets the color associated with a given handle.

Definition at line 39 of file KisLevelsSlider.cpp.

40{
41 Q_ASSERT(handleIndex >= 0 && handleIndex < m_handles.size());
42
43 return m_handles[handleIndex].color;
44}
QVector< Handle > m_handles
The collection of handles.

References m_handles.

◆ handleColorChanged

void KisLevelsSlider::handleColorChanged ( int handleIndex,
const QColor & color )
signal

Signal emitted when the color associated with a handle changes.

◆ handleIncrementInput()

void KisLevelsSlider::handleIncrementInput ( int direction,
Qt::KeyboardModifiers modifiers )
protected

Definition at line 153 of file KisLevelsSlider.cpp.

154{
155 if (direction == 0) {
156 return;
157 }
158 if (modifiers & Qt::ControlModifier) {
159 m_selectedHandle += direction < 0 ? -1 : 1;
160 m_selectedHandle = qBound(0, m_selectedHandle, m_handles.size() - 1);
161 update();
162 } else if (m_selectedHandle >= 0 && m_selectedHandle < m_handles.size()) {
163 const qreal increment = modifiers & Qt::ShiftModifier ? slowPositionIncrement : normalPositionIncrement;
164 const qreal position = m_handles[m_selectedHandle].position + (direction < 0 ? -increment : increment);
166 }
167}
virtual void setHandlePosition(int handleIndex, qreal newPosition)
Sets the normalized position of the given handle.
static constexpr qreal normalPositionIncrement
static constexpr qreal slowPositionIncrement
bool update(QSpinBox *spinBox)

References m_handles, m_selectedHandle, normalPositionIncrement, setHandlePosition(), and slowPositionIncrement.

◆ handlePosition()

qreal KisLevelsSlider::handlePosition ( int handleIndex) const

Gets the normalized position of a given handle.

Definition at line 32 of file KisLevelsSlider.cpp.

33{
34 Q_ASSERT(handleIndex >= 0 && handleIndex < m_handles.size());
35
36 return m_handles[handleIndex].position;
37}

References m_handles.

◆ handlePositionChanged

void KisLevelsSlider::handlePositionChanged ( int handleIndex,
qreal position )
signal

Signal emitted when the position of a handle changes.

◆ keyPressEvent()

void KisLevelsSlider::keyPressEvent ( QKeyEvent * e)
overrideprotected

Definition at line 287 of file KisLevelsSlider.cpp.

288{
289 if (m_handles.size() == 0) {
290 return;
291 }
292 if (m_selectedHandle == -1) {
293 return;
294 }
295
296 switch (e->key()) {
297 case Qt::Key_Left:
298 handleIncrementInput(-1, e->modifiers());
299 return;
300 case Qt::Key_Right:
301 handleIncrementInput(1, e->modifiers());
302 return;
303 default:
304 QWidget::keyPressEvent(e);
305 }
306}
void handleIncrementInput(int direction, Qt::KeyboardModifiers modifiers)

References handleIncrementInput(), m_handles, and m_selectedHandle.

◆ leaveEvent()

void KisLevelsSlider::leaveEvent ( QEvent * e)
overrideprotected

Definition at line 280 of file KisLevelsSlider.cpp.

281{
282 m_hoveredHandle = -1;
283 update();
284 QWidget::leaveEvent(e);
285}

References m_hoveredHandle.

◆ minimumSizeHint()

QSize KisLevelsSlider::minimumSizeHint ( ) const
override

Definition at line 90 of file KisLevelsSlider.cpp.

91{
92 return QSize(128, 20) + QSize(handleWidth, handleHeight);
93}

References handleHeight, and handleWidth.

◆ mouseMoveEvent()

void KisLevelsSlider::mouseMoveEvent ( QMouseEvent * e)
overrideprotected

Definition at line 262 of file KisLevelsSlider.cpp.

263{
264 if (m_handles.size() == 0) {
265 return;
266 }
267
268 if (e->buttons() & Qt::LeftButton && m_selectedHandle != -1) {
270 } else {
271 int handleIndex = closestHandleToX(e->x());
272 if (handleIndex != -1) {
273 m_hoveredHandle = handleIndex;
274 update();
275 }
276 }
277
278}
int closestHandleToX(int x) const
Given a widget-relative x position, this function returns the closest handle to that position.

References closestHandleToX(), m_handles, m_hoveredHandle, m_selectedHandle, positionFromX(), and setHandlePosition().

◆ mousePressEvent()

void KisLevelsSlider::mousePressEvent ( QMouseEvent * e)
overrideprotected

Definition at line 239 of file KisLevelsSlider.cpp.

240{
241 if (m_handles.size() == 0) {
242 return;
243 }
244 if (e->button() != Qt::LeftButton) {
245 return;
246 }
247
248 qreal mousePosition = positionFromX(e->x());
249 int handleIndex = closestHandleToPosition(mousePosition);
250
251 if (handleIndex != -1) {
252 m_selectedHandle = handleIndex;
253 const int handleX = xFromPosition(m_handles[handleIndex].position);
254 if (qAbs(handleX - e->x()) > handleWidth) {
255 setHandlePosition(handleIndex, mousePosition);
256 } else {
257 update();
258 }
259 }
260}
int xFromPosition(qreal position) const
Given a gradient rect relative position, this function returns the x position in pixels relative to t...

References closestHandleToPosition(), handleWidth, m_handles, m_selectedHandle, positionFromX(), setHandlePosition(), and xFromPosition().

◆ paintEvent()

void KisLevelsSlider::paintEvent ( QPaintEvent * e)
overrideprotected

Definition at line 212 of file KisLevelsSlider.cpp.

213{
214 Q_UNUSED(e);
215
216 QPainter painter(this);
217 const QRect gradientRect_ = gradientRect();
218 // Gradient
219 painter.save();
220 paintGradient(painter, gradientRect_);
221 painter.restore();
222 // Border
223 QColor borderColor = palette().text().color();
224 borderColor.setAlpha(64);
225 painter.setPen(borderColor);
226 painter.drawRect(gradientRect_.adjusted(0, 0, -1, -1));
227 // Handles
228 const QVector<Handle> sortedHandles_ = sortedHandles();
229 const int halfHandleWidth = handleWidth / 2;
230 painter.save();
231 for (const Handle &handle : sortedHandles_) {
232 const int handleX = static_cast<int>(qRound(handle.position * static_cast<qreal>(gradientRect_.width() - 1))) + halfHandleWidth;
233 const QRect handleRect(handleX - halfHandleWidth, gradientRect_.bottom() + 1, handleWidth, handleHeight);
234 paintHandle(painter, handleRect, handle);
235 }
236 painter.restore();
237}
virtual void paintHandle(QPainter &painter, const QRect &rect, const Handle &handle)
Override this function to paint custom handles.
virtual void paintGradient(QPainter &painter, const QRect &rect)=0
Derived classes must override this function to draw the gradient inside the given rect....
virtual QRect gradientRect() const
Gets the rect where the gradient will be painted.

References gradientRect(), handleHeight, handleWidth, paintGradient(), paintHandle(), and sortedHandles().

◆ paintGradient()

virtual void KisLevelsSlider::paintGradient ( QPainter & painter,
const QRect & rect )
protectedpure virtual

Derived classes must override this function to draw the gradient inside the given rect. A border is automatically drawn after.

Implemented in KisInputLevelsSlider.

◆ paintHandle()

void KisLevelsSlider::paintHandle ( QPainter & painter,
const QRect & rect,
const Handle & handle )
protectedvirtual

Override this function to paint custom handles.

Reimplemented in KisThresholdSlider.

Definition at line 169 of file KisLevelsSlider.cpp.

170{
171 painter.setRenderHint(QPainter::Antialiasing, false);
172 const int halfHandleWidth = handleWidth / 2.0;
173 {
174 const QPolygon shape({
175 {rect.left() + halfHandleWidth, rect.top()},
176 {rect.right() + 1, rect.top() + halfHandleWidth},
177 {rect.right() + 1, rect.bottom() + 1},
178 {rect.left(), rect.bottom() + 1},
179 {rect.left(), rect.top() + halfHandleWidth}
180 });
181 painter.setPen(Qt::NoPen);
182 const bool isSelected = handle.index == m_selectedHandle;
183 QColor brushColor =
184 isSelected && hasFocus()
185 ? KisPaintingTweaks::blendColors(handle.color, palette().highlight().color(), 0.25)
186 : handle.color;
187 if (!isEnabled()) {
188 brushColor.setAlpha(64);
189 }
190 painter.setBrush(brushColor);
191 painter.drawPolygon(shape);
192 }
193 {
194 const QPolygon shape({
195 {rect.left() + halfHandleWidth, rect.top()},
196 {rect.right(), rect.top() + halfHandleWidth},
197 {rect.right(), rect.bottom()},
198 {rect.left(), rect.bottom()},
199 {rect.left(), rect.top() + halfHandleWidth}
200 });
201 const bool isHovered = handle.index == m_hoveredHandle;
202 QColor penColor = isHovered && isEnabled() ? palette().highlight().color() : palette().text().color();
203 if (!isHovered) {
204 penColor.setAlpha(64);
205 }
206 painter.setPen(penColor);
207 painter.setBrush(Qt::NoBrush);
208 painter.drawPolygon(shape);
209 }
210}
QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)

References KisPaintingTweaks::blendColors(), KisLevelsSlider::Handle::color, handleWidth, KisLevelsSlider::Handle::index, m_hoveredHandle, and m_selectedHandle.

◆ positionFromX()

qreal KisLevelsSlider::positionFromX ( int x) const
protected

Given a widget-relative x position in pixels, this function returns the normalized position relative to the gradient rect.

Definition at line 136 of file KisLevelsSlider.cpp.

137{
138 const QRect gradientRect_ = gradientRect();
139 return static_cast<qreal>(x - gradientRect_.left()) / static_cast<qreal>(gradientRect_.width());
140}

References gradientRect().

◆ setHandleColor

void KisLevelsSlider::setHandleColor ( int handleIndex,
const QColor & newColor )
virtualslot

Sets the color associated with the given handle.

Definition at line 71 of file KisLevelsSlider.cpp.

72{
73 Q_ASSERT(handleIndex >= 0 && handleIndex < m_handles.size());
74
75 if (newColor == m_handles[handleIndex].color) {
76 return;
77 }
78
79 m_handles[handleIndex].color = newColor;
80
81 update();
82 Q_EMIT handleColorChanged(handleIndex, newColor);
83}
void handleColorChanged(int handleIndex, const QColor &color)
Signal emitted when the color associated with a handle changes.

References handleColorChanged(), and m_handles.

◆ setHandlePosition

void KisLevelsSlider::setHandlePosition ( int handleIndex,
qreal newPosition )
virtualslot

Sets the normalized position of the given handle.

Definition at line 46 of file KisLevelsSlider.cpp.

47{
48 Q_ASSERT(handleIndex >= 0 && handleIndex < m_handles.size());
49
51 newPosition =
52 qBound(
53 handleIndex == m_handles.first().index ? 0.0 : m_handles[handleIndex - 1].position + minimumSpaceBetweenHandles,
54 newPosition,
55 handleIndex == m_handles.last().index ? 1.0 : m_handles[handleIndex + 1].position - minimumSpaceBetweenHandles
56 );
57 } else {
58 newPosition = qBound(0.0, newPosition, 1.0);
59 }
60
61 if (newPosition == m_handles[handleIndex].position) {
62 return;
63 }
64
65 m_handles[handleIndex].position = newPosition;
66
67 update();
68 Q_EMIT handlePositionChanged(handleIndex, newPosition);
69}
void handlePositionChanged(int handleIndex, qreal position)
Signal emitted when the position of a handle changes.
static constexpr qreal minimumSpaceBetweenHandles

References handlePositionChanged(), m_constrainPositions, m_handles, and minimumSpaceBetweenHandles.

◆ sizeHint()

QSize KisLevelsSlider::sizeHint ( ) const
override

Definition at line 85 of file KisLevelsSlider.cpp.

86{
87 return QSize(256, 20) + QSize(handleWidth, handleHeight);
88}

References handleHeight, and handleWidth.

◆ sortedHandles()

QVector< KisLevelsSlider::Handle > KisLevelsSlider::sortedHandles ( ) const
protected

Regardless the index of a handle, they can be unordered in terms of the position. This returns a sorted vector with the handles that have a smaller position first. If two handles have the same position then the index is used for sorting.

Definition at line 101 of file KisLevelsSlider.cpp.

102{
103 QVector<Handle> sortedHandles_ = m_handles;
104 std::sort(sortedHandles_.begin(), sortedHandles_.end(),
105 [](const Handle &lhs, const Handle &rhs)
106 {
107 return qFuzzyCompare(lhs.position, rhs.position) ? lhs.index < rhs.index : lhs.position < rhs.position;
108 }
109 );
110 return sortedHandles_;
111}

References m_handles.

◆ wheelEvent()

void KisLevelsSlider::wheelEvent ( QWheelEvent * e)
overrideprotected

Definition at line 308 of file KisLevelsSlider.cpp.

309{
310 if (e->angleDelta().y() != 0) {
311 handleIncrementInput(e->angleDelta().y(), e->modifiers());
312 e->accept();
313 } else {
314 QWidget::wheelEvent(e);
315 }
316}

References handleIncrementInput().

◆ xFromPosition()

int KisLevelsSlider::xFromPosition ( qreal position) const
protected

Given a gradient rect relative position, this function returns the x position in pixels relative to the widget.

Definition at line 147 of file KisLevelsSlider.cpp.

148{
149 const QRect gradientRect_ = gradientRect();
150 return static_cast<int>(position * static_cast<qreal>(gradientRect_.width())) + gradientRect_.left();
151}

References gradientRect().

Member Data Documentation

◆ handleHeight

constexpr int KisLevelsSlider::handleHeight {11}
staticconstexprprotected

Definition at line 74 of file KisLevelsSlider.h.

74{11};

◆ handleWidth

constexpr int KisLevelsSlider::handleWidth {11}
staticconstexprprotected

Definition at line 73 of file KisLevelsSlider.h.

73{11};

◆ m_constrainPositions

int KisLevelsSlider::m_constrainPositions
protected

This variable indicates if the handles can have unordered positions. If it is set to true then the user won't be able to move a handle pass another one. If it is set to false then the ser will be able to move the handles freely.

Definition at line 89 of file KisLevelsSlider.h.

◆ m_handles

QVector<Handle> KisLevelsSlider::m_handles
protected

The collection of handles.

Definition at line 82 of file KisLevelsSlider.h.

◆ m_hoveredHandle

int KisLevelsSlider::m_hoveredHandle
protected

Definition at line 92 of file KisLevelsSlider.h.

◆ m_selectedHandle

int KisLevelsSlider::m_selectedHandle
protected

Definition at line 91 of file KisLevelsSlider.h.

◆ minimumSpaceBetweenHandles

constexpr qreal KisLevelsSlider::minimumSpaceBetweenHandles {0.001}
staticconstexprprotected

Definition at line 75 of file KisLevelsSlider.h.

75{0.001};

◆ normalPositionIncrement

constexpr qreal KisLevelsSlider::normalPositionIncrement {0.01}
staticconstexprprotected

Definition at line 76 of file KisLevelsSlider.h.

76{0.01};

◆ slowPositionIncrement

constexpr qreal KisLevelsSlider::slowPositionIncrement {0.001}
staticconstexprprotected

Definition at line 77 of file KisLevelsSlider.h.

77{0.001};

The documentation for this class was generated from the following files: