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.
rgba palette[MAX_PALETTE]
Definition palette.c:35

References gradientRect(), handleHeight, handleWidth, paintGradient(), paintHandle(), palette, 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, m_selectedHandle, and palette.

◆ 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: