11#include <QPainterPath>
16#include <klocalizedstring.h>
46#define FEEDBACK_LINE_WIDTH 2
50 KisCursor::load(
"tool_magnetic_selection_cursor.png", 6, 6),
51 i18n(
"Magnetic Selection"))
59 if (event->key() == Qt::Key_Control) {
74 qreal totalDistance = 0.0;
81 for (; finalPoint < points.count(); finalPoint++) {
82 totalDistance +=
kisDistance(points[finalPoint], points[finalPoint - 1]);
85 minPoint = finalPoint;
89 midPoint = finalPoint;
98 bool foundSomething =
false;
100 for (
int i = midPoint; i < finalPoint; i++) {
106 for (
int j = 0; j <= i; j++) {
107 temp.push_back(points[j]);
111 foundSomething =
true;
117 if (!foundSomething) {
118 for (
int i = midPoint - 1; i >= minPoint; i--) {
123 for (
int j = midPoint - 1; j >= i; j--) {
124 temp.push_front(points[j]);
128 foundSomething =
true;
135 if (!foundSomething) {
140 for (
int j = 0; j <= midPoint; j++) {
141 temp.push_back(points[j]);
145 checkPoint = midPoint;
146 foundSomething =
true;
153 for (; finalPoint < points.count(); finalPoint++) {
154 totalDistance +=
kisDistance(points[finalPoint], points[checkPoint]);
156 points.remove(0, checkPoint + 1);
166 if (event->key() == Qt::Key_Control ||
167 !(event->modifiers() & Qt::ControlModifier)) {
170 if (mode() != PAINT_MODE) {
215 QPointF temp(convertToPixelCoord(event));
217 if (!image()->
bounds().contains(temp.toPoint())) {
243 updateCanvasPixelRect(image()->
bounds());
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));
253 if (r.contains(temp.toPoint())) {
329 if (!image()->
bounds().contains(current))
354 QPointF temp(convertToPixelCoord(event));
356 if (!image()->
bounds().contains(temp.toPoint())) {
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));
485 QRectF boundingViewRect =
519 [tmpSel, antiAlias, grow, feather, path]()
mutable
539 }
else if (grow < 0) {
553 if (grow == 0 && feather == 0) {
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]));
601 for (
int i = 1; i <
m_points.count(); i++) {
611 updateCanvasPixelRect(image()->
bounds());
625 paintToolOutline(&gc, outline);
635 QRect r(QPoint(0, 0), QSize(sides, sides));
649 qint32 lastPointIndex =
m_points.count() - 1;
651 QRectF updateRect = QRectF(
m_points[lastPointIndex - 1],
m_points[lastPointIndex]).normalized();
654 updateCanvasPixelRect(updateRect);
661 qint32 lastPointIndex =
m_points.count() - 1;
666 updateCanvasPixelRect(updateRect);
673 m_configGroup = KSharedConfig::openConfig()->group(toolId());
674 connect(action(
"undo_polygon_selection"), SIGNAL(triggered()), SLOT(
undoPoints()), Qt::UniqueConnection);
686 disconnect(action(
"undo_polygon_selection"),
nullptr,
this,
nullptr);
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",
737 sliderThreshold->setObjectName(
"threshold");
739 sliderThreshold->setSingleStep(10);
740 sliderThreshold->setPrefix(
741 i18nc(
"Threshold in Magnetic Selection's Tool options",
"Threshold: "));
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",
750 sliderSearchRadius->setSuffix(
" px");
753 sliderAnchorGap->setObjectName(
"anchorgap");
755 sliderAnchorGap->setSingleStep(10);
756 sliderAnchorGap->setPrefix(
757 i18nc(
"Anchor Gap in Magnetic Selection's Tool options",
759 sliderAnchorGap->setSuffix(
" px");
761 QPushButton *buttonCompleteSelection =
762 new QPushButton(i18nc(
"Complete the selection",
"Complete"),
764 buttonCompleteSelection->setEnabled(
false);
766 QPushButton *buttonDiscardSelection =
767 new QPushButton(i18nc(
"Discard the selection",
"Discard"),
769 buttonDiscardSelection->setEnabled(
false);
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"));
790 i18nc(
"The 'path options' section label in magnetic selection's "
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);
816 SIGNAL(valueChanged(qreal)),
820 SIGNAL(valueChanged(
int)),
824 SIGNAL(valueChanged(
int)),
828 SIGNAL(valueChanged(
int)),
831 connect(buttonCompleteSelection,
837 buttonCompleteSelection,
838 SLOT(setEnabled(
bool)));
839 connect(buttonDiscardSelection,
845 buttonDiscardSelection,
846 SLOT(setEnabled(
bool)));
848 return selectionWidget;
879 useCursor(
KisCursor::load(
"tool_magnetic_selection_cursor_add.png", 6, 6));
881 useCursor(
KisCursor::load(
"tool_magnetic_selection_cursor_sub.png", 6, 6));
883 useCursor(
KisCursor::load(
"tool_magnetic_selection_cursor_inter.png", 6, 6));
885 useCursor(
KisCursor::load(
"tool_magnetic_selection_cursor_symdiff.png", 6, 6));
887 KisToolSelect::resetCursorStyle();
QVector< KisImageSignalType > KisImageSignalVector
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void updateCanvas(const QRectF &rc) override
KisViewManager * viewManager() const
static QCursor load(const QString &cursorName, 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 & highlightedPrimaryHandles()
static KisHandleStyle & primarySelection()
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)
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