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

#include <KisToolSelectMagnetic.h>

+ Inheritance diagram for KisToolSelectMagnetic:

Public Slots

void activate (const QSet< KoShape * > &shapes) override
 
void deactivate () override
 
void slotCalculateEdge ()
 
void slotSetAnchorGap (int)
 
void slotSetFilterRadius (qreal)
 
void slotSetSearchRadius (int)
 
void slotSetThreshold (int)
 
void undoPoints ()
 

Signals

void setButtonsEnabled (bool)
 

Public Member Functions

void beginPrimaryAction (KoPointerEvent *event) override
 
void continuePrimaryAction (KoPointerEvent *event) override
 
QWidget * createOptionWidget () override
 
void endPrimaryAction (KoPointerEvent *event) override
 
void keyPressEvent (QKeyEvent *event) override
 
void keyReleaseEvent (QKeyEvent *event) override
 
 KisToolSelectMagnetic (KoCanvasBase *canvas)
 
void mouseMoveEvent (KoPointerEvent *event) override
 
void paint (QPainter &gc, const KoViewConverter &converter) override
 
void requestStrokeCancellation () override
 
void requestStrokeEnd () override
 
void resetCursorStyle () override
 
 ~KisToolSelectMagnetic () override=default
 
- Public Member Functions inherited from KisToolSelectBase< BaseClass >
void activate (const QSet< KoShape * > &shapes) override
 
void activateAlternateAction (KisTool::AlternateAction action) override
 
SelectionAction alternateSelectionAction () const
 
bool antiAliasSelection () const
 
void beginAlternateAction (KoPointerEvent *event, KisTool::AlternateAction action) override
 
bool beginMoveSelectionInteraction ()
 
void beginPrimaryAction (KoPointerEvent *event) override
 
bool beginSelectInteraction ()
 
QList< int > colorLabelsSelected () const
 
void continueAlternateAction (KoPointerEvent *event, KisTool::AlternateAction action) override
 
void continuePrimaryAction (KoPointerEvent *event) override
 
QWidget * createOptionWidget () override
 
void deactivate () override
 
void deactivateAlternateAction (KisTool::AlternateAction action) override
 
void endAlternateAction (KoPointerEvent *event, KisTool::AlternateAction action) override
 
bool endMoveSelectionInteraction ()
 
void endPrimaryAction (KoPointerEvent *event) override
 
bool endSelectInteraction ()
 
int featherSelection () const
 
int growSelection () const
 
bool isMovingSelection () const
 
bool isSelecting () const
 
void keyPressEvent (QKeyEvent *event) override
 
void keyReleaseEvent (QKeyEvent *event) override
 
 KisToolSelectBase (KoCanvasBase *canvas, const QCursor cursor, const QString toolName)
 
 KisToolSelectBase (KoCanvasBase *canvas, const QString toolName)
 
 KisToolSelectBase (KoCanvasBase *canvas, QCursor cursor, QString toolName, KoToolBase *delegateTool)
 
KisNodeSP locateSelectionMaskUnderCursor (const QPointF &pos, Qt::KeyboardModifiers modifiers)
 
void mouseMoveEvent (KoPointerEvent *event) override
 
QMenu * popupActionsMenu () override
 
KisPopupWidgetInterfacepopupWidget () override
 
SampleLayersMode sampleLayersMode () const
 
SelectionAction selectionAction () const
 
bool selectionDidMove () const
 
SelectionMode selectionMode () const
 
KisSelectionOptionsselectionOptionWidget ()
 
virtual void setAlternateSelectionAction (SelectionAction action)
 
bool stopGrowingAtDarkestPixel () const
 
void updateActionShortcutToolTips ()
 
void updateCursorDelayed ()
 

Protected Attributes

KisSelectionToolConfigWidgetHelper m_widgetHelper
 
- Protected Attributes inherited from KisToolSelectBase< BaseClass >
SelectionAction m_selectionActionAlternate
 
KisSelectionToolConfigWidgetHelper m_widgetHelper
 

Private Member Functions

void calculateCheckPoints (vQPointF points)
 
void checkIfAnchorIsSelected (QPointF pt)
 
vQPointF computeEdgeWrapper (QPoint a, QPoint b)
 
void deleteSelectedAnchor ()
 
void drawAnchors (QPainter &gc)
 
void finishSelectionAction ()
 
void reEvaluatePoints ()
 
void resetVariables ()
 
void updateCanvas ()
 
void updateContinuedMode ()
 
void updateFeedback ()
 
int updateInitialAnchorBounds (QPoint pt)
 
void updatePaintPath ()
 
void updateSelectedAnchor ()
 

Private Attributes

int m_anchorGap {30}
 
QVector< QPoint > m_anchorPoints
 
bool m_complete {false}
 
KConfigGroup m_configGroup
 
bool m_continuedMode {false}
 
QPointF m_cursorOnPress
 
qreal m_filterRadius {3.0}
 
bool m_finished {false}
 
QPoint m_lastAnchor
 
QPointF m_lastCursorPos
 
KisSignalCompressor m_mouseHoverCompressor
 
QPainterPath m_paintPath
 
QVector< vQPointFm_pointCollection
 
QVector< QPointF > m_points
 
int m_searchRadius {30}
 
bool m_selected {false}
 
int m_selectedAnchor {0}
 
QRectF m_snapBound
 
int m_threshold {70}
 
QScopedPointer< KisMagneticWorkerm_worker
 

Additional Inherited Members

- Public Types inherited from KisToolSelectBase< BaseClass >
enum  SampleLayersMode { SampleAllLayers , SampleCurrentLayer , SampleColorLabeledLayers }
 
- Protected Member Functions inherited from KisToolSelectBase< BaseClass >
virtual bool isPixelOnly () const
 
virtual bool usesColorLabels () const
 

Detailed Description

Definition at line 19 of file KisToolSelectMagnetic.h.

Constructor & Destructor Documentation

◆ KisToolSelectMagnetic()

KisToolSelectMagnetic::KisToolSelectMagnetic ( KoCanvasBase * canvas)

Definition at line 48 of file KisToolSelectMagnetic.cc.

49 : KisToolSelect(canvas,
50 KisCursor::load("tool_magnetic_selection_cursor.png", 6, 6),
51 i18n("Magnetic Selection"))
52 , m_worker(nullptr)
54{ }
static QCursor load(const QString &cursorName, int hotspotX=-1, int hotspotY=-1)
QScopedPointer< KisMagneticWorker > m_worker
KisSignalCompressor m_mouseHoverCompressor
KisToolSelectBase< FakeBaseTool > KisToolSelect

◆ ~KisToolSelectMagnetic()

KisToolSelectMagnetic::~KisToolSelectMagnetic ( )
overridedefault

Member Function Documentation

◆ activate

void KisToolSelectMagnetic::activate ( const QSet< KoShape * > & shapes)
overrideslot

Definition at line 670 of file KisToolSelectMagnetic.cc.

671{
672 m_worker.reset(new KisMagneticWorker(image()->projection()));
673 m_configGroup = KSharedConfig::openConfig()->group(toolId());
674 connect(action("undo_polygon_selection"), SIGNAL(triggered()), SLOT(undoPoints()), Qt::UniqueConnection);
675 connect(&m_mouseHoverCompressor, SIGNAL(timeout()), this, SLOT(slotCalculateEdge()));
677}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void activate(const QSet< KoShape * > &shapes) override

References KisToolSelectBase< BaseClass >::activate(), connect(), m_configGroup, m_mouseHoverCompressor, m_worker, slotCalculateEdge(), and undoPoints().

◆ beginPrimaryAction()

void KisToolSelectMagnetic::beginPrimaryAction ( KoPointerEvent * event)
override

Definition at line 207 of file KisToolSelectMagnetic.cc.

208{
210 if (isMovingSelection()) {
211 return;
212 }
213
214 setMode(KisTool::PAINT_MODE);
215 QPointF temp(convertToPixelCoord(event));
216
217 if (!image()->bounds().contains(temp.toPoint())) {
218 return;
219 }
220
221 m_cursorOnPress = temp;
222
224
225 if (m_complete || m_selected) {
226 return;
227 }
228
229 if (m_anchorPoints.count() != 0) {
230 vQPointF edge = computeEdgeWrapper(m_anchorPoints.last(), temp.toPoint());
231 m_points.append(edge);
232 m_pointCollection.push_back(edge);
233 } else {
235 updateInitialAnchorBounds(temp.toPoint());
236 Q_EMIT setButtonsEnabled(true);
237 }
238
239 m_lastAnchor = temp.toPoint();
240 m_anchorPoints.push_back(m_lastAnchor);
241 m_lastCursorPos = temp;
243 updateCanvasPixelRect(image()->bounds());
244} // KisToolSelectMagnetic::beginPrimaryAction
void beginPrimaryAction(KoPointerEvent *event) override
QVector< QPoint > m_anchorPoints
int updateInitialAnchorBounds(QPoint pt)
QVector< QPointF > m_points
void checkIfAnchorIsSelected(QPointF pt)
void setButtonsEnabled(bool)
QVector< vQPointF > m_pointCollection
vQPointF computeEdgeWrapper(QPoint a, QPoint b)
#define bounds(x, a, b)
@ PAINT_MODE
Definition kis_tool.h:300

References KisToolSelectBase< BaseClass >::beginPrimaryAction(), KisToolSelectBase< BaseClass >::beginSelectInteraction(), bounds, checkIfAnchorIsSelected(), computeEdgeWrapper(), KisToolSelectBase< BaseClass >::isMovingSelection(), m_anchorPoints, m_complete, m_cursorOnPress, m_lastAnchor, m_lastCursorPos, m_pointCollection, m_points, m_selected, KisTool::PAINT_MODE, reEvaluatePoints(), setButtonsEnabled(), and updateInitialAnchorBounds().

◆ calculateCheckPoints()

void KisToolSelectMagnetic::calculateCheckPoints ( vQPointF points)
private

Definition at line 72 of file KisToolSelectMagnetic.cc.

73{
74 qreal totalDistance = 0.0;
75 int checkPoint = 0;
76 int finalPoint = 2;
77 int midPoint = 1;
78 int minPoint = 0;
79 qreal maxFactor = 2;
80
81 for (; finalPoint < points.count(); finalPoint++) {
82 totalDistance += kisDistance(points[finalPoint], points[finalPoint - 1]);
83
84 if (totalDistance <= m_anchorGap / 3.0) {
85 minPoint = finalPoint;
86 }
87
88 if (totalDistance <= m_anchorGap) {
89 midPoint = finalPoint;
90 }
91
92 if (totalDistance > maxFactor * m_anchorGap) {
93 break;
94 }
95 }
96
97 if (totalDistance > maxFactor * m_anchorGap) {
98 bool foundSomething = false;
99
100 for (int i = midPoint; i < finalPoint; i++) {
101 if (m_worker->intensity(points.at(i).toPoint()) >= m_threshold) {
102 m_lastAnchor = points.at(i).toPoint();
103 m_anchorPoints.push_back(m_lastAnchor);
104
105 vQPointF temp;
106 for (int j = 0; j <= i; j++) {
107 temp.push_back(points[j]);
108 }
109
110 m_pointCollection.push_back(temp);
111 foundSomething = true;
112 checkPoint = i;
113 break;
114 }
115 }
116
117 if (!foundSomething) {
118 for (int i = midPoint - 1; i >= minPoint; i--) {
119 if (m_worker->intensity(points.at(i).toPoint()) >= m_threshold) {
120 m_lastAnchor = points.at(i).toPoint();
121 m_anchorPoints.push_back(m_lastAnchor);
122 vQPointF temp;
123 for (int j = midPoint - 1; j >= i; j--) {
124 temp.push_front(points[j]);
125 }
126
127 m_pointCollection.push_back(temp);
128 foundSomething = true;
129 checkPoint = i;
130 break;
131 }
132 }
133 }
134
135 if (!foundSomething) {
136 m_lastAnchor = points[midPoint].toPoint();
137 m_anchorPoints.push_back(m_lastAnchor);
138 vQPointF temp;
139
140 for (int j = 0; j <= midPoint; j++) {
141 temp.push_back(points[j]);
142 }
143
144 m_pointCollection.push_back(temp);
145 checkPoint = midPoint;
146 foundSomething = true;
147 }
148 }
149
150 totalDistance = 0.0;
152
153 for (; finalPoint < points.count(); finalPoint++) {
154 totalDistance += kisDistance(points[finalPoint], points[checkPoint]);
155 if (totalDistance > maxFactor * m_anchorGap) {
156 points.remove(0, checkPoint + 1);
157 calculateCheckPoints(points);
158 break;
159 }
160 }
161} // KisToolSelectMagnetic::calculateCheckPoints
void calculateCheckPoints(vQPointF points)
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:190

References calculateCheckPoints(), kisDistance(), m_anchorGap, m_anchorPoints, m_lastAnchor, m_pointCollection, m_threshold, m_worker, and reEvaluatePoints().

◆ checkIfAnchorIsSelected()

void KisToolSelectMagnetic::checkIfAnchorIsSelected ( QPointF pt)
private

Definition at line 246 of file KisToolSelectMagnetic.cc.

247{
248 Q_FOREACH (const QPoint pt, m_anchorPoints) {
249 qreal zoomLevel = canvas()->viewConverter()->zoom();
250 int sides = (int) std::ceil(10.0 / zoomLevel);
251 QRect r = QRect(QPoint(0, 0), QSize(sides, sides));
252 r.moveCenter(pt);
253 if (r.contains(temp.toPoint())) {
254 m_selected = true;
255 m_selectedAnchor = m_anchorPoints.lastIndexOf(pt);
256 return;
257 }
258 }
259}

References m_anchorPoints, m_selected, and m_selectedAnchor.

◆ computeEdgeWrapper()

vQPointF KisToolSelectMagnetic::computeEdgeWrapper ( QPoint a,
QPoint b )
private

Definition at line 186 of file KisToolSelectMagnetic.cc.

187{
188 return m_worker->computeEdge(m_searchRadius, a, b, m_filterRadius);
189}

References m_filterRadius, m_searchRadius, and m_worker.

◆ continuePrimaryAction()

void KisToolSelectMagnetic::continuePrimaryAction ( KoPointerEvent * event)
override

◆ createOptionWidget()

QWidget * KisToolSelectMagnetic::createOptionWidget ( )
override

Definition at line 722 of file KisToolSelectMagnetic.cc.

723{
725 KisSelectionOptions *selectionWidget = selectionOptionWidget();
726
727 // Create widgets
729 sliderRadius->setObjectName("radius");
730 sliderRadius->setRange(2.5, 100.0, 2);
731 sliderRadius->setSingleStep(0.5);
732 sliderRadius->setPrefix(
733 i18nc("Filter radius in Magnetic Select Tool settings",
734 "Filter Radius: "));
735
736 KisSliderSpinBox *sliderThreshold = new KisSliderSpinBox;
737 sliderThreshold->setObjectName("threshold");
738 sliderThreshold->setRange(1, 255);
739 sliderThreshold->setSingleStep(10);
740 sliderThreshold->setPrefix(
741 i18nc("Threshold in Magnetic Selection's Tool options", "Threshold: "));
742
743 KisSliderSpinBox *sliderSearchRadius = new KisSliderSpinBox;
744 sliderSearchRadius->setObjectName("frequency");
745 sliderSearchRadius->setRange(20, 200);
746 sliderSearchRadius->setSingleStep(10);
747 sliderSearchRadius->setPrefix(
748 i18nc("Search Radius in Magnetic Selection's Tool options",
749 "Search Radius: "));
750 sliderSearchRadius->setSuffix(" px");
751
752 KisSliderSpinBox *sliderAnchorGap = new KisSliderSpinBox;
753 sliderAnchorGap->setObjectName("anchorgap");
754 sliderAnchorGap->setRange(20, 200);
755 sliderAnchorGap->setSingleStep(10);
756 sliderAnchorGap->setPrefix(
757 i18nc("Anchor Gap in Magnetic Selection's Tool options",
758 "Anchor Gap: "));
759 sliderAnchorGap->setSuffix(" px");
760
761 QPushButton *buttonCompleteSelection =
762 new QPushButton(i18nc("Complete the selection", "Complete"),
763 selectionWidget);
764 buttonCompleteSelection->setEnabled(false);
765
766 QPushButton *buttonDiscardSelection =
767 new QPushButton(i18nc("Discard the selection", "Discard"),
768 selectionWidget);
769 buttonDiscardSelection->setEnabled(false);
770
771 // Set the tooltips
772 sliderRadius->setToolTip(i18nc("@info:tooltip",
773 "Radius of the filter for the detecting "
774 "edges, might take some time to calculate"));
775 sliderThreshold->setToolTip(
776 i18nc("@info:tooltip",
777 "Threshold for determining the minimum intensity of the edges"));
778 sliderSearchRadius->setToolTip(
779 i18nc("@info:tooltip", "Extra area to be searched"));
780 sliderAnchorGap->setToolTip(
781 i18nc("@info:tooltip", "Gap between 2 anchors in interactive mode"));
782 buttonCompleteSelection->setToolTip(
783 i18nc("@info:tooltip", "Complete Selection"));
784 buttonDiscardSelection->setToolTip(
785 i18nc("@info:tooltip", "Discard Selection"));
786
787 // Construct the option widget
788 KisOptionCollectionWidgetWithHeader *sectionPathOptions =
790 i18nc("The 'path options' section label in magnetic selection's "
791 "tool options",
792 "Path options"));
793 sectionPathOptions->appendWidget("sliderRadius", sliderRadius);
794 sectionPathOptions->appendWidget("sliderThreshold", sliderThreshold);
795 sectionPathOptions->appendWidget("sliderSearchRadius", sliderSearchRadius);
796 sectionPathOptions->appendWidget("sliderAnchorGap", sliderAnchorGap);
797 sectionPathOptions->appendWidget("buttonCompleteSelection",
798 buttonCompleteSelection);
799 sectionPathOptions->appendWidget("buttonDiscardSelection",
800 buttonDiscardSelection);
801 selectionWidget->appendWidget("sectionPathOptions", sectionPathOptions);
802
803 // Load configuration settings into tool options
804 m_filterRadius = m_configGroup.readEntry("filterradius", 3.0);
805 m_threshold = m_configGroup.readEntry("threshold", 100);
806 m_searchRadius = m_configGroup.readEntry("searchradius", 30);
807 m_anchorGap = m_configGroup.readEntry("anchorgap", 20);
808
809 sliderRadius->setValue(m_filterRadius);
810 sliderThreshold->setValue(m_threshold);
811 sliderSearchRadius->setValue(m_searchRadius);
812 sliderAnchorGap->setValue(m_anchorGap);
813
814 // Make connections
815 connect(sliderRadius,
816 SIGNAL(valueChanged(qreal)),
817 this,
818 SLOT(slotSetFilterRadius(qreal)));
819 connect(sliderThreshold,
820 SIGNAL(valueChanged(int)),
821 this,
822 SLOT(slotSetThreshold(int)));
823 connect(sliderSearchRadius,
824 SIGNAL(valueChanged(int)),
825 this,
826 SLOT(slotSetSearchRadius(int)));
827 connect(sliderAnchorGap,
828 SIGNAL(valueChanged(int)),
829 this,
830 SLOT(slotSetAnchorGap(int)));
831 connect(buttonCompleteSelection,
832 SIGNAL(clicked()),
833 this,
834 SLOT(requestStrokeEnd()));
835 connect(this,
836 SIGNAL(setButtonsEnabled(bool)),
837 buttonCompleteSelection,
838 SLOT(setEnabled(bool)));
839 connect(buttonDiscardSelection,
840 SIGNAL(clicked()),
841 this,
843 connect(this,
844 SIGNAL(setButtonsEnabled(bool)),
845 buttonDiscardSelection,
846 SLOT(setEnabled(bool)));
847
848 return selectionWidget;
849
850} // KisToolSelectMagnetic::createOptionWidget
This class is a spinbox in which you can click and drag to set the value. A slider like bar is displa...
void setValue(qreal newValue)
void setRange(qreal newMinimum, qreal newMaximum, int newNumberOfDecimals=0, bool computeNewFastSliderStep=true)
Set the minimum and the maximum values of the range.
Wrapper class around a KisOptionCollectionWidget that also provide a header with a title label and an...
void appendWidget(const QString &id, QWidget *widget)
Insert the given widget with the given id at the end of the list. The list widget takes ownership of ...
void appendWidget(const QString &id, QWidget *widget)
Insert the given widget with the given id at the end of the list. The list widget takes ownership of ...
This class is a spinbox in which you can click and drag to set the value. A slider like bar is displa...
void setValue(int newValue)
void setRange(int newMinimum, int newMaximum, bool computeNewFastSliderStep=true)
Set the minimum and the maximum values of the range, computing a new "fast slider step" based on the ...
KisSelectionOptions * selectionOptionWidget()
QWidget * createOptionWidget() override
void requestStrokeCancellation() override

References KisOptionCollectionWidget::appendWidget(), KisOptionCollectionWidgetWithHeader::appendWidget(), connect(), KisToolSelectBase< BaseClass >::createOptionWidget(), m_anchorGap, m_configGroup, m_filterRadius, m_searchRadius, m_threshold, requestStrokeCancellation(), requestStrokeEnd(), KisToolSelectBase< BaseClass >::selectionOptionWidget(), setButtonsEnabled(), KisSliderSpinBox::setRange(), KisDoubleSliderSpinBox::setRange(), KisSliderSpinBox::setValue(), KisDoubleSliderSpinBox::setValue(), slotSetAnchorGap(), slotSetFilterRadius(), slotSetSearchRadius(), and slotSetThreshold().

◆ deactivate

void KisToolSelectMagnetic::deactivate ( )
overrideslot

Definition at line 679 of file KisToolSelectMagnetic.cc.

680{
681 KisCanvas2 *kisCanvas = dynamic_cast<KisCanvas2 *>(canvas());
682 KIS_ASSERT_RECOVER_RETURN(kisCanvas);
683 kisCanvas->updateCanvas();
685 m_continuedMode = false;
686 disconnect(action("undo_polygon_selection"), nullptr, this, nullptr);
687
689}
void updateCanvas(const QRectF &rc) override
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
void deactivate() override
Definition kis_tool.cc:131

References KisTool::deactivate(), KIS_ASSERT_RECOVER_RETURN, m_continuedMode, resetVariables(), and KisCanvas2::updateCanvas().

◆ deleteSelectedAnchor()

void KisToolSelectMagnetic::deleteSelectedAnchor ( )
private

Definition at line 378 of file KisToolSelectMagnetic.cc.

379{
380 if (m_anchorPoints.isEmpty())
381 return;
382
383 if (m_anchorPoints.size() <= 1) {
385
386 } else if (m_selectedAnchor == 0) { // if it is the initial anchor
387 m_anchorPoints.pop_front();
388 m_pointCollection.pop_front();
389
390 if (m_complete) {
392 }
393
394 } else if (m_selectedAnchor == m_anchorPoints.count() - 1) { // if it is the last anchor
395 m_anchorPoints.pop_back();
396 m_pointCollection.pop_back();
397
398 if (m_complete) {
400 }
401
402 } else { // it is in the middle
408 }
409
410 if (m_complete && m_anchorPoints.size() < 3) {
411 m_complete = false;
412 m_pointCollection.pop_back();
413 }
414
416
417} // KisToolSelectMagnetic::deleteSelectedAnchor

References computeEdgeWrapper(), m_anchorPoints, m_complete, m_pointCollection, m_selectedAnchor, reEvaluatePoints(), and resetVariables().

◆ drawAnchors()

void KisToolSelectMagnetic::drawAnchors ( QPainter & gc)
private

Definition at line 630 of file KisToolSelectMagnetic.cc.

631{
632 int sides = updateInitialAnchorBounds(m_anchorPoints.first());
633 Q_FOREACH (const QPoint pt, m_anchorPoints) {
634 KisHandlePainterHelper helper(&gc, handleRadius(), decorationThickness());
635 QRect r(QPoint(0, 0), QSize(sides, sides));
636 r.moveCenter(pt);
637 if (r.contains(m_lastCursorPos.toPoint())) {
638 helper.setHandleStyle(KisHandleStyle::highlightedPrimaryHandles());
639 } else {
640 helper.setHandleStyle(KisHandleStyle::primarySelection());
641 }
642 helper.drawHandleRect(pixelToView(pt), 4, QPoint(0, 0));
643 }
644}
The KisHandlePainterHelper class is a special helper for painting handles around objects....
static KisHandleStyle & highlightedPrimaryHandles()
static KisHandleStyle & primarySelection()

References KisHandlePainterHelper::drawHandleRect(), KisHandleStyle::highlightedPrimaryHandles(), m_anchorPoints, m_lastCursorPos, KisHandleStyle::primarySelection(), KisHandlePainterHelper::setHandleStyle(), and updateInitialAnchorBounds().

◆ endPrimaryAction()

void KisToolSelectMagnetic::endPrimaryAction ( KoPointerEvent * event)
override

Definition at line 340 of file KisToolSelectMagnetic.cc.

341{
342 if (isMovingSelection()) {
344 return;
345 }
346
347 if (m_selected && convertToPixelCoord(event) != m_cursorOnPress) {
348 if (!image()->bounds().contains(m_anchorPoints[m_selectedAnchor])) {
350 } else {
352 }
353 } else if (m_selected) {
354 QPointF temp(convertToPixelCoord(event));
355
356 if (!image()->bounds().contains(temp.toPoint())) {
357 return;
358 }
359
360 if (m_snapBound.contains(temp) && m_anchorPoints.count() > 1) {
361 if(m_complete){
363 return;
364 }
365 vQPointF edge = computeEdgeWrapper(m_anchorPoints.last(), temp.toPoint());
366 m_points.append(edge);
367 m_pointCollection.push_back(edge);
368 m_complete = true;
369 }
370 }
374 }
375 m_selected = false;
376} // KisToolSelectMagnetic::endPrimaryAction
void endPrimaryAction(KoPointerEvent *event) override

References bounds, computeEdgeWrapper(), deleteSelectedAnchor(), KisToolSelectBase< BaseClass >::endPrimaryAction(), finishSelectionAction(), KisSignalCompressor::isActive(), KisToolSelectBase< BaseClass >::isMovingSelection(), m_anchorPoints, m_complete, m_cursorOnPress, m_mouseHoverCompressor, m_pointCollection, m_points, m_selected, m_selectedAnchor, m_snapBound, slotCalculateEdge(), KisSignalCompressor::stop(), and updateSelectedAnchor().

◆ finishSelectionAction()

void KisToolSelectMagnetic::finishSelectionAction ( )
private

Definition at line 473 of file KisToolSelectMagnetic.cc.

474{
475 KisCanvas2 *kisCanvas = dynamic_cast<KisCanvas2 *>(canvas());
476 KIS_ASSERT_RECOVER_RETURN(kisCanvas);
477 kisCanvas->updateCanvas();
478 setMode(KisTool::HOVER_MODE);
479 m_complete = false;
480 m_finished = true;
481
482 // just for testing out
483 // m_worker.saveTheImage(m_points);
484
485 QRectF boundingViewRect =
487
488 KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Magnetic Selection"));
489
490 if (m_points.count() > 2 &&
491 !helper.tryDeselectCurrentSelection(boundingViewRect, selectionAction()))
492 {
493 KisCursorOverrideLock cursorLock(KisCursor::waitCursor());
494
495 const SelectionMode mode =
496 helper.tryOverrideSelectionMode(kisCanvas->viewManager()->selection(),
499 if (mode == PIXEL_SELECTION) {
500 KisProcessingApplicator applicator(
501 currentImage(),
502 currentNode(),
505 kundo2_i18n("Magnetic Selection"));
506
507 KisPixelSelectionSP tmpSel =
508 new KisPixelSelection(new KisDefaultBounds(currentImage()));
509
510 const bool antiAlias = antiAliasSelection();
511 const int grow = growSelection();
512 const int feather = featherSelection();
513
514 QPainterPath path;
515 path.addPolygon(m_points);
516 path.closeSubpath();
517
519 [tmpSel, antiAlias, grow, feather, path]() mutable
520 -> KUndo2Command * {
521 KisPainter painter(tmpSel);
522 painter.setPaintColor(
523 KoColor(Qt::black, tmpSel->colorSpace()));
524 // Since the feathering already smooths the selection, the
525 // antiAlias is not applied if we must feather
526 painter.setAntiAliasPolygonFill(antiAlias && feather == 0);
527 painter.setFillStyle(KisPainter::FillStyleForegroundColor);
528 painter.setStrokeStyle(KisPainter::StrokeStyleNone);
529
530 painter.paintPainterPath(path);
531
532 if (grow > 0) {
533 KisGrowSelectionFilter biggy(grow, grow);
534 biggy.process(tmpSel,
535 tmpSel->selectedRect().adjusted(-grow,
536 -grow,
537 grow,
538 grow));
539 } else if (grow < 0) {
540 KisShrinkSelectionFilter tiny(-grow, -grow, false);
541 tiny.process(tmpSel, tmpSel->selectedRect());
542 }
543 if (feather > 0) {
544 KisFeatherSelectionFilter feathery(feather);
545 feathery.process(
546 tmpSel,
547 tmpSel->selectedRect().adjusted(-feather,
548 -feather,
549 feather,
550 feather));
551 }
552
553 if (grow == 0 && feather == 0) {
554 tmpSel->setOutlineCache(path);
555 } else {
556 tmpSel->invalidateOutlineCache();
557 }
558
559 return 0;
560 });
561
562 applicator.applyCommand(cmd, KisStrokeJobData::SEQUENTIAL);
563 helper.selectPixelSelection(applicator, tmpSel, selectionAction());
564 applicator.end();
565
566 } else {
567 KoPathShape *path = new KoPathShape();
568 path->setShapeId(KoPathShapeId);
569
570 QTransform resolutionMatrix;
571 resolutionMatrix.scale(1 / currentImage()->xRes(), 1 / currentImage()->yRes());
572 path->moveTo(resolutionMatrix.map(m_points[0]));
573 for (int i = 1; i < m_points.count(); i++)
574 path->lineTo(resolutionMatrix.map(m_points[i]));
575 path->close();
576 path->normalize();
577 helper.addSelectionShape(path, selectionAction());
578 }
579 }
580
582
584} // KisToolSelectMagnetic::finishSelectionAction
QVector< KisImageSignalType > KisImageSignalVector
SelectionMode
@ PIXEL_SELECTION
#define KoPathShapeId
Definition KoPathShape.h:20
KisViewManager * viewManager() const
static QCursor waitCursor()
Definition kis_cursor.cc:54
const KoColorSpace * colorSpace() const
@ FillStyleForegroundColor
SelectionAction selectionAction() const
SelectionMode selectionMode() const
bool antiAliasSelection() const
KisSelectionSP selection()
The position of a path point within a path shape.
Definition KoPathShape.h:63
KUndo2MagicString kundo2_i18n(const char *text)
void accumulateBounds(const Point &pt, Rect *bounds)
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...
void setOutlineCache(const QPainterPath &cache)
@ HOVER_MODE
Definition kis_tool.h:299

References KisAlgebra2D::accumulateBounds(), KisSelectionToolHelper::addSelectionShape(), KisToolSelectBase< BaseClass >::antiAliasSelection(), KisProcessingApplicator::applyCommand(), KisPaintDevice::colorSpace(), KisProcessingApplicator::end(), KisToolSelectBase< BaseClass >::endSelectInteraction(), KisToolSelectBase< BaseClass >::featherSelection(), KisPainter::FillStyleForegroundColor, KisToolSelectBase< BaseClass >::growSelection(), KisTool::HOVER_MODE, KisPixelSelection::invalidateOutlineCache(), KIS_ASSERT_RECOVER_RETURN, KoPathShapeId, kundo2_i18n(), m_complete, m_finished, m_points, KisProcessingApplicator::NONE, KisPainter::paintPainterPath(), PIXEL_SELECTION, KisFeatherSelectionFilter::process(), KisGrowSelectionFilter::process(), KisShrinkSelectionFilter::process(), resetVariables(), KisPixelSelection::selectedRect(), KisViewManager::selection(), KisToolSelectBase< BaseClass >::selectionAction(), KisToolSelectBase< BaseClass >::selectionMode(), KisSelectionToolHelper::selectPixelSelection(), KisStrokeJobData::SEQUENTIAL, KisPainter::setAntiAliasPolygonFill(), KisPainter::setFillStyle(), KisPixelSelection::setOutlineCache(), KisPainter::setPaintColor(), KisPainter::setStrokeStyle(), KisPainter::StrokeStyleNone, KisSelectionToolHelper::tryDeselectCurrentSelection(), KisSelectionToolHelper::tryOverrideSelectionMode(), KisCanvas2::updateCanvas(), KisCanvas2::viewManager(), and KisCursor::waitCursor().

◆ keyPressEvent()

void KisToolSelectMagnetic::keyPressEvent ( QKeyEvent * event)
override

Definition at line 56 of file KisToolSelectMagnetic.cc.

57{
58 if (isSelecting()) {
59 if (event->key() == Qt::Key_Control) {
60 m_continuedMode = true;
61 }
62 }
64}
void keyPressEvent(QKeyEvent *event) override

References KisToolSelectBase< BaseClass >::isSelecting(), KisToolSelectBase< BaseClass >::keyPressEvent(), and m_continuedMode.

◆ keyReleaseEvent()

void KisToolSelectMagnetic::keyReleaseEvent ( QKeyEvent * event)
override

Definition at line 163 of file KisToolSelectMagnetic.cc.

164{
165 if (isSelecting()) {
166 if (event->key() == Qt::Key_Control ||
167 !(event->modifiers() & Qt::ControlModifier)) {
168
169 m_continuedMode = false;
170 if (mode() != PAINT_MODE) {
171 // Prevent finishing the selection if there is only one point, since
172 // finishSelectionAction will deselect the current selection. That
173 // is fine if the user just clicks, but not if we are in continued
174 // mode
175 if (m_points.count() > 1) {
177 }
178 m_points.clear(); // ensure points are always cleared
179 }
180 }
181 }
182
184}
void keyReleaseEvent(QKeyEvent *event) override

References finishSelectionAction(), KisToolSelectBase< BaseClass >::isSelecting(), KisToolSelectBase< BaseClass >::keyReleaseEvent(), m_continuedMode, and m_points.

◆ mouseMoveEvent()

void KisToolSelectMagnetic::mouseMoveEvent ( KoPointerEvent * event)
override

Definition at line 192 of file KisToolSelectMagnetic.cc.

193{
194 if (isMovingSelection()) {
196 return;
197 }
198
199 m_lastCursorPos = convertToPixelCoord(event);
200 if (isSelecting()) {
202 }
204} // KisToolSelectMagnetic::mouseMoveEvent
void mouseMoveEvent(KoPointerEvent *event) override

References KisToolSelectBase< BaseClass >::isMovingSelection(), KisToolSelectBase< BaseClass >::isSelecting(), m_lastCursorPos, KisToolSelectBase< BaseClass >::mouseMoveEvent(), and updatePaintPath().

◆ paint()

void KisToolSelectMagnetic::paint ( QPainter & gc,
const KoViewConverter & converter )
override

Definition at line 614 of file KisToolSelectMagnetic.cc.

615{
616 Q_UNUSED(converter);
618 if ((mode() == KisTool::PAINT_MODE || m_continuedMode) &&
619 !m_anchorPoints.isEmpty())
620 {
621 QPainterPath outline = m_paintPath;
622 if (m_continuedMode && mode() != KisTool::PAINT_MODE) {
623 outline.lineTo(pixelToView(m_lastCursorPos));
624 }
625 paintToolOutline(&gc, outline);
626 drawAnchors(gc);
627 }
628}

References drawAnchors(), m_anchorPoints, m_continuedMode, m_lastCursorPos, m_paintPath, KisTool::PAINT_MODE, and updatePaintPath().

◆ reEvaluatePoints()

void KisToolSelectMagnetic::reEvaluatePoints ( )
private

Definition at line 463 of file KisToolSelectMagnetic.cc.

464{
465 m_points.clear();
466 Q_FOREACH (const vQPointF vec, m_pointCollection) {
467 m_points.append(vec);
468 }
469
471}

References m_pointCollection, m_points, and updatePaintPath().

◆ requestStrokeCancellation()

void KisToolSelectMagnetic::requestStrokeCancellation ( )
override

Definition at line 714 of file KisToolSelectMagnetic.cc.

715{
716 m_complete = false;
717 m_finished = false;
718 setButtonsEnabled(false);
720}

References m_complete, m_finished, resetVariables(), and setButtonsEnabled().

◆ requestStrokeEnd()

void KisToolSelectMagnetic::requestStrokeEnd ( )
override

Definition at line 705 of file KisToolSelectMagnetic.cc.

706{
707 if (m_finished || m_anchorPoints.count() < 2) return;
708
709 setButtonsEnabled(false);
711 m_finished = false;
712}

References finishSelectionAction(), m_anchorPoints, m_finished, and setButtonsEnabled().

◆ resetCursorStyle()

void KisToolSelectMagnetic::resetCursorStyle ( )
override

Definition at line 876 of file KisToolSelectMagnetic.cc.

877{
879 useCursor(KisCursor::load("tool_magnetic_selection_cursor_add.png", 6, 6));
880 } else if (selectionAction() == SELECTION_SUBTRACT) {
881 useCursor(KisCursor::load("tool_magnetic_selection_cursor_sub.png", 6, 6));
882 } else if (selectionAction() == SELECTION_INTERSECT) {
883 useCursor(KisCursor::load("tool_magnetic_selection_cursor_inter.png", 6, 6));
885 useCursor(KisCursor::load("tool_magnetic_selection_cursor_symdiff.png", 6, 6));
886 } else {
887 KisToolSelect::resetCursorStyle();
888 }
889}
@ SELECTION_INTERSECT
@ SELECTION_SYMMETRICDIFFERENCE
@ SELECTION_SUBTRACT
@ SELECTION_ADD

References KisCursor::load(), SELECTION_ADD, SELECTION_INTERSECT, SELECTION_SUBTRACT, SELECTION_SYMMETRICDIFFERENCE, and KisToolSelectBase< BaseClass >::selectionAction().

◆ resetVariables()

void KisToolSelectMagnetic::resetVariables ( )
private

Definition at line 586 of file KisToolSelectMagnetic.cc.

587{
588 m_points.clear();
589 m_anchorPoints.clear();
590 m_pointCollection.clear();
591 m_paintPath = QPainterPath();
592 m_complete = false;
593}

References m_anchorPoints, m_complete, m_paintPath, m_pointCollection, and m_points.

◆ setButtonsEnabled

void KisToolSelectMagnetic::setButtonsEnabled ( bool )
signal

◆ slotCalculateEdge

void KisToolSelectMagnetic::slotCalculateEdge ( )
slot

Definition at line 326 of file KisToolSelectMagnetic.cc.

327{
328 QPoint current = m_lastCursorPos.toPoint();
329 if (!image()->bounds().contains(current))
330 return;
331
332 if(kisDistance(m_lastAnchor, current) < m_anchorGap)
333 return;
334
335 vQPointF pointSet = computeEdgeWrapper(m_lastAnchor, current);
336 calculateCheckPoints(pointSet);
337}

References bounds, calculateCheckPoints(), computeEdgeWrapper(), kisDistance(), m_anchorGap, m_lastAnchor, and m_lastCursorPos.

◆ slotSetAnchorGap

void KisToolSelectMagnetic::slotSetAnchorGap ( int g)
slot

Definition at line 870 of file KisToolSelectMagnetic.cc.

871{
872 m_anchorGap = g;
873 m_configGroup.writeEntry("anchorgap", g);
874}

References m_anchorGap, and m_configGroup.

◆ slotSetFilterRadius

void KisToolSelectMagnetic::slotSetFilterRadius ( qreal r)
slot

Definition at line 852 of file KisToolSelectMagnetic.cc.

853{
855 m_configGroup.writeEntry("filterradius", r);
856}

References m_configGroup, and m_filterRadius.

◆ slotSetSearchRadius

void KisToolSelectMagnetic::slotSetSearchRadius ( int r)
slot

Definition at line 864 of file KisToolSelectMagnetic.cc.

865{
867 m_configGroup.writeEntry("searchradius", r);
868}

References m_configGroup, and m_searchRadius.

◆ slotSetThreshold

void KisToolSelectMagnetic::slotSetThreshold ( int t)
slot

Definition at line 858 of file KisToolSelectMagnetic.cc.

859{
860 m_threshold = t;
861 m_configGroup.writeEntry("threshold", t);
862}

References m_configGroup, and m_threshold.

◆ undoPoints

void KisToolSelectMagnetic::undoPoints ( )
slot

Definition at line 691 of file KisToolSelectMagnetic.cc.

692{
693 if (m_complete) return;
694
695 if(m_anchorPoints.count() <= 1){
697 return;
698 }
699
700 m_anchorPoints.pop_back();
701 m_pointCollection.pop_back();
703}

References m_anchorPoints, m_complete, m_pointCollection, reEvaluatePoints(), and resetVariables().

◆ updateCanvas()

void KisToolSelectMagnetic::updateCanvas ( )
private

◆ updateContinuedMode()

void KisToolSelectMagnetic::updateContinuedMode ( )
private

Definition at line 658 of file KisToolSelectMagnetic.cc.

659{
660 if (!m_points.isEmpty()) {
661 qint32 lastPointIndex = m_points.count() - 1;
662
663 QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_lastCursorPos).normalized();
664 updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH);
665
666 updateCanvasPixelRect(updateRect);
667 }
668}
#define FEEDBACK_LINE_WIDTH
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186

References FEEDBACK_LINE_WIDTH, kisGrowRect(), m_lastCursorPos, and m_points.

◆ updateFeedback()

void KisToolSelectMagnetic::updateFeedback ( )
private

Definition at line 646 of file KisToolSelectMagnetic.cc.

647{
648 if (m_points.count() > 1) {
649 qint32 lastPointIndex = m_points.count() - 1;
650
651 QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_points[lastPointIndex]).normalized();
652 updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH);
653
654 updateCanvasPixelRect(updateRect);
655 }
656}

References FEEDBACK_LINE_WIDTH, kisGrowRect(), and m_points.

◆ updateInitialAnchorBounds()

int KisToolSelectMagnetic::updateInitialAnchorBounds ( QPoint pt)
private

Definition at line 454 of file KisToolSelectMagnetic.cc.

455{
456 qreal zoomLevel = canvas()->viewConverter()->zoom();
457 int sides = (int) std::ceil(10.0 / zoomLevel);
458 m_snapBound = QRectF(QPoint(0, 0), QSize(sides, sides));
459 m_snapBound.moveCenter(pt);
460 return sides;
461}

References m_snapBound.

◆ updatePaintPath()

void KisToolSelectMagnetic::updatePaintPath ( )
private

Definition at line 595 of file KisToolSelectMagnetic.cc.

596{
597 m_paintPath = QPainterPath();
598 if (m_points.size() > 0) {
599 m_paintPath.moveTo(pixelToView(m_points[0]));
600 }
601 for (int i = 1; i < m_points.count(); i++) {
602 m_paintPath.lineTo(pixelToView(m_points[i]));
603 }
604
606
607 if (m_continuedMode && mode() != PAINT_MODE) {
609 }
610
611 updateCanvasPixelRect(image()->bounds());
612}

References bounds, m_continuedMode, m_paintPath, m_points, updateContinuedMode(), and updateFeedback().

◆ updateSelectedAnchor()

void KisToolSelectMagnetic::updateSelectedAnchor ( )
private

Member Data Documentation

◆ m_anchorGap

int KisToolSelectMagnetic::m_anchorGap {30}
private

Definition at line 88 of file KisToolSelectMagnetic.h.

88{30};

◆ m_anchorPoints

QVector<QPoint> KisToolSelectMagnetic::m_anchorPoints
private

Definition at line 77 of file KisToolSelectMagnetic.h.

◆ m_complete

bool KisToolSelectMagnetic::m_complete {false}
private

Definition at line 81 of file KisToolSelectMagnetic.h.

81{false};

◆ m_configGroup

KConfigGroup KisToolSelectMagnetic::m_configGroup
private

Definition at line 91 of file KisToolSelectMagnetic.h.

◆ m_continuedMode

bool KisToolSelectMagnetic::m_continuedMode {false}
private

Definition at line 78 of file KisToolSelectMagnetic.h.

78{false};

◆ m_cursorOnPress

QPointF KisToolSelectMagnetic::m_cursorOnPress
private

Definition at line 79 of file KisToolSelectMagnetic.h.

◆ m_filterRadius

qreal KisToolSelectMagnetic::m_filterRadius {3.0}
private

Definition at line 89 of file KisToolSelectMagnetic.h.

89{3.0};

◆ m_finished

bool KisToolSelectMagnetic::m_finished {false}
private

Definition at line 83 of file KisToolSelectMagnetic.h.

83{false};

◆ m_lastAnchor

QPoint KisToolSelectMagnetic::m_lastAnchor
private

Definition at line 80 of file KisToolSelectMagnetic.h.

◆ m_lastCursorPos

QPointF KisToolSelectMagnetic::m_lastCursorPos
private

Definition at line 79 of file KisToolSelectMagnetic.h.

◆ m_mouseHoverCompressor

KisSignalCompressor KisToolSelectMagnetic::m_mouseHoverCompressor
private

Definition at line 93 of file KisToolSelectMagnetic.h.

◆ m_paintPath

QPainterPath KisToolSelectMagnetic::m_paintPath
private

Definition at line 75 of file KisToolSelectMagnetic.h.

◆ m_pointCollection

QVector<vQPointF> KisToolSelectMagnetic::m_pointCollection
private

Definition at line 92 of file KisToolSelectMagnetic.h.

◆ m_points

QVector<QPointF> KisToolSelectMagnetic::m_points
private

Definition at line 76 of file KisToolSelectMagnetic.h.

◆ m_searchRadius

int KisToolSelectMagnetic::m_searchRadius {30}
private

Definition at line 86 of file KisToolSelectMagnetic.h.

86{30};

◆ m_selected

bool KisToolSelectMagnetic::m_selected {false}
private

Definition at line 82 of file KisToolSelectMagnetic.h.

82{false};

◆ m_selectedAnchor

int KisToolSelectMagnetic::m_selectedAnchor {0}
private

Definition at line 87 of file KisToolSelectMagnetic.h.

87{0};

◆ m_snapBound

QRectF KisToolSelectMagnetic::m_snapBound
private

Definition at line 90 of file KisToolSelectMagnetic.h.

◆ m_threshold

int KisToolSelectMagnetic::m_threshold {70}
private

Definition at line 85 of file KisToolSelectMagnetic.h.

85{70};

◆ m_widgetHelper

KisSelectionToolConfigWidgetHelper KisToolSelectBase< BaseClass >::m_widgetHelper
protected

Definition at line 535 of file kis_tool_select_base.h.

◆ m_worker

QScopedPointer<KisMagneticWorker> KisToolSelectMagnetic::m_worker
private

Definition at line 84 of file KisToolSelectMagnetic.h.


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