31#include <QTabletEvent>
36#include <klocalizedstring.h>
37#include <ktoggleaction.h>
38#include <kconfiggroup.h>
42#include <QApplication>
44#include <QPainterPath>
126 d->m_viewManager = viewManager;
139 for (
int i = 0; i < data.length(); i++) {
142 connect(
button, &QAbstractButton::clicked,
d->m_selectionManager, buttonData.
slot);
147 d->sapPinButtonIndex = i;
148 button->setCheckable(
true);
153 connect(
d->m_handleWidget, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(
showContextMenu(QPoint)));
155 d->disable_action =
new KisAction(i18n(
"Disable selection actions bar"));
166 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"");
167 d->m_dragHandle.dragOffset = cfg.readEntry(
d->dragOffsetConfigName, QPoint(0, 0));
181 if (!selection || !
d->m_enabled || !
d->m_visible) {
185 if (
d->m_pressed &&
d->behavior == Behavior::FreeFloating) {
193 button->draw(painter, displayRendererInterface);
196 if (
d->m_handleWidget->isEnabled()) {
197 d->m_handleWidget->draw(painter, displayRendererInterface);
204 d->orientation = mode;
205 d->m_handleWidget->setOrientation(mode);
214 if (enabled && !
d->m_handleWidget->isEnabled()) {
215 d->m_handleWidget->setEnabled(enabled);
219 if (!enabled &&
d->m_handleWidget->isEnabled()) {
220 d->m_handleWidget->setEnabled(enabled);
228 QWidget *canvasWidget =
dynamic_cast<QWidget *
>(
d->m_viewManager->canvas());
233 QRect canvasBounds = canvasWidget->rect();
234 QPoint result = QPoint();
236 switch (
d->position) {
238 result.setY(canvasBounds.bottom());
239 result.setX((canvasBounds.width() -
d->m_actionBarWidth) / 2);
242 result.setY(canvasBounds.bottom());
243 result.setX(canvasBounds.left());
246 result.setY(canvasBounds.bottom());
247 result.setX(canvasBounds.right());
250 result.setY((canvasBounds.height() -
d->m_actionBarHeight) / 2);
251 result.setX(canvasBounds.left());
254 result.setY((canvasBounds.height() -
d->m_actionBarHeight) / 2);
255 result.setX(canvasBounds.right());
258 result.setY(canvasBounds.top());
259 result.setX((canvasBounds.width() -
d->m_actionBarWidth) / 2);
262 result.setY(canvasBounds.top());
263 result.setX(canvasBounds.left());
266 result.setY(canvasBounds.top());
267 result.setX(canvasBounds.right());
276 if (!
d->m_handleWidget)
return;
278 if (
d->orientation == Orientation::Horizontal) {
279 d->m_innerActionBarHeight =
d->m_actionBarHeight =
BUTTON_SIZE;
280 d->m_innerActionBarWidth =
d->m_actionBarWidth =
BUTTON_SIZE *
d->m_buttonCount;
281 if (
d->m_handleWidget->isEnabled()) {
282 d->m_innerActionBarWidth =
BUTTON_SIZE * (
d->m_buttonCount - 1);
284 }
else if (
d->orientation == Orientation::Vertical) {
285 d->m_innerActionBarHeight =
d->m_actionBarHeight =
BUTTON_SIZE *
d->m_buttonCount;
286 d->m_innerActionBarWidth =
d->m_actionBarWidth =
BUTTON_SIZE;
287 if (
d->m_handleWidget->isEnabled()) {
288 d->m_innerActionBarHeight =
BUTTON_SIZE * (
d->m_buttonCount - 1);
297 QWidget *canvasWidget =
dynamic_cast<QWidget *
>(
d->m_viewManager->canvas());
302 p_visible &=
d->m_enabled;
304 const bool VISIBILITY_CHANGED =
d->m_visible != p_visible;
305 if (!VISIBILITY_CHANGED) {
309 d->configure_action->setVisible(p_visible &&
d->m_viewManager->selection());
313 d->m_visible = p_visible;
315 if (
d->m_viewManager->selection() && p_visible) {
316 d->m_handleWidget->installEventFilter(
this);
319 d->m_handleWidget->removeEventFilter(
this);
324 d->m_handleWidget->hide();
326 d->m_pressed =
false;
333 bool configurationChanged = enabled !=
d->m_enabled;
335 d->configure_action->setVisible(enabled &&
d->m_viewManager->selection());
337 d->m_enabled = enabled;
338 if (configurationChanged) {
348 switch (event->type()) {
349 case QEvent::MouseButtonPress: {
350 const QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>(event);
353 case QEvent::TabletPress: {
354 const QTabletEvent *tabletEvent =
static_cast<QTabletEvent *
>(event);
357 case QEvent::TouchBegin: {
358 const QTouchEvent *touchEvent =
static_cast<QTouchEvent *
>(event);
366 case QEvent::MouseMove:
368 const QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>(event);
372 case QEvent::TabletMove:
374 const QTabletEvent *tabletEvent =
static_cast<QTabletEvent *
>(event);
378 case QEvent::TouchUpdate:
380 const QTouchEvent *touchEvent =
static_cast<QTouchEvent *
>(event);
388 case QEvent::MouseButtonRelease:
389 case QEvent::TabletRelease:
390 case QEvent::TouchEnd:
391 case QEvent::TouchCancel:
407 Q_FOREACH(QWidget* btn,
d->m_buttons) {
408 btn->setParent(canvas->
widget());
414 d->m_handleWidget->setParent(canvas->
widget());
416 d->m_handleWidget->show();
430 QRect canvasBounds = canvasWidget->rect();
432 const int ACTION_BAR_WIDTH =
d->m_actionBarWidth;
433 const int ACTION_BAR_HEIGHT =
d->m_actionBarHeight;
436 int pos_x_max = canvasBounds.right() - ACTION_BAR_WIDTH -
BUFFER_SPACE;
439 int pos_y_max = canvasBounds.bottom() - ACTION_BAR_HEIGHT -
BUFFER_SPACE;
443 if (pos_x_max < pos_x_min) {
444 pos_x_max = pos_x_min;
448 if (pos_y_max < pos_y_min) {
449 pos_y_max = pos_y_min;
452 position.setX(qBound(pos_x_min, position.x(), pos_x_max));
453 position.setY(qBound(pos_y_min, position.y(), pos_y_max));
462 QPoint anchor = selection.center();
463 QPoint offsetted = selection.center();
464 qreal barHorizontalOffset =
d->m_actionBarWidth;
465 qreal barVerticalOffset =
d->m_actionBarHeight;
469 case Position::Bottom:
470 anchor = QPoint(selection.center().x(), 0);
471 offsetted = anchor - QPoint(barHorizontalOffset/2, 0);
473 case Position::TopLeft:
474 case Position::BottomLeft:
475 anchor = QPoint(selection.left(), 0);
478 case Position::TopRight:
479 case Position::BottomRight:
480 anchor = QPoint(selection.right(), 0);
481 offsetted = anchor - QPoint(barHorizontalOffset, 0);
486 anchor = QPoint(selection.left(), 0);
490 case Position::Right:
491 anchor = QPoint(selection.right(), 0);
498 case Position::TopLeft:
499 case Position::TopRight:
500 anchor += QPoint(0, selection.top());
503 case Position::Bottom:
504 case Position::BottomLeft:
505 case Position::BottomRight:
506 anchor += QPoint(0, selection.bottom());
511 case Position::Right:
512 anchor += QPoint(0, selection.center().y());
513 offsetted += QPoint(0, selection.center().y() - barVerticalOffset/2);
518 if (calculateOnlyAnchor) {
529 QPoint anchor = selection.center();
530 QPoint offsetted = selection.center();
531 qreal barVerticalOffset =
d->m_actionBarHeight;
532 qreal barHorizontalOffset =
d->m_actionBarWidth;
536 case Position::Right:
537 anchor = QPoint(0, selection.center().y());
538 offsetted = -QPoint(0, barVerticalOffset/2);
540 case Position::TopLeft:
541 case Position::TopRight:
542 anchor = QPoint(0, selection.top());
543 offsetted = QPoint();
545 case Position::BottomLeft:
546 case Position::BottomRight:
547 anchor = QPoint(0, selection.bottom());
548 offsetted = -QPoint(0, barVerticalOffset);
552 anchor = QPoint(0, selection.top());
556 case Position::Bottom:
557 anchor = QPoint(0, selection.bottom());
564 case Position::TopLeft:
565 case Position::BottomLeft:
566 anchor += QPoint(selection.left(), 0);
569 case Position::Right:
570 case Position::TopRight:
571 case Position::BottomRight:
572 anchor += QPoint(selection.right(), 0);
577 case Position::Bottom:
578 anchor += QPoint(selection.center().x(), 0);
579 offsetted += QPoint(- barHorizontalOffset/2, 0);
583 if (calculateOnlyAnchor) {
586 return anchor + offsetted;
591 if (!
d->m_viewManager) {
598 if (!canvas || !selection) {
602 QPainterPath selectionOutline = selection->
outlineCache();
609 QRectF selectionBoundsWidget = converter->
imageToWidget(selectionOutline).boundingRect();
611 return selectionBoundsWidget;
616 if (
d->orientation == Orientation::Horizontal) {
625 if (
d->behavior == Behavior::Fixed) {
630 widgetTopLeftPosition +=
d->m_dragHandle.dragOffset;
639 QPen pen = painter.pen();
640 pen.setStyle(Qt::CustomDashLine);
641 pen.setDashPattern({6, 6});
642 pen.setColor(Qt::darkGray);
645 QPoint offset = QPoint(
d->m_actionBarWidth/2,
d->m_actionBarHeight/2);
646 painter.drawLine(QLine(initial,
d->m_dragHandle.position + offset));
649 pen.setStyle(Qt::SolidLine);
652 painter.drawLine(initial + QPoint(xSize, xSize), initial - QPoint(xSize, xSize));
653 painter.drawLine(initial + QPoint(xSize, -xSize), initial + QPoint(-xSize, xSize));
660 const int cornerRadius = 4;
661 QColor outlineColor = qApp->palette().window().color();
663 QColor bgColor = qApp->palette().window().color();
667 bgColor = bgColor.lighter(120);
679 QColor bgColorTrans = bgColor;
680 bgColorTrans.setAlpha(80);
681 const int outline_width = 4;
684 QRectF contrastOutline(
d->m_dragHandle.position - QPoint(outline_width + 1,outline_width + 1), QSize(
d->m_actionBarWidth,
d->m_actionBarHeight) +QSize(outline_width + 1,outline_width + 1) * 2);
685 QRectF midOutline(
d->m_dragHandle.position - QPoint(outline_width,outline_width), QSize(
d->m_actionBarWidth,
d->m_actionBarHeight) +QSize(outline_width,outline_width) * 2);
687 QRectF centerBackground(
d->m_dragHandle.position - QPoint(outline_width,outline_width) / 2, QSize(
d->m_innerActionBarWidth,
d->m_innerActionBarHeight) +QSize(outline_width,outline_width));
689 QPainterPath outlinePath;
690 QPainterPath contrastOutlinePath;
692 bgPath.addRoundedRect(centerBackground, cornerRadius, cornerRadius);
693 outlinePath.addRoundedRect(midOutline, cornerRadius, cornerRadius);
694 contrastOutlinePath.addRoundedRect(contrastOutline, cornerRadius, cornerRadius);
696 painter.fillPath(contrastOutlinePath, bgColorTrans);
697 painter.fillPath(outlinePath, outlineColor);
698 painter.fillPath(bgPath, bgColor);
708 if (
button == Qt::LeftButton) {
710 d->m_dragHandle.dragOrigin = pos -
d->m_dragHandle.dragOffset;
711 d->m_handleWidget->set_held(
true);
722 QWidget *canvasWidget =
d->m_viewManager->canvas();
723 QPoint newPos = pos -
d->m_dragHandle.dragOrigin;
724 d->m_dragHandle.dragOffset = newPos;
728 canvasWidget->update();
735 d->m_handleWidget->set_held(
false);
736 d->m_pressed =
false;
739 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"");
740 cfg.writeEntry(
d->dragOffsetConfigName,
d->m_dragHandle.dragOffset);
748 if (!
d->m_handleWidget)
755 if (
d->orientation == Orientation::Vertical) {
756 d->m_handleWidget->move(
d->m_dragHandle.position.x(),
757 d->m_dragHandle.position.y() +
d->m_buttons.size() *
BUTTON_SIZE);
758 }
else if (
d->orientation == Orientation::Horizontal) {
759 d->m_handleWidget->move(
d->m_dragHandle.position.x() +
d->m_buttons.size() *
BUTTON_SIZE,
760 d->m_dragHandle.position.y());
762 d->m_handleWidget->show();
768 if (
d->orientation == Orientation::Vertical) {
769 button->move(
d->m_dragHandle.position.x(),
d->m_dragHandle.position.y() + buttonPosition);
770 }
else if (
d->orientation == Orientation::Horizontal) {
771 button->move(
d->m_dragHandle.position.x() + buttonPosition,
d->m_dragHandle.position.y());
781#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
790#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
799#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
800 if (touchEvent->pointCount() < 1) {
808 if (touchPoints.isEmpty()) {
818 return d->m_dragHandle.position + pos;
823 QMenu menu = QMenu();
824 menu.addAction(
d->disable_action);
825 menu.addAction(
d->configure_action);
848 KConfigGroup silentCfg = KSharedConfig::openConfig()->group(
"");
853 bool resetOffset =
false;
864 if (resetOffset && !skipResettingOffset) {
865 d->m_dragHandle.dragOffset = QPoint();
866 silentCfg.writeEntry(
d->dragOffsetConfigName, QPoint());
869 if (
d->sapPinButtonIndex >= 0 &&
d->m_buttons[
d->sapPinButtonIndex] &&
d->m_buttons[
d->sapPinButtonIndex]->isCheckable()) {
886 d->m_handleWidget->themeChanged();
893 d->position = position;
894 QBrush brush(Qt::cyan);
896 brush.setColor(QColor(100 + 20*(
int)position, 100, 100, 150));
897 painter.setBrush(brush);
898 painter.drawRect(QRect(
p, QSize(
d->m_actionBarWidth,
d->m_actionBarHeight)));
908 for (
int position = 0; position < 8; position++) {
913 d->position = remember;
KisAction * actionByName(const QString &name) const
KisActionManager * actionManager
static KisConfigNotifier * instance()
void notifyConfigChanged(void)
SelectionActionsBarOrientation selectionActionBarOrientation(bool defaultValue=false) const
SelectionActionsBarPosition
SelectionActionsBarBehavior
SelectionActionsBarBehavior selectionActionBarBehavior(bool defaultValue=false) const
void setSelectionActionBarOrientation(SelectionActionsBarOrientation value)
SelectionActionsBarOrientation
SelectionActionsBarPosition selectionActionBarPosition(bool defaultValue=false) const
void setSelectionActionBarPosition(SelectionActionsBarPosition value)
void setSelectionActionBar(bool value)
_Private::Traits< T >::Result imageToWidget(const T &obj) const
static KisPart * instance()
void showContextMenu(const QPoint &pos)
void disableSelectionActionsPanel()
void setVisible(bool visible)
void drawAnchorWhileMoving(QPainter &painter) const
End of positioning ///.
bool handlePress(QEvent *event, const QPoint &pos, Qt::MouseButton button=Qt::LeftButton)
void recalculateDimensions()
void movePanelWidgets()
Moves all the widgets that are a part of the panel.
QScopedPointer< Private > d
void drawDebugRectangle(QPainter &painter, Position position)
void setOrientation(Orientation orientation)
void configChanged(bool skipResettingOffset=false)
bool eventFilter(QObject *obj, QEvent *event) override
void configureSelectionActionsPanel()
QPoint currentTopLeftPosition() const
bool handleRelease(QEvent *event)
KisSelectionActionsPanel()=delete
QPoint tabletEventPos(const QTabletEvent *tabletEvent)
QPoint transformHandleCoords(QPoint pos)
void canvasStateChanged()
void setHandleEnabled(bool enabled)
bool handleMove(QEvent *event, const QPoint &pos)
QPoint verticalFreeFloatingTopLeftPosition(bool calculateOnlyAnchor=false) const
QPoint horizontalFreeFloatingTopLeftPosition(bool calculateOnlyAnchor=false) const
QPoint getFixedPosition() const
Positioning ///.
QPoint clipPositionToCanvasBoundaries(QPoint position, QWidget *canvasWidget) const
QPoint mouseEventPos(const QMouseEvent *mouseEvent)
void canvasWidgetChanged(KisCanvasWidgetBase *canvas)
void draw(QPainter &painter, const KoColorDisplayRendererInterface *displayRendererInterface)
bool touchEventPos(const QTouchEvent *touchEvent, QPoint &outPos)
void drawDebugRectanglesForFreeFloatingBehaviour(QPainter &painter)
void drawActionBarBackground(QPainter &gc, const KoColorDisplayRendererInterface *displayRendererInterface) const
void setEnabled(bool enabled)
~KisSelectionActionsPanel()
QPoint freeFloatingInitialTopLeftPosition(bool calculateOnlyAnchor=false) const
QRectF getWidgetSelectionRect() const
void imageResizeToSelection()
void fillForegroundColor()
void copySelectionToNewLayer()
KisActionManager * actionManager() const
QWidget * canvas() const
Return the actual widget that is displaying the current image.
KisSelectionManager * selectionManager()
virtual QColor convertColorToDisplayColorSpace(const KoColor color) const =0
convertColorToDisplayColorSpace
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
static constexpr int BIG_BUFFER_SPACE_X
static constexpr int BUFFER_SPACE
static constexpr int BIG_BUFFER_SPACE_Y
static constexpr int BUTTON_SIZE
QString button(const QWheelEvent &ev)
void updateIcon(QAbstractButton *button)
void dragColor(QColor *color, const QColor &baseColor, qreal threshold)
KisSelectionManager * m_selectionManager
KisSelectionActionsPanelHandle * m_handleWidget
int m_innerActionBarWidth
const QString dragOffsetConfigName
QList< KisSelectionActionsPanelButton * > m_buttons
KisAction * configure_action
KisViewManager * m_viewManager
KisAction * disable_action
static const QVector< ActionButtonData > & buttonData()
int m_innerActionBarHeight
QPainterPath outlineCache() const