Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPathToolSelection.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2006, 2008 Jan Hambrecht <jaham@gmx.net>
3 * SPDX-FileCopyrightText: 2006, 2007 Thorsten Zachmann <zachmann@kde.org>
4 * SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
5 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
6 *
7 * SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9
10#include "KoPathToolSelection.h"
11#include "KoPathTool.h"
12#include <KoParameterShape.h>
13#include <KoPathPoint.h>
14#include <KoPathPointData.h>
15#include <KoViewConverter.h>
16#include <KoCanvasBase.h>
18#include <KoShapeController.h>
19#include <QPainter>
21
23 : m_tool(tool)
24{
25}
26
30
31void KoPathToolSelection::paint(QPainter &painter, const KoViewConverter &converter, qreal handleRadius)
32{
33 int decorationThickness = m_tool? m_tool->decorationThickness(): 1;
34 PathShapePointMap::iterator it(m_shapePointMap.begin());
35 for (; it != m_shapePointMap.end(); ++it) {
37 KoShape::createHandlePainterHelperView(&painter, it.key(), converter, handleRadius, decorationThickness);
39
40 Q_FOREACH (KoPathPoint *p, it.value()) {
41 p->paint(helper, KoPathPoint::All);
42 }
43 }
44}
45
46void KoPathToolSelection::add(KoPathPoint * point, bool clear)
47{
48 if(! point)
49 return;
50
51 bool alreadyIn = false;
52 if (clear) {
53 if (size() == 1 && m_selectedPoints.contains(point)) {
54 alreadyIn = true;
55 } else {
56 this->clear();
57 }
58 } else {
59 alreadyIn = m_selectedPoints.contains(point);
60 }
61
62 if (!alreadyIn) {
63 m_selectedPoints.insert(point);
64 KoPathShape * pathShape = point->parent();
65 PathShapePointMap::iterator it(m_shapePointMap.find(pathShape));
66 if (it == m_shapePointMap.end()) {
67 it = m_shapePointMap.insert(pathShape, QSet<KoPathPoint *>());
68 }
69 it.value().insert(point);
70 Q_EMIT selectionChanged();
71 }
72}
73
75{
76 if (m_selectedPoints.remove(point)) {
77 KoPathShape * pathShape = point->parent();
78 m_shapePointMap[pathShape].remove(point);
79 if (m_shapePointMap[pathShape].size() == 0) {
80 m_shapePointMap.remove(pathShape);
81 }
82 Q_EMIT selectionChanged();
83 }
84}
85
87{
88 m_selectedPoints.clear();
89 m_shapePointMap.clear();
90 Q_EMIT selectionChanged();
91}
92
93void KoPathToolSelection::selectPoints(const QRectF &rect, bool clearSelection)
94{
95 if (clearSelection) {
96 clear();
97 }
98
99 blockSignals(true);
100 Q_FOREACH (KoPathShape* shape, m_selectedShapes) {
101 KoParameterShape *parameterShape = dynamic_cast<KoParameterShape*>(shape);
102 if (parameterShape && parameterShape->isParametricShape())
103 continue;
104 Q_FOREACH (KoPathPoint* point, shape->pointsAt(shape->documentToShape(rect)))
105 add(point, false);
106 }
107 blockSignals(false);
108 Q_EMIT selectionChanged();
109}
110
112{
113 blockSignals(true);
114 Q_FOREACH (KoPathShape* shape, m_selectedShapes) {
115 KoParameterShape *parameterShape = dynamic_cast<KoParameterShape*>(shape);
116 if (parameterShape && parameterShape->isParametricShape())
117 continue;
118 Q_FOREACH (KoPathPoint* point, shape->pointsAt(shape->outlineRect().adjusted(-2, -2, 2, 2)))
119 add(point, false);
120 }
121 blockSignals(false);
122 Q_EMIT selectionChanged();
123}
124
126{
127 return m_shapePointMap.size();
128}
129
131{
132 return m_selectedPoints.size();
133}
134
136{
137 return m_selectedPoints.contains(point);
138}
139
140const QSet<KoPathPoint *> & KoPathToolSelection::selectedPoints() const
141{
142 return m_selectedPoints;
143}
144
146{
147 QList<KoPathPointData> pointData;
148 Q_FOREACH (KoPathPoint* p, m_selectedPoints) {
149 KoPathShape * pathShape = p->parent();
150 pointData.append(KoPathPointData(pathShape, pathShape->pathPointIndex(p)));
151 }
152 return pointData;
153}
154
156{
157 QList<KoPathPointData> pointData;
158
160 std::sort(pd.begin(), pd.end());
161
162 KoPathPointData last(0, KoPathPointIndex(-1, -1));
163 KoPathPointData lastSubpathStart(0, KoPathPointIndex(-1, -1));
164
165 QList<KoPathPointData>::const_iterator it(pd.constBegin());
166 for (; it != pd.constEnd(); ++it) {
167 if (it->pointIndex.second == 0)
168 lastSubpathStart = *it;
169
170 if (last.pathShape == it->pathShape
171 && last.pointIndex.first == it->pointIndex.first
172 && last.pointIndex.second + 1 == it->pointIndex.second) {
173 pointData.append(last);
174 }
175
176 if (lastSubpathStart.pathShape == it->pathShape
177 && it->pathShape->pointByIndex(it->pointIndex)->properties() & KoPathPoint::CloseSubpath
178 && (it->pathShape->pointByIndex(it->pointIndex)->properties() & KoPathPoint::StartSubpath) == 0) {
179 pointData.append(*it);
180 }
181
182 last = *it;
183 }
184
185 return pointData;
186}
187
192
194{
195 Q_FOREACH(KoPathShape *shape, m_selectedShapes) {
196 shape->removeShapeChangeListener(this);
197 }
198
199 m_selectedShapes = shapes;
200
201 Q_FOREACH(KoPathShape *shape, m_selectedShapes) {
202 shape->addShapeChangeListener(this);
203 }
204}
205
207{
208 bool selectionHasChanged = false;
209
210 PathShapePointMap::iterator it(m_shapePointMap.begin());
211 while (it != m_shapePointMap.end()) {
212 KoParameterShape *parameterShape = dynamic_cast<KoParameterShape*>(it.key());
213 bool isParametricShape = parameterShape && parameterShape->isParametricShape();
214 if (! m_selectedShapes.contains(it.key()) || isParametricShape) {
215 QSet<KoPathPoint *>::iterator pointIt(it.value().begin());
216 for (; pointIt != it.value().end(); ++pointIt) {
217 m_selectedPoints.remove(*pointIt);
218 }
219 it = m_shapePointMap.erase(it);
220 selectionHasChanged = true;
221 } else {
222 QSet<KoPathPoint *>::iterator pointIt(it.value().begin());
223 while (pointIt != it.value().end()) {
224 if ((*pointIt)->parent()->pathPointIndex(*pointIt) == KoPathPointIndex(-1, -1)) {
225 m_selectedPoints.remove(*pointIt);
226 pointIt = it.value().erase(pointIt);
227 selectionHasChanged = true;
228 } else {
229 ++pointIt;
230 }
231 }
232 ++it;
233 }
234 }
235
236 if (selectionHasChanged)
237 Q_EMIT selectionChanged();
238}
239
241{
242 return !m_selectedPoints.isEmpty();
243}
244
246{
247 QSet<KoPathPoint*> selectedShapePoints = m_shapePointMap.value(shape, QSet<KoPathPoint*>());
248
249 Q_FOREACH (KoPathPoint *point, selectedShapePoints) {
250 remove(point);
251 }
252
253 Q_FOREACH (const KoPathPointIndex &index, newSelection) {
254 KoPathPoint *point = shape->pointByIndex(index);
255 KIS_SAFE_ASSERT_RECOVER(point) { continue; }
256
257 add(point, false);
258 }
259
260 Q_EMIT selectionChanged();
261}
262
264{
265 QSet<KoPathPoint*> selectedShapePoints = m_shapePointMap.value(shape, QSet<KoPathPoint*>());
266
267 Q_FOREACH (KoPathPoint *point, selectedShapePoints) {
268 m_selectedPoints.remove(point);
269 }
270 m_shapePointMap.remove(shape);
271
273
274 Q_EMIT selectionChanged();
275}
276
278{
279 if (type == KoShape::Deleted) {
280 // we cannot select non-path shapes, so static cast is safe here
282
283 if (KoPathShape *pathShape = static_cast<KoPathShape*>(shape)) {
284
285 QSet<KoPathPoint*> selectedShapePoints = m_shapePointMap.value(pathShape, QSet<KoPathPoint*>());
286 Q_FOREACH (KoPathPoint *point, selectedShapePoints) {
287 m_selectedPoints.remove(point);
288 }
289 m_shapePointMap.remove(pathShape);
290 m_selectedShapes.removeAll(pathShape);
291 }
292 }
293
295}
const Params2D p
#define KoPathShapeId
Definition KoPathShape.h:20
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void setHandleStyle(const KisHandleStyle &style)
static KisHandleStyle & selectedPrimaryHandles()
bool isParametricShape() const
Check if object is a parametric shape.
Describe a KoPathPoint by a KoPathShape and its indices.
KoPathPointIndex pointIndex
position of the point in the path shape
KoPathShape * pathShape
path shape the path point belongs too
A KoPathPoint represents a point in a path.
KoPathShape * parent() const
Get the path shape the point belongs to.
@ StartSubpath
it starts a new subpath by a moveTo command
Definition KoPathPoint.h:38
@ CloseSubpath
it closes a subpath (only applicable on StartSubpath and StopSubpath)
Definition KoPathPoint.h:40
The position of a path point within a path shape.
Definition KoPathShape.h:63
QRectF outlineRect() const override
reimplemented
QList< KoPathPoint * > pointsAt(const QRectF &rect, const bool useControlPoints=false) const
Returns the path points within the given rectangle.
KoPathPointIndex pathPointIndex(const KoPathPoint *point) const
Returns the path point index of a given path point.
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.
void notifyPathPointsChanged(KoPathShape *shape) override
QList< KoPathShape * > m_selectedShapes
int objectCount() const
Get the number of path objects in the selection.
void paint(QPainter &painter, const KoViewConverter &converter, qreal handleRadius)
Draw the selected points.
const QSet< KoPathPoint * > & selectedPoints() const
Get all selected points.
bool contains(KoPathPoint *point)
Check if a point is in the selection.
bool hasSelection() override
reimplemented from KoToolSelection
int size() const
Get the number of path points in the selection.
QList< KoPathPointData > selectedPointsData() const
Get the point data of all selected points.
KoPathToolSelection(KoPathTool *tool)
void recommendPointSelectionChange(KoPathShape *shape, const QList< KoPathPointIndex > &newSelection) override
void update()
Update the selection to contain only valid points.
void clear()
Clear the selection.
QList< KoPathShape * > selectedShapes() const
Returns list of selected shapes.
void add(KoPathPoint *point, bool clear)
Add a point to the selection.
QSet< KoPathPoint * > m_selectedPoints
void setSelectedShapes(const QList< KoPathShape * > shapes)
Sets list of selected shapes.
PathShapePointMap m_shapePointMap
void selectPoints(const QRectF &rect, bool clearSelection)
Select points in rect.
void notifyShapeChanged(KoShape::ChangeType type, KoShape *shape) override
void remove(KoPathPoint *point)
Remove a point form the selection.
QList< KoPathPointData > selectedSegmentsData() const
Get the point data of all selected segments.
void notifyPathPointsChanged(KoPathShape *shape)
void addShapeChangeListener(ShapeChangeListener *listener)
Definition KoShape.cpp:1360
QString shapeId() const
Definition KoShape.cpp:1057
void removeShapeChangeListener(ShapeChangeListener *listener)
Definition KoShape.cpp:1368
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
Definition KoShape.cpp:1211
KoShapeContainer * parent() const
Definition KoShape.cpp:1039
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:1177
ChangeType
Used by shapeChanged() to select which change was made.
Definition KoShape.h:95
@ Deleted
the shape was deleted
Definition KoShape.h:104
int decorationThickness() const
decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen ...
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
void notifyShapeChanged(ChangeType type, KoShape *shape) override