11#include <QPainterPath>
16#include <klocalizedstring.h>
47#define FEEDBACK_LINE_WIDTH 2
51 KisCursor::loadWithSize(
"tool_magnetic_selection_cursor.svg", 32, 32, 6, 6),
52 i18n(
"Magnetic Selection"))
60 if (event->key() == Qt::Key_Control) {
75 qreal totalDistance = 0.0;
82 for (; finalPoint < points.count(); finalPoint++) {
83 totalDistance +=
kisDistance(points[finalPoint], points[finalPoint - 1]);
86 minPoint = finalPoint;
90 midPoint = finalPoint;
99 bool foundSomething =
false;
101 for (
int i = midPoint; i < finalPoint; i++) {
107 for (
int j = 0; j <= i; j++) {
108 temp.push_back(points[j]);
112 foundSomething =
true;
118 if (!foundSomething) {
119 for (
int i = midPoint - 1; i >= minPoint; i--) {
124 for (
int j = midPoint - 1; j >= i; j--) {
125 temp.push_front(points[j]);
129 foundSomething =
true;
136 if (!foundSomething) {
141 for (
int j = 0; j <= midPoint; j++) {
142 temp.push_back(points[j]);
146 checkPoint = midPoint;
147 foundSomething =
true;
154 for (; finalPoint < points.count(); finalPoint++) {
155 totalDistance +=
kisDistance(points[finalPoint], points[checkPoint]);
157 points.remove(0, checkPoint + 1);
167 if (event->key() == Qt::Key_Control ||
168 !(event->modifiers() & Qt::ControlModifier)) {
171 if (mode() != PAINT_MODE) {
216 QPointF temp(convertToPixelCoord(event));
218 if (!image()->
bounds().contains(temp.toPoint())) {
244 updateCanvasPixelRect(image()->
bounds());
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));
254 if (r.contains(temp.toPoint())) {
330 if (!image()->
bounds().contains(current))
355 QPointF temp(convertToPixelCoord(event));
357 if (!image()->
bounds().contains(temp.toPoint())) {
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));
486 QRectF boundingViewRect =
520 [tmpSel, antiAlias, grow, feather, path]()
mutable
540 }
else if (grow < 0) {
554 if (grow == 0 && feather == 0) {
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]));
602 for (
int i = 1; i <
m_points.count(); i++) {
612 updateCanvasPixelRect(image()->
bounds());
626 paintToolOutline(&gc, outline);
637 QRect r(QPoint(0, 0), QSize(sides, sides));
651 qint32 lastPointIndex =
m_points.count() - 1;
653 QRectF updateRect = QRectF(
m_points[lastPointIndex - 1],
m_points[lastPointIndex]).normalized();
656 updateCanvasPixelRect(updateRect);
663 qint32 lastPointIndex =
m_points.count() - 1;
668 updateCanvasPixelRect(updateRect);
675 m_configGroup = KSharedConfig::openConfig()->group(toolId());
676 connect(action(
"undo_polygon_selection"), SIGNAL(triggered()), SLOT(
undoPoints()), Qt::UniqueConnection);
688 disconnect(action(
"undo_polygon_selection"),
nullptr,
this,
nullptr);
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",
739 sliderThreshold->setObjectName(
"threshold");
741 sliderThreshold->setSingleStep(10);
742 sliderThreshold->setPrefix(
743 i18nc(
"Threshold in Magnetic Selection's Tool options",
"Threshold: "));
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",
752 sliderSearchRadius->setSuffix(
" px");
755 sliderAnchorGap->setObjectName(
"anchorgap");
757 sliderAnchorGap->setSingleStep(10);
758 sliderAnchorGap->setPrefix(
759 i18nc(
"Anchor Gap in Magnetic Selection's Tool options",
761 sliderAnchorGap->setSuffix(
" px");
763 QPushButton *buttonCompleteSelection =
764 new QPushButton(i18nc(
"Complete the selection",
"Complete"),
766 buttonCompleteSelection->setEnabled(
false);
768 QPushButton *buttonDiscardSelection =
769 new QPushButton(i18nc(
"Discard the selection",
"Discard"),
771 buttonDiscardSelection->setEnabled(
false);
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"));
792 i18nc(
"The 'path options' section label in magnetic selection's "
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);
817 connect(sliderRadius,
818 SIGNAL(valueChanged(qreal)),
821 connect(sliderThreshold,
822 SIGNAL(valueChanged(
int)),
825 connect(sliderSearchRadius,
826 SIGNAL(valueChanged(
int)),
829 connect(sliderAnchorGap,
830 SIGNAL(valueChanged(
int)),
833 connect(buttonCompleteSelection,
839 buttonCompleteSelection,
840 SLOT(setEnabled(
bool)));
841 connect(buttonDiscardSelection,
847 buttonDiscardSelection,
848 SLOT(setEnabled(
bool)));
850 return selectionWidget;
889 KisToolSelect::resetCursorStyle();
QVector< KisImageSignalType > KisImageSignalVector
void updateCanvas(const QRectF &rc) override
KisViewManager * viewManager() const
static QCursor loadWithSize(const QString &cursorName, int width, int height, int hotspotX=-1, int hotspotY=-1)
static QCursor waitCursor()
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.
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void drawHandleRect(const QPointF ¢er, qreal radius)
void setHandleStyle(const KisHandleStyle &style)
static KisHandleStyle & primarySelection(KisHandlePalette palette=KisHandlePalette())
static KisHandleStyle & highlightedPrimaryHandles(KisHandlePalette palette=KisHandlePalette())
const KoColorSpace * colorSpace() const
@ FillStyleForegroundColor
void paintPainterPath(const QPainterPath &path)
void setStrokeStyle(StrokeStyle strokeStyle)
Set the current brush stroke style.
void setFillStyle(FillStyle fillStyle)
Set the current style with which to fill.
void setPaintColor(const KoColor &color)
void setAntiAliasPolygonFill(bool antiAliasPolygonFill)
Set whether a polygon's filled area should be anti-aliased or not. The default is true.
void applyCommand(KUndo2Command *command, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
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 ...
KisSelectionSP selection()
The position of a path point within a path shape.
#define KIS_ASSERT_RECOVER_RETURN(cond)
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
T kisGrowRect(const T &rect, U offset)
KUndo2MagicString kundo2_i18n(const char *text)
void accumulateBounds(const Point &pt, Rect *bounds)
rgba palette[MAX_PALETTE]
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...
void invalidateOutlineCache()
void setOutlineCache(const QPainterPath &cache)
QRect selectedRect() const