File indexing completed on 2025-01-26 04:04:52
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2006, 2008 Jan Hambrecht <jaham@gmx.net> 0003 * SPDX-FileCopyrightText: 2006, 2007 Thorsten Zachmann <zachmann@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "KoPathPointInsertCommand.h" 0009 0010 #include "KoPathPoint.h" 0011 #include <KoPathSegment.h> 0012 #include <klocalizedstring.h> 0013 0014 class KoPathPointInsertCommandPrivate 0015 { 0016 public: 0017 KoPathPointInsertCommandPrivate() : deletePoints(true) { } 0018 ~KoPathPointInsertCommandPrivate() { 0019 if (deletePoints) { 0020 qDeleteAll(points); 0021 } 0022 } 0023 QList<KoPathPointData> pointDataList; 0024 QList<KoPathPoint*> points; 0025 QList<QPair<QPointF, QPointF> > controlPoints; 0026 bool deletePoints; 0027 }; 0028 0029 KoPathPointInsertCommand::KoPathPointInsertCommand(const QList<KoPathPointData> &pointDataList, qreal insertPosition, KUndo2Command *parent) 0030 : KUndo2Command(parent), 0031 d(new KoPathPointInsertCommandPrivate()) 0032 { 0033 if (insertPosition < 0) 0034 insertPosition = 0; 0035 if (insertPosition > 1) 0036 insertPosition = 1; 0037 0038 //TODO the list needs to be sorted 0039 0040 QList<KoPathPointData>::const_iterator it(pointDataList.begin()); 0041 for (; it != pointDataList.end(); ++it) { 0042 KoPathShape * pathShape = it->pathShape; 0043 0044 KoPathSegment segment = pathShape->segmentByIndex(it->pointIndex); 0045 0046 // should not happen but to be sure 0047 if (! segment.isValid()) 0048 continue; 0049 0050 d->pointDataList.append(*it); 0051 0052 QPair<KoPathSegment, KoPathSegment> splitSegments = segment.splitAt(insertPosition); 0053 0054 KoPathPoint * split1 = splitSegments.first.second(); 0055 KoPathPoint * split2 = splitSegments.second.first(); 0056 KoPathPoint * splitPoint = new KoPathPoint(pathShape, split1->point()); 0057 if(split1->activeControlPoint1()) 0058 splitPoint->setControlPoint1(split1->controlPoint1()); 0059 if(split2->activeControlPoint2()) 0060 splitPoint->setControlPoint2(split2->controlPoint2()); 0061 0062 d->points.append(splitPoint); 0063 QPointF cp1 = splitSegments.first.first()->controlPoint2(); 0064 QPointF cp2 = splitSegments.second.second()->controlPoint1(); 0065 d->controlPoints.append(QPair<QPointF, QPointF>(cp1, cp2)); 0066 } 0067 setText(kundo2_i18n("Insert points")); 0068 } 0069 0070 KoPathPointInsertCommand::~KoPathPointInsertCommand() 0071 { 0072 delete d; 0073 } 0074 0075 void KoPathPointInsertCommand::redo() 0076 { 0077 KUndo2Command::redo(); 0078 for (int i = d->pointDataList.size() - 1; i >= 0; --i) { 0079 KoPathPointData pointData = d->pointDataList.at(i); 0080 KoPathShape * pathShape = pointData.pathShape; 0081 0082 KoPathSegment segment = pathShape->segmentByIndex(pointData.pointIndex); 0083 0084 ++pointData.pointIndex.second; 0085 0086 if (segment.first()->activeControlPoint2()) { 0087 QPointF controlPoint2 = segment.first()->controlPoint2(); 0088 std::swap(controlPoint2, d->controlPoints[i].first); 0089 segment.first()->setControlPoint2(controlPoint2); 0090 } 0091 0092 if (segment.second()->activeControlPoint1()) { 0093 QPointF controlPoint1 = segment.second()->controlPoint1(); 0094 std::swap(controlPoint1, d->controlPoints[i].second); 0095 segment.second()->setControlPoint1(controlPoint1); 0096 } 0097 0098 pathShape->insertPoint(d->points.at(i), pointData.pointIndex); 0099 pathShape->recommendPointSelectionChange({pointData.pointIndex}); 0100 pathShape->update(); 0101 } 0102 d->deletePoints = false; 0103 } 0104 0105 void KoPathPointInsertCommand::undo() 0106 { 0107 KUndo2Command::undo(); 0108 for (int i = 0; i < d->pointDataList.size(); ++i) { 0109 const KoPathPointData &pdBefore = d->pointDataList.at(i); 0110 KoPathShape * pathShape = pdBefore.pathShape; 0111 KoPathPointIndex piAfter = pdBefore.pointIndex; 0112 ++piAfter.second; 0113 0114 KoPathPoint * before = pathShape->pointByIndex(pdBefore.pointIndex); 0115 0116 d->points[i] = pathShape->removePoint(piAfter); 0117 0118 if (d->points[i]->properties() & KoPathPoint::CloseSubpath) { 0119 piAfter.second = 0; 0120 } 0121 0122 KoPathPoint * after = pathShape->pointByIndex(piAfter); 0123 0124 if (before->activeControlPoint2()) { 0125 QPointF controlPoint2 = before->controlPoint2(); 0126 std::swap(controlPoint2, d->controlPoints[i].first); 0127 before->setControlPoint2(controlPoint2); 0128 } 0129 0130 if (after->activeControlPoint1()) { 0131 QPointF controlPoint1 = after->controlPoint1(); 0132 std::swap(controlPoint1, d->controlPoints[i].second); 0133 after->setControlPoint1(controlPoint1); 0134 } 0135 0136 QList<KoPathPointIndex> segmentPoints; 0137 segmentPoints << pdBefore.pointIndex; 0138 0139 KoPathPointIndex nextPoint(pdBefore.pointIndex.first, pdBefore.pointIndex.second + 1); 0140 if (pathShape->pointByIndex(nextPoint)) { 0141 segmentPoints << nextPoint; 0142 } 0143 0144 pathShape->recommendPointSelectionChange(segmentPoints); 0145 pathShape->update(); 0146 } 0147 d->deletePoints = true; 0148 } 0149 0150 QList<KoPathPoint*> KoPathPointInsertCommand::insertedPoints() const 0151 { 0152 return d->points; 0153 }