56#include <klocalizedstring.h>
58#include <QPainterPath>
67 qreal dx =
p1.x()-
p2.x();
68 qreal dy =
p1.y()-
p2.y();
89 , m_pointSelection(this)
112 m_selectCursor = QCursor(QIcon(
":/cursor-needle.svg").pixmap(32), 0, 0);
113 m_moveCursor = QCursor(QIcon(
":/cursor-needle-move.svg").pixmap(32), 0, 0);
127 connect(
this, SIGNAL(
typeChanged(
int)), toolOptions, SLOT(setSelectionType(
int)));
129 connect(toolOptions, SIGNAL(sigRequestUpdateActions()),
this, SLOT(
updateActions()));
131 toolOptions->setWindowTitle(i18n(
"Edit Shape"));
132 list.append(toolOptions);
157 if (initialConversionCommand) {
158 initialConversionCommand->
redo();
164 if (initialConversionCommand) {
167 parent->setText(command->
text());
169 parent->addCommand(command);
173 d->canvas->addCommand(command);
181 if (segments.size() == 1) {
182 qreal positionInSegment = 0.5;
188 d->canvas->addCommand(cmd);
209 d->canvas->addCommand(cmd);
221 for (; it != selectedPoints.constEnd(); ++it) {
222 KoPathPoint *point = it->pathShape->pointByIndex(it->pointIndex);
224 pointToChange.append(*it);
227 if (! pointToChange.isEmpty()) {
242 d->canvas->addCommand(command);
253 for (; it != points.constEnd(); ++it) {
254 KoPathPoint *point = it->pathShape->pointByIndex(it->pointIndex);
256 pointToChange.append(*it);
259 if (!pointToChange.isEmpty()) {
271 if (segments.size() > 0) {
282 if (segments.size() > 0) {
299 parameterShapes.append(parametric);
303 if (!parameterShapes.isEmpty()) {
310 textShapes.append(text);
314 if (!textShapes.isEmpty()) {
316 const QList<KoShape*> oldSelectedShapes = implicitCastList<KoShape*>(textShapes);
329 newSelectedShapes << outlineShape;
357 if (index1.second != 0 && index1.second != path1->
subpathPointCount(index1.first)-1)
361 if (index2.second != 0 && index2.second != path2->
subpathPointCount(index2.first)-1)
376 if (pointData.size() != 2)
return;
381 if (!checkCanJoinToPoints(pd1, pd2)) {
390 cmd =
new KoMultiPathPointJoinCommand(pd1, pd2, d->canvas->shapeController()->documentBase(), d->canvas->shapeManager()->selection());
394 d->canvas->addCommand(cmd);
421 if (segments.size() == 1) {
435 if (segments.size() == 1) {
462 if (!shape->
stroke() || !shape->
stroke()->isVisible()) {
512 d->canvas->snapGuide()->paint(painter, converter,
canvas()->displayRendererInterface());
521 QRectF newDecorationsRect;
547 return newDecorationsRect;
574 if (event->
button() & Qt::LeftButton) {
594 if (shape && !
selection->isSelected(shape)) {
596 if (!(event->
modifiers() & Qt::ShiftModifier)) {
612 if (event->
button() & Qt::RightButton)
633 int handleId = parameterShape->
handleIdAt(roi);
634 if (handleId != -1) {
644 if (! points.empty()) {
648 qreal minDistance = HUGE_VAL;
656 if (
p->activeControlPoint1() && roi.contains(
p->controlPoint1())) {
658 if (dist < minDistance) {
665 if (
p->activeControlPoint2() && roi.contains(
p->controlPoint2())) {
667 if (dist < minDistance) {
676 if (dist < minDistance) {
690 Q_EMIT
statusTextChanged(i18n(
"Drag to move point. Shift click to change point type."));
715 Q_EMIT
statusTextChanged(i18n(
"Drag to change curve directly. Double click to insert new path point."));
720 if (selectedPointCount == 0)
724 if (selectedPointCount == 1)
743 d->canvas->addCommand(command);
757 switch (event->key()) {
758 case Qt::Key_Control:
762 if (! event->isAutoRepeat()) {
775 switch (event->key()) {
796 switch (event->key()) {
797 case Qt::Key_Control:
801 if (! event->isAutoRepeat()) {
825 d->canvas->addCommand(cmd);
841 std::unique_ptr<PathSegment> segment(
new PathSegment);
850 segment->path = shape;
851 segment->segmentStart = s.
first();
856 if (!segment->isValid()) {
860 return segment.release();
869 d->canvas->snapGuide()->reset();
902 d->canvas->selectedShapesProxy()->selection()->selectedEditableShapesAndDelegates();
928 Q_FOREACH (
KoShape *shape, shapes) {
932 selectedShapes.append(pathShape);
948 PathToolOptionWidget::Types type;
964 bool canBreakAtPoint =
false;
966 bool hasNonSmoothPoints =
false;
967 bool hasNonSymmetricPoints =
false;
968 bool hasNonSplitPoints =
false;
970 bool hasNonLinePoints =
false;
971 bool hasNonCurvePoints =
false;
973 bool canJoinSubpaths =
false;
975 if (!pointData.isEmpty()) {
995 if (pointData.size() == 2) {
999 canJoinSubpaths = checkCanJoinToPoints(pd1, pd2);
1020 bool canSplitAtSegment =
false;
1021 bool canConvertSegmentToLine =
false;
1022 bool canConvertSegmentToCurve=
false;
1024 if (!segments.isEmpty()) {
1026 canSplitAtSegment = segments.size() == 1;
1028 bool hasLines =
false;
1029 bool hasCurves =
false;
1033 hasLines |= segment.
degree() == 1;
1034 hasCurves |= segment.
degree() > 1;
1037 canConvertSegmentToLine = !segments.isEmpty() && hasCurves;
1038 canConvertSegmentToCurve= !segments.isEmpty() && hasLines;
1050 bool haveConvertibleShapes =
false;
1057 haveConvertibleShapes =
true;
1075 d->canvas->snapGuide()->reset();
1113void addActionsGroupIfEnabled(QMenu *menu, QAction *a1, QAction *a2)
1115 if (a1->isEnabled() || a2->isEnabled()) {
1116 menu->addAction(a1);
1117 menu->addAction(a2);
1118 menu->addSeparator();
1122void addActionsGroupIfEnabled(QMenu *menu, QAction *a1, QAction *a2, QAction *a3)
1124 if (a1->isEnabled() || a2->isEnabled()) {
1125 menu->addAction(a1);
1126 menu->addAction(a2);
1127 menu->addAction(a3);
1128 menu->addSeparator();
QPair< int, int > KoPathPointIndex
KUndo2MagicString text() const
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void drawPath(const QPainterPath &path)
void setHandleStyle(const KisHandleStyle &style)
static KisHandleStyle & secondarySelection(KisHandlePalette palette=KisHandlePalette())
static KisHandleStyle & primarySelection(KisHandlePalette palette=KisHandlePalette())
void addConnection(Sender sender, Signal signal, Receiver receiver, Method method, Qt::ConnectionType type=Qt::AutoConnection)
QPointer< KoShapeController > shapeController
virtual KoShapeManager * shapeManager() const =0
virtual KoColorDisplayRendererInterface * displayRendererInterface() const
displayRendererInterface The display renderer interface has a number of color conversion functions wh...
virtual void addCommand(KUndo2Command *command)=0
virtual KoSelectedShapesProxy * selectedShapesProxy() const =0
selectedShapesProxy() is a special interface for keeping a persistent connections to selectionChanged...
virtual KisHandlePalette handlePaletteForDisplayColorSpace() const =0
handlePaletteForDisplayColorSpace
void paintHandles(KisHandlePainterHelper &handlesHelper)
Paint the handles.
bool isParametricShape() const
Check if object is a parametric shape.
int handleIdAt(const QRectF &rect) const
Get the id of the handle within the given rect.
The undo / redo command for changing a KoParameterShape into a KoPathShape.
Command to break a subpath at points.
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
The undo / redo command for inserting path points.
QList< KoPathPoint * > insertedPoints() const
Returns list of inserted points.
static KUndo2Command * createCommand(const QList< KoPathPointData > &pointDataList, KoShapeController *shapeController, KUndo2Command *parent=0)
Create command for removing points from path shapes.
Strategy to rubber select points of a path shape.
The undo / redo command for changing the path point type.
PointType
The type of the point.
A KoPathPoint represents a point in a path.
PointProperties properties
QRectF boundingRect(bool active=true) const
Get the bounding rect of the point.
@ IsSmooth
it is smooth, both control points on a line through the point
@ IsSymmetric
it is symmetric, like smooth but control points have same distance to point
PointType
the type for identifying part of a KoPathPoint
@ ControlPoint2
the second control point
@ ControlPoint1
the first control point
The undo / redo command for breaking a subpath by removing the segment.
Strategy for deforming a segment of a path shape.
The undo / redo command for changing segments to curves/lines.
A KoPathSegment consist of two neighboring KoPathPoints.
int degree() const
Returns the degree of the segment: 1 = line, 2 = quadratic, 3 = cubic, -1 = invalid.
qreal nearestPoint(const QPointF &point) const
bool isValid() const
Returns if segment is valid, e.g. has two valid points.
QRectF boundingRect() const
Returns the axis aligned tight bounding rect.
KoPathSegment toCubic() const
Returns cubic bezier curve segment of this segment.
The position of a path point within a path shape.
int subpathPointCount(int subpathIndex) const
Returns the number of points in a subpath.
bool isClosedSubpath(int subpathIndex) const
Checks if a subpath is closed.
KoPathSegment segmentAtPoint(const QPointF &point, const QRectF &grabRoi) const
QList< KoPathPoint * > pointsAt(const QRectF &rect, const bool useControlPoints=false) const
Returns the path points within the given rectangle.
QPainterPath outline() const override
reimplemented
KoPathSegment segmentByIndex(const KoPathPointIndex &pointIndex) const
Returns the segment specified by a path point index.
virtual void paintPoints(KisHandlePainterHelper &handlesHelper)
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.
Qt::MouseButton button() const
return button pressed (see QMouseEvent::button());
bool isTouchEvent() const
Qt::KeyboardModifiers modifiers() const
QPointF point
The point in document coordinates.
virtual KoSelection * selection()=0
void connectToCanvas(KoCanvasBase *canvas)
KoShape * shapeAt(const QPointF &position, KoFlake::ShapeSelection selection=KoFlake::ShapeOnTop, bool omitHiddenShapes=true)
virtual bool isShapeEditable(bool recursive=true) const
checks recursively if the shape or one of its parents is not visible or locked
virtual KoShapeStrokeModelSP stroke() const
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
virtual QRectF boundingRect() const
Get the bounding box of the shape.
KoShapeContainer * parent() const
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
The KoSvgTextShapeOutlineHelper class helper class that draws the text outlines and contour mode butt...
KoShape * textOutline() const
textOutline This turns the text object into non-text KoShape(s) to the best of its abilities.
virtual QPointF documentToView(const QPointF &documentPoint) const
KoPathPoint * activePoint() const
KoPathPoint::PointType activePointType() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_RETURN(cond)
T kisGrowRect(const T &rect, U offset)
KUndo2MagicString kundo2_i18n(const char *text)
@ DecorationThickness
Integer, the thickness of single px decorations, will be adjusted by HiDPI settings....
@ HandleRadius
The handle radius used for drawing handles of any kind.
@ ShapeOnTop
return the shape highest z-ordering, regardless of selection.
rgba palette[MAX_PALETTE]