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 beginMoveContentInteraction ()
 
bool beginMoveSelectionInteraction ()
 
void beginPrimaryAction (KoPointerEvent *event) override
 
bool beginSelectInteraction ()
 
bool canBeginNewAction (KoPointerEvent *event, const QPointF &pos, CursorHit hit)
 
void cancelMoveSelectionStroke ()
 
CursorHit checkCursorHit (const QPointF &pos, Qt::KeyboardModifiers modifiers) const
 
QList< int > colorLabelsSelected () const
 
void commitMoveSelectionStroke ()
 
void commitMoveSelectionStrokeImpl (bool cancel)
 
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 endMoveContentInteraction ()
 
bool endMoveSelectionInteraction ()
 
void endPrimaryAction (KoPointerEvent *event) override
 
bool endSelectInteraction ()
 
void explicitUserStrokeEndRequest () override
 
int featherSelection () const
 
int growSelection () const
 
void initializeStrokeAttributes (const QPointF &pos, KisStrokeStrategy *strategy, bool moved)
 
bool isMovingContent () 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
 
bool moveSelectedContent () const
 
QMenu * popupActionsMenu () override
 
KisPopupWidgetInterfacepopupWidget () override
 
void requestStrokeCancellation () 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 updateCursor ()
 
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  CursorHit { CursorHit_None , CursorHit_Border , CursorHit_Inside , CursorHit_Outside }
 
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 49 of file KisToolSelectMagnetic.cc.

50 : KisToolSelect(canvas,
51 KisCursor::loadWithSize("tool_magnetic_selection_cursor.svg", 32, 32, 6, 6),
52 i18n("Magnetic Selection"))
53 , m_worker(nullptr)
55{ }
static QCursor loadWithSize(const QString &cursorName, int width, int height, 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 672 of file KisToolSelectMagnetic.cc.

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

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

◆ beginPrimaryAction()

void KisToolSelectMagnetic::beginPrimaryAction ( KoPointerEvent * event)
override

Definition at line 208 of file KisToolSelectMagnetic.cc.

209{
211 if (isMovingSelection()) {
212 return;
213 }
214
215 setMode(KisTool::PAINT_MODE);
216 QPointF temp(convertToPixelCoord(event));
217
218 if (!image()->bounds().contains(temp.toPoint())) {
219 return;
220 }
221
222 m_cursorOnPress = temp;
223
225
226 if (m_complete || m_selected) {
227 return;
228 }
229
230 if (m_anchorPoints.count() != 0) {
231 vQPointF edge = computeEdgeWrapper(m_anchorPoints.last(), temp.toPoint());
232 m_points.append(edge);
233 m_pointCollection.push_back(edge);
234 } else {
236 updateInitialAnchorBounds(temp.toPoint());
237 Q_EMIT setButtonsEnabled(true);
238 }
239
240 m_lastAnchor = temp.toPoint();
241 m_anchorPoints.push_back(m_lastAnchor);
242 m_lastCursorPos = temp;
244 updateCanvasPixelRect(image()->bounds());
245} // 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 73 of file KisToolSelectMagnetic.cc.

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

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

References m_anchorPoints, m_selected, and m_selectedAnchor.

◆ computeEdgeWrapper()

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

Definition at line 187 of file KisToolSelectMagnetic.cc.

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

References m_filterRadius, m_searchRadius, and m_worker.

◆ continuePrimaryAction()

void KisToolSelectMagnetic::continuePrimaryAction ( KoPointerEvent * event)
override

◆ createOptionWidget()

QWidget * KisToolSelectMagnetic::createOptionWidget ( )
override

Definition at line 724 of file KisToolSelectMagnetic.cc.

725{
727 KisSelectionOptions *selectionWidget = selectionOptionWidget();
728
729 // Create widgets
731 sliderRadius->setObjectName("radius");
732 sliderRadius->setRange(2.5, 100.0, 2);
733 sliderRadius->setSingleStep(0.5);
734 sliderRadius->setPrefix(
735 i18nc("Filter radius in Magnetic Select Tool settings",
736 "Filter Radius: "));
737
738 KisSliderSpinBox *sliderThreshold = new KisSliderSpinBox;
739 sliderThreshold->setObjectName("threshold");
740 sliderThreshold->setRange(1, 255);
741 sliderThreshold->setSingleStep(10);
742 sliderThreshold->setPrefix(
743 i18nc("Threshold in Magnetic Selection's Tool options", "Threshold: "));
744
745 KisSliderSpinBox *sliderSearchRadius = new KisSliderSpinBox;
746 sliderSearchRadius->setObjectName("frequency");
747 sliderSearchRadius->setRange(20, 200);
748 sliderSearchRadius->setSingleStep(10);
749 sliderSearchRadius->setPrefix(
750 i18nc("Search Radius in Magnetic Selection's Tool options",
751 "Search Radius: "));
752 sliderSearchRadius->setSuffix(" px");
753
754 KisSliderSpinBox *sliderAnchorGap = new KisSliderSpinBox;
755 sliderAnchorGap->setObjectName("anchorgap");
756 sliderAnchorGap->setRange(20, 200);
757 sliderAnchorGap->setSingleStep(10);
758 sliderAnchorGap->setPrefix(
759 i18nc("Anchor Gap in Magnetic Selection's Tool options",
760 "Anchor Gap: "));
761 sliderAnchorGap->setSuffix(" px");
762
763 QPushButton *buttonCompleteSelection =
764 new QPushButton(i18nc("Complete the selection", "Complete"),
765 selectionWidget);
766 buttonCompleteSelection->setEnabled(false);
767
768 QPushButton *buttonDiscardSelection =
769 new QPushButton(i18nc("Discard the selection", "Discard"),
770 selectionWidget);
771 buttonDiscardSelection->setEnabled(false);
772
773 // Set the tooltips
774 sliderRadius->setToolTip(i18nc("@info:tooltip",
775 "Radius of the filter for the detecting "
776 "edges, might take some time to calculate"));
777 sliderThreshold->setToolTip(
778 i18nc("@info:tooltip",
779 "Threshold for determining the minimum intensity of the edges"));
780 sliderSearchRadius->setToolTip(
781 i18nc("@info:tooltip", "Extra area to be searched"));
782 sliderAnchorGap->setToolTip(
783 i18nc("@info:tooltip", "Gap between 2 anchors in interactive mode"));
784 buttonCompleteSelection->setToolTip(
785 i18nc("@info:tooltip", "Complete Selection"));
786 buttonDiscardSelection->setToolTip(
787 i18nc("@info:tooltip", "Discard Selection"));
788
789 // Construct the option widget
790 KisOptionCollectionWidgetWithHeader *sectionPathOptions =
792 i18nc("The 'path options' section label in magnetic selection's "
793 "tool options",
794 "Path options"));
795 sectionPathOptions->appendWidget("sliderRadius", sliderRadius);
796 sectionPathOptions->appendWidget("sliderThreshold", sliderThreshold);
797 sectionPathOptions->appendWidget("sliderSearchRadius", sliderSearchRadius);
798 sectionPathOptions->appendWidget("sliderAnchorGap", sliderAnchorGap);
799 sectionPathOptions->appendWidget("buttonCompleteSelection",
800 buttonCompleteSelection);
801 sectionPathOptions->appendWidget("buttonDiscardSelection",
802 buttonDiscardSelection);
803 selectionWidget->appendWidget("sectionPathOptions", sectionPathOptions);
804
805 // Load configuration settings into tool options
806 m_filterRadius = m_configGroup.readEntry("filterradius", 3.0);
807 m_threshold = m_configGroup.readEntry("threshold", 100);
808 m_searchRadius = m_configGroup.readEntry("searchradius", 30);
809 m_anchorGap = m_configGroup.readEntry("anchorgap", 20);
810
811 sliderRadius->setValue(m_filterRadius);
812 sliderThreshold->setValue(m_threshold);
813 sliderSearchRadius->setValue(m_searchRadius);
814 sliderAnchorGap->setValue(m_anchorGap);
815
816 // Make connections
817 connect(sliderRadius,
818 SIGNAL(valueChanged(qreal)),
819 this,
820 SLOT(slotSetFilterRadius(qreal)));
821 connect(sliderThreshold,
822 SIGNAL(valueChanged(int)),
823 this,
824 SLOT(slotSetThreshold(int)));
825 connect(sliderSearchRadius,
826 SIGNAL(valueChanged(int)),
827 this,
828 SLOT(slotSetSearchRadius(int)));
829 connect(sliderAnchorGap,
830 SIGNAL(valueChanged(int)),
831 this,
832 SLOT(slotSetAnchorGap(int)));
833 connect(buttonCompleteSelection,
834 SIGNAL(clicked()),
835 this,
836 SLOT(requestStrokeEnd()));
837 connect(this,
838 SIGNAL(setButtonsEnabled(bool)),
839 buttonCompleteSelection,
840 SLOT(setEnabled(bool)));
841 connect(buttonDiscardSelection,
842 SIGNAL(clicked()),
843 this,
845 connect(this,
846 SIGNAL(setButtonsEnabled(bool)),
847 buttonDiscardSelection,
848 SLOT(setEnabled(bool)));
849
850 return selectionWidget;
851
852} // 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(), 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 681 of file KisToolSelectMagnetic.cc.

682{
683 KisCanvas2 *kisCanvas = dynamic_cast<KisCanvas2 *>(canvas());
684 KIS_ASSERT_RECOVER_RETURN(kisCanvas);
685 kisCanvas->updateCanvas();
687 m_continuedMode = false;
688 disconnect(action("undo_polygon_selection"), nullptr, this, nullptr);
689
691}
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 379 of file KisToolSelectMagnetic.cc.

380{
381 if (m_anchorPoints.isEmpty())
382 return;
383
384 if (m_anchorPoints.size() <= 1) {
386
387 } else if (m_selectedAnchor == 0) { // if it is the initial anchor
388 m_anchorPoints.pop_front();
389 m_pointCollection.pop_front();
390
391 if (m_complete) {
393 }
394
395 } else if (m_selectedAnchor == m_anchorPoints.count() - 1) { // if it is the last anchor
396 m_anchorPoints.pop_back();
397 m_pointCollection.pop_back();
398
399 if (m_complete) {
401 }
402
403 } else { // it is in the middle
409 }
410
411 if (m_complete && m_anchorPoints.size() < 3) {
412 m_complete = false;
413 m_pointCollection.pop_back();
414 }
415
417
418} // 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 631 of file KisToolSelectMagnetic.cc.

632{
633 const KisHandlePalette palette = canvas()->displayRendererInterface()->handlePaletteForDisplayColorSpace();
634 int sides = updateInitialAnchorBounds(m_anchorPoints.first());
635 Q_FOREACH (const QPoint pt, m_anchorPoints) {
636 KisHandlePainterHelper helper(&gc, handleRadius(), decorationThickness());
637 QRect r(QPoint(0, 0), QSize(sides, sides));
638 r.moveCenter(pt);
639 if (r.contains(m_lastCursorPos.toPoint())) {
641 } else {
642 helper.setHandleStyle(KisHandleStyle::primarySelection(palette));
643 }
644 helper.drawHandleRect(pixelToView(pt), 4, QPoint(0, 0));
645 }
646}
The KisHandlePainterHelper class is a special helper for painting handles around objects....
static KisHandleStyle & primarySelection(KisHandlePalette palette=KisHandlePalette())
static KisHandleStyle & highlightedPrimaryHandles(KisHandlePalette palette=KisHandlePalette())
rgba palette[MAX_PALETTE]
Definition palette.c:35

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

◆ endPrimaryAction()

void KisToolSelectMagnetic::endPrimaryAction ( KoPointerEvent * event)
override

Definition at line 341 of file KisToolSelectMagnetic.cc.

342{
343 if (isMovingSelection()) {
345 return;
346 }
347
348 if (m_selected && convertToPixelCoord(event) != m_cursorOnPress) {
349 if (!image()->bounds().contains(m_anchorPoints[m_selectedAnchor])) {
351 } else {
353 }
354 } else if (m_selected) {
355 QPointF temp(convertToPixelCoord(event));
356
357 if (!image()->bounds().contains(temp.toPoint())) {
358 return;
359 }
360
361 if (m_snapBound.contains(temp) && m_anchorPoints.count() > 1) {
362 if(m_complete){
364 return;
365 }
366 vQPointF edge = computeEdgeWrapper(m_anchorPoints.last(), temp.toPoint());
367 m_points.append(edge);
368 m_pointCollection.push_back(edge);
369 m_complete = true;
370 }
371 }
375 }
376 m_selected = false;
377} // 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 474 of file KisToolSelectMagnetic.cc.

475{
476 KisCanvas2 *kisCanvas = dynamic_cast<KisCanvas2 *>(canvas());
477 KIS_ASSERT_RECOVER_RETURN(kisCanvas);
478 kisCanvas->updateCanvas();
479 setMode(KisTool::HOVER_MODE);
480 m_complete = false;
481 m_finished = true;
482
483 // just for testing out
484 // m_worker.saveTheImage(m_points);
485
486 QRectF boundingViewRect =
488
489 KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Magnetic Selection"));
490
491 if (m_points.count() > 2 &&
492 !helper.tryDeselectCurrentSelection(boundingViewRect, selectionAction()))
493 {
494 KisCursorOverrideLock cursorLock(KisCursor::waitCursor());
495
496 const SelectionMode mode =
497 helper.tryOverrideSelectionMode(kisCanvas->viewManager()->selection(),
500 if (mode == PIXEL_SELECTION) {
501 KisProcessingApplicator applicator(
502 currentImage(),
503 currentNode(),
506 kundo2_i18n("Magnetic Selection"));
507
508 KisPixelSelectionSP tmpSel =
509 new KisPixelSelection(new KisDefaultBounds(currentImage()));
510
511 const bool antiAlias = antiAliasSelection();
512 const int grow = growSelection();
513 const int feather = featherSelection();
514
515 QPainterPath path;
516 path.addPolygon(m_points);
517 path.closeSubpath();
518
520 [tmpSel, antiAlias, grow, feather, path]() mutable
521 -> KUndo2Command * {
522 KisPainter painter(tmpSel);
523 painter.setPaintColor(
524 KoColor(Qt::black, tmpSel->colorSpace()));
525 // Since the feathering already smooths the selection, the
526 // antiAlias is not applied if we must feather
527 painter.setAntiAliasPolygonFill(antiAlias && feather == 0);
528 painter.setFillStyle(KisPainter::FillStyleForegroundColor);
529 painter.setStrokeStyle(KisPainter::StrokeStyleNone);
530
531 painter.paintPainterPath(path);
532
533 if (grow > 0) {
534 KisGrowSelectionFilter biggy(grow, grow);
535 biggy.process(tmpSel,
536 tmpSel->selectedRect().adjusted(-grow,
537 -grow,
538 grow,
539 grow));
540 } else if (grow < 0) {
541 KisShrinkSelectionFilter tiny(-grow, -grow, false);
542 tiny.process(tmpSel, tmpSel->selectedRect());
543 }
544 if (feather > 0) {
545 KisFeatherSelectionFilter feathery(feather);
546 feathery.process(
547 tmpSel,
548 tmpSel->selectedRect().adjusted(-feather,
549 -feather,
550 feather,
551 feather));
552 }
553
554 if (grow == 0 && feather == 0) {
555 tmpSel->setOutlineCache(path);
556 } else {
557 tmpSel->invalidateOutlineCache();
558 }
559
560 return 0;
561 });
562
563 applicator.applyCommand(cmd, KisStrokeJobData::SEQUENTIAL);
564 helper.selectPixelSelection(applicator, tmpSel, selectionAction());
565 applicator.end();
566
567 } else {
568 KoPathShape *path = new KoPathShape();
569 path->setShapeId(KoPathShapeId);
570
571 QTransform resolutionMatrix;
572 resolutionMatrix.scale(1 / currentImage()->xRes(), 1 / currentImage()->yRes());
573 path->moveTo(resolutionMatrix.map(m_points[0]));
574 for (int i = 1; i < m_points.count(); i++)
575 path->lineTo(resolutionMatrix.map(m_points[i]));
576 path->close();
577 path->normalize();
578 helper.addSelectionShape(path, selectionAction());
579 }
580 }
581
583
585} // 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 57 of file KisToolSelectMagnetic.cc.

58{
59 if (isSelecting()) {
60 if (event->key() == Qt::Key_Control) {
61 m_continuedMode = true;
62 }
63 }
65}
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 164 of file KisToolSelectMagnetic.cc.

165{
166 if (isSelecting()) {
167 if (event->key() == Qt::Key_Control ||
168 !(event->modifiers() & Qt::ControlModifier)) {
169
170 m_continuedMode = false;
171 if (mode() != PAINT_MODE) {
172 // Prevent finishing the selection if there is only one point, since
173 // finishSelectionAction will deselect the current selection. That
174 // is fine if the user just clicks, but not if we are in continued
175 // mode
176 if (m_points.count() > 1) {
178 }
179 m_points.clear(); // ensure points are always cleared
180 }
181 }
182 }
183
185}
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 193 of file KisToolSelectMagnetic.cc.

194{
195 if (isMovingSelection()) {
197 return;
198 }
199
200 m_lastCursorPos = convertToPixelCoord(event);
201 if (isSelecting()) {
203 }
205} // 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 615 of file KisToolSelectMagnetic.cc.

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

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

◆ reEvaluatePoints()

void KisToolSelectMagnetic::reEvaluatePoints ( )
private

Definition at line 464 of file KisToolSelectMagnetic.cc.

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

References m_pointCollection, m_points, and updatePaintPath().

◆ requestStrokeCancellation()

void KisToolSelectMagnetic::requestStrokeCancellation ( )
override

Definition at line 716 of file KisToolSelectMagnetic.cc.

717{
718 m_complete = false;
719 m_finished = false;
720 setButtonsEnabled(false);
722}

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

◆ requestStrokeEnd()

void KisToolSelectMagnetic::requestStrokeEnd ( )
override

Definition at line 707 of file KisToolSelectMagnetic.cc.

708{
709 if (m_finished || m_anchorPoints.count() < 2) return;
710
711 setButtonsEnabled(false);
713 m_finished = false;
714}

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

◆ resetCursorStyle()

void KisToolSelectMagnetic::resetCursorStyle ( )
override

Definition at line 878 of file KisToolSelectMagnetic.cc.

879{
881 useCursor(KisCursor::loadWithSize("tool_magnetic_selection_cursor_add.svg", 32, 32, 6, 6));
882 } else if (selectionAction() == SELECTION_SUBTRACT) {
883 useCursor(KisCursor::loadWithSize("tool_magnetic_selection_cursor_sub.svg", 32, 32, 6, 6));
884 } else if (selectionAction() == SELECTION_INTERSECT) {
885 useCursor(KisCursor::loadWithSize("tool_magnetic_selection_cursor_inter.svg", 32, 32, 6, 6));
887 useCursor(KisCursor::loadWithSize("tool_magnetic_selection_cursor_symdiff.svg", 32, 32, 6, 6));
888 } else {
889 KisToolSelect::resetCursorStyle();
890 }
891}
@ SELECTION_INTERSECT
@ SELECTION_SYMMETRICDIFFERENCE
@ SELECTION_SUBTRACT
@ SELECTION_ADD

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

◆ resetVariables()

void KisToolSelectMagnetic::resetVariables ( )
private

Definition at line 587 of file KisToolSelectMagnetic.cc.

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

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 327 of file KisToolSelectMagnetic.cc.

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

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

◆ slotSetAnchorGap

void KisToolSelectMagnetic::slotSetAnchorGap ( int g)
slot

Definition at line 872 of file KisToolSelectMagnetic.cc.

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

References m_anchorGap, and m_configGroup.

◆ slotSetFilterRadius

void KisToolSelectMagnetic::slotSetFilterRadius ( qreal r)
slot

Definition at line 854 of file KisToolSelectMagnetic.cc.

855{
857 m_configGroup.writeEntry("filterradius", r);
858}

References m_configGroup, and m_filterRadius.

◆ slotSetSearchRadius

void KisToolSelectMagnetic::slotSetSearchRadius ( int r)
slot

Definition at line 866 of file KisToolSelectMagnetic.cc.

867{
869 m_configGroup.writeEntry("searchradius", r);
870}

References m_configGroup, and m_searchRadius.

◆ slotSetThreshold

void KisToolSelectMagnetic::slotSetThreshold ( int t)
slot

Definition at line 860 of file KisToolSelectMagnetic.cc.

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

References m_configGroup, and m_threshold.

◆ undoPoints

void KisToolSelectMagnetic::undoPoints ( )
slot

Definition at line 693 of file KisToolSelectMagnetic.cc.

694{
695 if (m_complete) return;
696
697 if(m_anchorPoints.count() <= 1){
699 return;
700 }
701
702 m_anchorPoints.pop_back();
703 m_pointCollection.pop_back();
705}

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

◆ updateCanvas()

void KisToolSelectMagnetic::updateCanvas ( )
private

◆ updateContinuedMode()

void KisToolSelectMagnetic::updateContinuedMode ( )
private

Definition at line 660 of file KisToolSelectMagnetic.cc.

661{
662 if (!m_points.isEmpty()) {
663 qint32 lastPointIndex = m_points.count() - 1;
664
665 QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_lastCursorPos).normalized();
666 updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH);
667
668 updateCanvasPixelRect(updateRect);
669 }
670}
#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 648 of file KisToolSelectMagnetic.cc.

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

References FEEDBACK_LINE_WIDTH, kisGrowRect(), and m_points.

◆ updateInitialAnchorBounds()

int KisToolSelectMagnetic::updateInitialAnchorBounds ( QPoint pt)
private

Definition at line 455 of file KisToolSelectMagnetic.cc.

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

References m_snapBound.

◆ updatePaintPath()

void KisToolSelectMagnetic::updatePaintPath ( )
private

Definition at line 596 of file KisToolSelectMagnetic.cc.

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

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