Krita Source Code Documentation
Loading...
Searching...
No Matches
KisSelectionActionsPanel Class Reference

#include <kis_selection_actions_panel.h>

+ Inheritance diagram for KisSelectionActionsPanel:

Classes

struct  Private
 

Public Member Functions

void draw (QPainter &painter)
 
bool eventFilter (QObject *obj, QEvent *event) override
 
 KisSelectionActionsPanel ()=delete
 
 KisSelectionActionsPanel (KisViewManager *viewManager, QWidget *parent)
 
void setEnabled (bool enabled)
 
void setVisible (bool visible)
 
 ~KisSelectionActionsPanel ()
 

Private Member Functions

QPushButton * createButton (const QString &iconName, const QString &tooltip)
 
void drawActionBarBackground (QPainter &gc) const
 
bool handleMove (QEvent *event, const QPoint &pos, QObject *obj)
 
bool handlePress (QEvent *event, const QPoint &pos, Qt::MouseButton button=Qt::LeftButton)
 
bool handleRelease (QEvent *event, const QPoint &pos, QObject *obj)
 
QPoint initialDragHandlePosition () const
 
void setupButtons ()
 
QPoint updateCanvasBoundaries (QPoint position, QWidget *canvasWidget) const
 

Static Private Member Functions

static QPoint mouseEventPos (const QMouseEvent *mouseEvent)
 
static QPoint tabletEventPos (const QTabletEvent *tabletEvent)
 
static bool touchEventPos (const QTouchEvent *touchEvent, QPoint &outPos)
 

Private Attributes

QScopedPointer< Privated
 

Detailed Description

Definition at line 30 of file kis_selection_actions_panel.h.

Constructor & Destructor Documentation

◆ KisSelectionActionsPanel() [1/2]

KisSelectionActionsPanel::KisSelectionActionsPanel ( )
delete

◆ KisSelectionActionsPanel() [2/2]

KisSelectionActionsPanel::KisSelectionActionsPanel ( KisViewManager * viewManager,
QWidget * parent )

Definition at line 85 of file kis_selection_actions_panel.cpp.

86 : QWidget(parent)
87 , d(new Private)
88{
89 d->m_viewManager = viewManager;
90 d->m_selectionManager = viewManager->selectionManager();
91
92 QWidget *canvasWidget = dynamic_cast<QWidget *>(viewManager->canvas());
93
94 // Setup buttons...
95 for (const ActionButtonData &buttonData : Private::buttonData()) {
96 QPushButton *button = createButton(buttonData.iconName, buttonData.tooltip);
97 connect(button, &QPushButton::clicked, d->m_selectionManager, buttonData.slot);
98 button->setParent(canvasWidget);
99 d->m_buttons.append(button);
100 }
101}
QPushButton * createButton(const QString &iconName, const QString &tooltip)
QWidget * canvas() const
Return the actual widget that is displaying the current image.
KisSelectionManager * selectionManager()
QString button(const QWheelEvent &ev)

References button(), KisSelectionActionsPanel::Private::buttonData(), KisViewManager::canvas(), createButton(), d, and KisViewManager::selectionManager().

◆ ~KisSelectionActionsPanel()

KisSelectionActionsPanel::~KisSelectionActionsPanel ( )

Definition at line 103 of file kis_selection_actions_panel.cpp.

104{
105}

Member Function Documentation

◆ createButton()

QPushButton * KisSelectionActionsPanel::createButton ( const QString & iconName,
const QString & tooltip )
private

Definition at line 288 of file kis_selection_actions_panel.cpp.

289{
290 QPushButton *button = new QPushButton();
291 button->setIcon(KisIconUtils::loadIcon(iconName));
292 button->setFixedSize(BUTTON_SIZE, BUTTON_SIZE);
293 button->setToolTip(tooltip);
294 return button;
295}
static constexpr int BUTTON_SIZE
QIcon loadIcon(const QString &name)

References button(), BUTTON_SIZE, and KisIconUtils::loadIcon().

◆ draw()

void KisSelectionActionsPanel::draw ( QPainter & painter)

Definition at line 107 of file kis_selection_actions_panel.cpp.

108{
109 KisSelectionSP selection = d->m_viewManager->selection();
110
111 if (!selection || !d->m_enabled || !d->m_visible) {
112 return;
113 }
114
116
117 for (int i = 0; i < d->m_buttons.size(); i++) {
118 QPushButton *button = d->m_buttons[i];
119 int buttonPosition = i * BUTTON_SIZE;
120 button->move(d->m_dragHandle->position.x() + buttonPosition, d->m_dragHandle->position.y());
121 button->show();
122 }
123}
void drawActionBarBackground(QPainter &gc) const

References button(), BUTTON_SIZE, d, and drawActionBarBackground().

◆ drawActionBarBackground()

void KisSelectionActionsPanel::drawActionBarBackground ( QPainter & gc) const
private

Definition at line 297 of file kis_selection_actions_panel.cpp.

298{
299 const int CORNER_RADIUS = 4;
300 const int PEN_WIDTH = 5;
301 const QColor BACKGROUND_COLOR = Qt::darkGray;
302 const QColor OUTLINE_COLOR(60, 60, 60, 80);
303 const QColor DOT_COLOR = Qt::lightGray;
304 const int DOT_SIZE = 4;
305 const int DOT_SPACING = 5;
306 const QPoint DRAG_HANDLE_RECT_DOTS_OFFSET(10, 10);
307
308 QRectF actionBarRect(d->m_dragHandle->position, QSize(d->m_actionBarWidth, BUTTON_SIZE));
309 QPainterPath bgPath;
310 bgPath.addRoundedRect(actionBarRect, CORNER_RADIUS, CORNER_RADIUS);
311 painter.fillPath(bgPath, BACKGROUND_COLOR);
312
313 QPen pen(OUTLINE_COLOR);
314 pen.setWidth(PEN_WIDTH);
315 painter.setPen(pen);
316 painter.drawPath(bgPath);
317
318 QRectF dragHandleRect(
319 QPoint(d->m_dragHandle->position.x() + d->m_actionBarWidth - BUTTON_SIZE, d->m_dragHandle->position.y()),
320 QSize(BUTTON_SIZE, BUTTON_SIZE));
321 QPainterPath dragHandlePath;
322 dragHandlePath.addRect(dragHandleRect);
323 painter.fillPath(dragHandlePath, BACKGROUND_COLOR);
324
325 const std::list<std::pair<int, int>> DOT_OFFSETS = {{0, 0},
326 {DOT_SPACING, 0},
327 {-DOT_SPACING, 0},
328 {0, DOT_SPACING},
329 {0, -DOT_SPACING},
330 {DOT_SPACING, DOT_SPACING},
331 {DOT_SPACING, -DOT_SPACING},
332 {-DOT_SPACING, DOT_SPACING},
333 {-DOT_SPACING, -DOT_SPACING}};
334
335 QPainterPath dragHandleRectDots;
336 for (const std::pair<int, int> &offset : DOT_OFFSETS) {
337 dragHandleRectDots.addEllipse(offset.first, offset.second, DOT_SIZE, DOT_SIZE);
338 };
339
340 dragHandleRectDots.translate(dragHandleRect.topLeft() + DRAG_HANDLE_RECT_DOTS_OFFSET);
341 painter.fillPath(dragHandleRectDots, DOT_COLOR);
342}

References BUTTON_SIZE, and d.

◆ eventFilter()

bool KisSelectionActionsPanel::eventFilter ( QObject * obj,
QEvent * event )
override

Definition at line 170 of file kis_selection_actions_panel.cpp.

171{
172 switch (event->type()) {
173 case QEvent::FocusIn:
174 event->accept();
175 return true;
176
177 case QEvent::MouseButtonPress: {
178 const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
179 return handlePress(event, mouseEventPos(mouseEvent), mouseEvent->button());
180 }
181 case QEvent::TabletPress: {
182 const QTabletEvent *tabletEvent = static_cast<QTabletEvent *>(event);
183 return handlePress(event, tabletEventPos(tabletEvent));
184 }
185 case QEvent::TouchBegin: {
186 const QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
187 QPoint pos;
188 if (touchEventPos(touchEvent, pos)) {
189 return handlePress(event, pos);
190 }
191 break;
192 }
193
194 case QEvent::MouseMove:
195 if (d->m_pressed) {
196 const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
197 return handleMove(event, mouseEventPos(mouseEvent), obj);
198 }
199 break;
200 case QEvent::TabletMove:
201 if (d->m_pressed) {
202 const QTabletEvent *tabletEvent = static_cast<QTabletEvent *>(event);
203 return handleMove(event, tabletEventPos(tabletEvent), obj);
204 }
205 break;
206 case QEvent::TouchUpdate:
207 if (d->m_pressed) {
208 const QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
209 QPoint pos;
210 if (touchEventPos(touchEvent, pos)) {
211 return handleMove(event, pos, obj);
212 }
213 }
214 break;
215
216 case QEvent::MouseButtonRelease:
217 case QEvent::TabletRelease:
218 case QEvent::TouchEnd:
219 case QEvent::TouchCancel:
220 if (d->m_pressed) {
221 if (d->m_pressedIndex >= 0 && d->m_pressedIndex < d->m_buttons.size()) {
222 // A button was pressed, trigger it on the next event loop.
223 QTimer::singleShot(0, d->m_buttons[d->m_pressedIndex], &QPushButton::click);
224 }
225 d->m_pressed = false;
226 d->m_pressedIndex = -1;
227 event->accept();
228 return true;
229 }
230 break;
231
232 default:
233 break;
234 }
235 return false;
236}
bool handlePress(QEvent *event, const QPoint &pos, Qt::MouseButton button=Qt::LeftButton)
static QPoint tabletEventPos(const QTabletEvent *tabletEvent)
static QPoint mouseEventPos(const QMouseEvent *mouseEvent)
static bool touchEventPos(const QTouchEvent *touchEvent, QPoint &outPos)
bool handleMove(QEvent *event, const QPoint &pos, QObject *obj)

References d, handleMove(), handlePress(), mouseEventPos(), tabletEventPos(), and touchEventPos().

◆ handleMove()

bool KisSelectionActionsPanel::handleMove ( QEvent * event,
const QPoint & pos,
QObject * obj )
private

Definition at line 369 of file kis_selection_actions_panel.cpp.

370{
371 // Are we dragging the bar or was a button pressed?
372 if (d->m_pressedIndex < 0 || d->m_pressedIndex >= d->m_buttons.size()) {
373 // bound actionBar to stay within canvas space
374 QWidget *canvasWidget = d->m_viewManager->canvas();
375
376 // Explicitly casting just in case inheritance adjusts the pointer weirdly
377 // (MSVC does spicy things like that sometimes to keep you on your toes.)
378 if (obj == static_cast<QObject *>(canvasWidget)) {
379 QPoint newPos = pos - d->m_dragHandle->dragOrigin;
380 d->m_dragHandle->position = updateCanvasBoundaries(newPos, canvasWidget);
381 canvasWidget->update();
382 event->accept();
383 return true;
384 } else {
385 return false;
386 }
387 } else {
388 // Button was pressed, we're just waiting for a release.
389 event->accept();
390 return true;
391 }
392}
QPoint updateCanvasBoundaries(QPoint position, QWidget *canvasWidget) const

References d, and updateCanvasBoundaries().

◆ handlePress()

bool KisSelectionActionsPanel::handlePress ( QEvent * event,
const QPoint & pos,
Qt::MouseButton button = Qt::LeftButton )
private

Definition at line 344 of file kis_selection_actions_panel.cpp.

345{
346 if (d->m_pressed) {
347 event->accept();
348 return true;
349 }
350
351 if (button == Qt::LeftButton) {
352 QRect targetRect(d->m_dragHandle->position, QSize(BUTTON_SIZE * d->m_buttonCount, BUTTON_SIZE));
353 if (targetRect.contains(pos)) {
354 d->m_pressed = true;
355
356 d->m_pressedIndex = (pos.x() - targetRect.left()) / BUTTON_SIZE;
357 if (d->m_pressedIndex < 0 || d->m_pressedIndex >= d->m_buttons.size()) {
358 d->m_dragHandle->dragOrigin = pos - d->m_dragHandle->position;
359 }
360
361 event->accept();
362 return true;
363 }
364 }
365
366 return false;
367}

References button(), BUTTON_SIZE, and d.

◆ handleRelease()

bool KisSelectionActionsPanel::handleRelease ( QEvent * event,
const QPoint & pos,
QObject * obj )
private

◆ initialDragHandlePosition()

QPoint KisSelectionActionsPanel::initialDragHandlePosition ( ) const
private

Definition at line 268 of file kis_selection_actions_panel.cpp.

269{
270 KisSelectionSP selection = d->m_viewManager->selection();
271 KisCanvasWidgetBase *canvas = dynamic_cast<KisCanvasWidgetBase*>(d->m_viewManager->canvas());
272 KIS_ASSERT(selection);
273 KIS_ASSERT(canvas);
274
275 QRectF selectionBounds = selection->selectedRect();
276 int selectionBottom = selectionBounds.bottom();
277 QPointF selectionCenter = selectionBounds.center();
278 QPointF bottomCenter(selectionCenter.x(), selectionBottom);
279
280 QPointF widgetBottomCenter = canvas->coordinatesConverter()->imageToWidget(bottomCenter); // converts current selection's QPointF into canvasWidget's QPointF space
281
282 widgetBottomCenter.setX(widgetBottomCenter.x() - (d->m_actionBarWidth / 2)); // centers toolbar midpoint with the selection center
283 widgetBottomCenter.setY(widgetBottomCenter.y() + BUFFER_SPACE);
284
285 return updateCanvasBoundaries(widgetBottomCenter.toPoint(), d->m_viewManager->canvas());
286}
KisCoordinatesConverter * coordinatesConverter() const
_Private::Traits< T >::Result imageToWidget(const T &obj) const
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
static constexpr int BUFFER_SPACE
QRect selectedRect() const

References BUFFER_SPACE, KisCanvasWidgetBase::coordinatesConverter(), d, KisCoordinatesConverter::imageToWidget(), KIS_ASSERT, KisSelection::selectedRect(), and updateCanvasBoundaries().

◆ mouseEventPos()

QPoint KisSelectionActionsPanel::mouseEventPos ( const QMouseEvent * mouseEvent)
staticprivate

Definition at line 394 of file kis_selection_actions_panel.cpp.

395{
396#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
397 return mouseEvent->position().toPoint();
398#else
399 return mouseEvent->pos();
400#endif
401}

◆ setEnabled()

void KisSelectionActionsPanel::setEnabled ( bool enabled)

Definition at line 160 of file kis_selection_actions_panel.cpp.

161{
162 bool configurationChanged = enabled != d->m_enabled;
163 d->m_enabled = enabled;
164 if (configurationChanged) {
165 // Reset visibility when configuration changes
166 setVisible(d->m_visible);
167 }
168}

References d, and setVisible().

◆ setupButtons()

void KisSelectionActionsPanel::setupButtons ( )
private

◆ setVisible()

void KisSelectionActionsPanel::setVisible ( bool visible)

Definition at line 125 of file kis_selection_actions_panel.cpp.

126{
127 QWidget *canvasWidget = dynamic_cast<QWidget *>(d->m_viewManager->canvas());
128 if (!canvasWidget) {
129 return;
130 }
131
132 p_visible &= d->m_enabled;
133
134 const bool VISIBILITY_CHANGED = d->m_visible != p_visible;
135 if (!VISIBILITY_CHANGED) {
136 return;
137 }
138
139 if (d->m_viewManager->selection() && p_visible) { // Now visible!
140 canvasWidget->installEventFilter(this);
141
142 if (!d->m_dragHandle) {
143 d->m_dragHandle.reset(new Private::DragHandle());
144 d->m_dragHandle->position = initialDragHandlePosition();
145 }
146 } else { // Now hidden!
147 canvasWidget->removeEventFilter(this);
148
149 for (QPushButton *button : d->m_buttons) {
150 button->hide();
151 }
152
153 d->m_pressed = false;
154 d->m_dragHandle.reset();
155 }
156
157 d->m_visible = p_visible;
158}

References button(), d, and initialDragHandlePosition().

◆ tabletEventPos()

QPoint KisSelectionActionsPanel::tabletEventPos ( const QTabletEvent * tabletEvent)
staticprivate

Definition at line 403 of file kis_selection_actions_panel.cpp.

404{
405#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
406 return tabletEvent->position().toPoint();
407#else
408 return tabletEvent->pos();
409#endif
410}

◆ touchEventPos()

bool KisSelectionActionsPanel::touchEventPos ( const QTouchEvent * touchEvent,
QPoint & outPos )
staticprivate

Definition at line 412 of file kis_selection_actions_panel.cpp.

413{
414#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
415 if (touchEvent->pointCount() < 1) {
416 return false;
417 } else {
418 outPos = touchEvent->points().first().position().toPoint();
419 return true;
420 }
421#else
422 const QList<QTouchEvent::TouchPoint> &touchPoints = touchEvent->touchPoints();
423 if (touchPoints.isEmpty()) {
424 return false;
425 } else {
426 outPos = touchPoints.first().pos().toPoint();
427 return true;
428 }
429#endif
430}

◆ updateCanvasBoundaries()

QPoint KisSelectionActionsPanel::updateCanvasBoundaries ( QPoint position,
QWidget * canvasWidget ) const
private

Definition at line 238 of file kis_selection_actions_panel.cpp.

239{
240 QRect canvasBounds = canvasWidget->rect();
241
242 const int ACTION_BAR_WIDTH = d->m_actionBarWidth;
243 const int ACTION_BAR_HEIGHT = BUTTON_SIZE;
244
245 int pos_x_min = canvasBounds.left() + BUFFER_SPACE;
246 int pos_x_max = canvasBounds.right() - ACTION_BAR_WIDTH - BUFFER_SPACE;
247
248 int pos_y_min = canvasBounds.top() + BUFFER_SPACE;
249 int pos_y_max = canvasBounds.bottom() - ACTION_BAR_HEIGHT - BUFFER_SPACE;
250
251 //Ensure that max is always bigger than min
252 //If the window is small enough max could be smaller than min
253 if (pos_x_max < pos_x_min) {
254 pos_x_max = pos_x_min;
255 }
256
257 //It is pretty implausible for it to happen vertically but better safe than sorry
258 if (pos_y_max < pos_y_min) {
259 pos_y_max = pos_y_min;
260 }
261
262 position.setX(qBound(pos_x_min, position.x(), pos_x_max));
263 position.setY(qBound(pos_y_min, position.y(), pos_y_max));
264
265 return position;
266}

References BUFFER_SPACE, BUTTON_SIZE, and d.

Member Data Documentation

◆ d

QScopedPointer<Private> KisSelectionActionsPanel::d
private

Definition at line 61 of file kis_selection_actions_panel.h.


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