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>
20#include <QPainter>
22
24 : m_tool(tool)
25{
26}
27
31
32void KoPathToolSelection::paint(QPainter &painter, const KoViewConverter &converter, qreal handleRadius, KoColorDisplayRendererInterface *renderInterface)
33{
34 int decorationThickness = m_tool? m_tool->decorationThickness(): 1;
36 PathShapePointMap::iterator it(m_shapePointMap.begin());
37 for (; it != m_shapePointMap.end(); ++it) {
39 KoShape::createHandlePainterHelperView(&painter, it.key(), converter, handleRadius, decorationThickness);
41
42 Q_FOREACH (KoPathPoint *p, it.value()) {
43 p->paint(helper, KoPathPoint::All);
44 }
45 }
46}
47
48void KoPathToolSelection::add(KoPathPoint * point, bool clear)
49{
50 if(! point)
51 return;
52
53 bool alreadyIn = false;
54 if (clear) {
55 if (size() == 1 && m_selectedPoints.contains(point)) {
56 alreadyIn = true;
57 } else {
58 this->clear();
59 }
60 } else {
61 alreadyIn = m_selectedPoints.contains(point);
62 }
63
64 if (!alreadyIn) {
65 m_selectedPoints.insert(point);
66 KoPathShape * pathShape = point->parent();
67 PathShapePointMap::iterator it(m_shapePointMap.find(pathShape));
68 if (it == m_shapePointMap.end()) {
69 it = m_shapePointMap.insert(pathShape, QSet<KoPathPoint *>());
70 }
71 it.value().insert(point);
72 Q_EMIT selectionChanged();
73 }
74}
75
77{
78 if (m_selectedPoints.remove(point)) {
79 KoPathShape * pathShape = point->parent();
80 m_shapePointMap[pathShape].remove(point);
81 if (m_shapePointMap[pathShape].size() == 0) {
82 m_shapePointMap.remove(pathShape);
83 }
84 Q_EMIT selectionChanged();
85 }
86}
87
89{
90 m_selectedPoints.clear();
91 m_shapePointMap.clear();
92 Q_EMIT selectionChanged();
93}
94
95void KoPathToolSelection::selectPoints(const QRectF &rect, bool clearSelection)
96{
97 if (clearSelection) {
98 clear();
99 }
100
101 blockSignals(true);
102 Q_FOREACH (KoPathShape* shape, m_selectedShapes) {
103 KoParameterShape *parameterShape = dynamic_cast<KoParameterShape*>(shape);
104 if (parameterShape && parameterShape->isParametricShape())
105 continue;
106 Q_FOREACH (KoPathPoint* point, shape->pointsAt(shape->documentToShape(rect)))
107 add(point, false);
108 }
109 blockSignals(false);
110 Q_EMIT selectionChanged();
111}
112
114{
115 blockSignals(true);
116 Q_FOREACH (KoPathShape* shape, m_selectedShapes) {
117 KoParameterShape *parameterShape = dynamic_cast<KoParameterShape*>(shape);
118 if (parameterShape && parameterShape->isParametricShape())
119 continue;
120 Q_FOREACH (KoPathPoint* point, shape->pointsAt(shape->outlineRect().adjusted(-2, -2, 2, 2)))
121 add(point, false);
122 }
123 blockSignals(false);
124 Q_EMIT selectionChanged();
125}
126
128{
129 return m_shapePointMap.size();
130}
131
133{
134 return m_selectedPoints.size();
135}
136
138{
139 return m_selectedPoints.contains(point);
140}
141
142const QSet<KoPathPoint *> & KoPathToolSelection::selectedPoints() const
143{
144 return m_selectedPoints;
145}
146
148{
149 QList<KoPathPointData> pointData;
150 Q_FOREACH (KoPathPoint* p, m_selectedPoints) {
151 KoPathShape * pathShape = p->parent();
152 pointData.append(KoPathPointData(pathShape, pathShape->pathPointIndex(p)));
153 }
154 return pointData;
155}
156
158{
159 QList<KoPathPointData> pointData;
160
162 std::sort(pd.begin(), pd.end());
163
164 KoPathPointData last(0, KoPathPointIndex(-1, -1));
165 KoPathPointData lastSubpathStart(0, KoPathPointIndex(-1, -1));
166
167 QList<KoPathPointData>::const_iterator it(pd.constBegin());
168 for (; it != pd.constEnd(); ++it) {
169 if (it->pointIndex.second == 0)
170 lastSubpathStart = *it;
171
172 if (last.pathShape == it->pathShape
173 && last.pointIndex.first == it->pointIndex.first
174 && last.pointIndex.second + 1 == it->pointIndex.second) {
175 pointData.append(last);
176 }
177
178 if (lastSubpathStart.pathShape == it->pathShape
179 && it->pathShape->pointByIndex(it->pointIndex)->properties() & KoPathPoint::CloseSubpath
180 && (it->pathShape->pointByIndex(it->pointIndex)->properties() & KoPathPoint::StartSubpath) == 0) {
181 pointData.append(*it);
182 }
183
184 last = *it;
185 }
186
187 return pointData;
188}
189
194
196{
197 Q_FOREACH(KoPathShape *shape, m_selectedShapes) {
198 shape->removeShapeChangeListener(this);
199 }
200
201 m_selectedShapes = shapes;
202
203 Q_FOREACH(KoPathShape *shape, m_selectedShapes) {
204 shape->addShapeChangeListener(this);
205 }
206}
207
209{
210 bool selectionHasChanged = false;
211
212 PathShapePointMap::iterator it(m_shapePointMap.begin());
213 while (it != m_shapePointMap.end()) {
214 KoParameterShape *parameterShape = dynamic_cast<KoParameterShape*>(it.key());
215 bool isParametricShape = parameterShape && parameterShape->isParametricShape();
216 if (! m_selectedShapes.contains(it.key()) || isParametricShape) {
217 QSet<KoPathPoint *>::iterator pointIt(it.value().begin());
218 for (; pointIt != it.value().end(); ++pointIt) {
219 m_selectedPoints.remove(*pointIt);
220 }
221 it = m_shapePointMap.erase(it);
222 selectionHasChanged = true;
223 } else {
224 QSet<KoPathPoint *>::iterator pointIt(it.value().begin());
225 while (pointIt != it.value().end()) {
226 if ((*pointIt)->parent()->pathPointIndex(*pointIt) == KoPathPointIndex(-1, -1)) {
227 m_selectedPoints.remove(*pointIt);
228 pointIt = it.value().erase(pointIt);
229 selectionHasChanged = true;
230 } else {
231 ++pointIt;
232 }
233 }
234 ++it;
235 }
236 }
237
238 if (selectionHasChanged)
239 Q_EMIT selectionChanged();
240}
241
243{
244 return !m_selectedPoints.isEmpty();
245}
246
248{
249 QSet<KoPathPoint*> selectedShapePoints = m_shapePointMap.value(shape, QSet<KoPathPoint*>());
250
251 Q_FOREACH (KoPathPoint *point, selectedShapePoints) {
252 remove(point);
253 }
254
255 Q_FOREACH (const KoPathPointIndex &index, newSelection) {
256 KoPathPoint *point = shape->pointByIndex(index);
257 KIS_SAFE_ASSERT_RECOVER(point) { continue; }
258
259 add(point, false);
260 }
261
262 Q_EMIT selectionChanged();
263}
264
266{
267 QSet<KoPathPoint*> selectedShapePoints = m_shapePointMap.value(shape, QSet<KoPathPoint*>());
268
269 Q_FOREACH (KoPathPoint *point, selectedShapePoints) {
270 m_selectedPoints.remove(point);
271 }
272 m_shapePointMap.remove(shape);
273
275
276 Q_EMIT selectionChanged();
277}
278
280{
281 if (type == KoShape::Deleted) {
282 // we cannot select non-path shapes, so static cast is safe here
284
285 if (KoPathShape *pathShape = static_cast<KoPathShape*>(shape)) {
286
287 QSet<KoPathPoint*> selectedShapePoints = m_shapePointMap.value(pathShape, QSet<KoPathPoint*>());
288 Q_FOREACH (KoPathPoint *point, selectedShapePoints) {
289 m_selectedPoints.remove(point);
290 }
291 m_shapePointMap.remove(pathShape);
292 m_selectedShapes.removeAll(pathShape);
293 }
294 }
295
297}
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(KisHandlePalette palette=KisHandlePalette())
virtual KisHandlePalette handlePaletteForDisplayColorSpace() const =0
handlePaletteForDisplayColorSpace
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.
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.
void paint(QPainter &painter, const KoViewConverter &converter, qreal handleRadius, KoColorDisplayRendererInterface *renderInterface)
Draw the selected points.
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:1152
QString shapeId() const
Definition KoShape.cpp:875
void removeShapeChangeListener(ShapeChangeListener *listener)
Definition KoShape.cpp:1160
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
Definition KoShape.cpp:1011
KoShapeContainer * parent() const
Definition KoShape.cpp:857
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:977
ChangeType
Used by shapeChanged() to select which change was made.
Definition KoShape.h:92
@ Deleted
the shape was deleted
Definition KoShape.h:101
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
rgba palette[MAX_PALETTE]
Definition palette.c:35
void notifyShapeChanged(ChangeType type, KoShape *shape) override