55#include <klocalizedstring.h>
57#include <QPainterPath>
66 qreal dx =
p1.x()-
p2.x();
67 qreal dy =
p1.y()-
p2.y();
88 , m_pointSelection(this)
111 m_selectCursor = QCursor(QIcon(
":/cursor-needle.svg").pixmap(32), 0, 0);
112 m_moveCursor = QCursor(QIcon(
":/cursor-needle-move.svg").pixmap(32), 0, 0);
126 connect(
this, SIGNAL(
typeChanged(
int)), toolOptions, SLOT(setSelectionType(
int)));
128 connect(toolOptions, SIGNAL(sigRequestUpdateActions()),
this, SLOT(
updateActions()));
130 toolOptions->setWindowTitle(i18n(
"Edit Shape"));
131 list.append(toolOptions);
156 if (initialConversionCommand) {
157 initialConversionCommand->
redo();
163 if (initialConversionCommand) {
166 parent->setText(command->
text());
168 parent->addCommand(command);
172 d->canvas->addCommand(command);
180 if (segments.size() == 1) {
181 qreal positionInSegment = 0.5;
187 d->canvas->addCommand(cmd);
208 d->canvas->addCommand(cmd);
220 for (; it != selectedPoints.constEnd(); ++it) {
221 KoPathPoint *point = it->pathShape->pointByIndex(it->pointIndex);
223 pointToChange.append(*it);
226 if (! pointToChange.isEmpty()) {
241 d->canvas->addCommand(command);
252 for (; it != points.constEnd(); ++it) {
253 KoPathPoint *point = it->pathShape->pointByIndex(it->pointIndex);
255 pointToChange.append(*it);
258 if (!pointToChange.isEmpty()) {
270 if (segments.size() > 0) {
281 if (segments.size() > 0) {
298 parameterShapes.append(parametric);
302 if (!parameterShapes.isEmpty()) {
309 textShapes.append(text);
313 if (!textShapes.isEmpty()) {
315 const QList<KoShape*> oldSelectedShapes = implicitCastList<KoShape*>(textShapes);
328 newSelectedShapes << outlineShape;
356 if (index1.second != 0 && index1.second != path1->
subpathPointCount(index1.first)-1)
360 if (index2.second != 0 && index2.second != path2->
subpathPointCount(index2.first)-1)
375 if (pointData.size() != 2)
return;
380 if (!checkCanJoinToPoints(pd1, pd2)) {
389 cmd =
new KoMultiPathPointJoinCommand(pd1, pd2, d->canvas->shapeController()->documentBase(), d->canvas->shapeManager()->selection());
393 d->canvas->addCommand(cmd);
420 if (segments.size() == 1) {
434 if (segments.size() == 1) {
459 if (!shape->
stroke() || !shape->
stroke()->isVisible()) {
509 d->canvas->snapGuide()->paint(painter, converter);
518 QRectF newDecorationsRect;
544 return newDecorationsRect;
571 if (event->
button() & Qt::LeftButton) {
591 if (shape && !
selection->isSelected(shape)) {
593 if (!(event->
modifiers() & Qt::ShiftModifier)) {
609 if (event->
button() & Qt::RightButton)
630 int handleId = parameterShape->
handleIdAt(roi);
631 if (handleId != -1) {
641 if (! points.empty()) {
645 qreal minDistance = HUGE_VAL;
653 if (
p->activeControlPoint1() && roi.contains(
p->controlPoint1())) {
655 if (dist < minDistance) {
662 if (
p->activeControlPoint2() && roi.contains(
p->controlPoint2())) {
664 if (dist < minDistance) {
673 if (dist < minDistance) {
687 Q_EMIT
statusTextChanged(i18n(
"Drag to move point. Shift click to change point type."));
712 Q_EMIT
statusTextChanged(i18n(
"Drag to change curve directly. Double click to insert new path point."));
717 if (selectedPointCount == 0)
721 if (selectedPointCount == 1)
740 d->canvas->addCommand(command);
754 switch (event->key()) {
755 case Qt::Key_Control:
759 if (! event->isAutoRepeat()) {
772 switch (event->key()) {
793 switch (event->key()) {
794 case Qt::Key_Control:
798 if (! event->isAutoRepeat()) {
822 d->canvas->addCommand(cmd);
838 QScopedPointer<PathSegment> segment(
new PathSegment);
847 segment->path = shape;
848 segment->segmentStart = s.
first();
853 if (!segment->isValid()) {
857 return segment.take();
866 d->canvas->snapGuide()->reset();
899 d->canvas->selectedShapesProxy()->selection()->selectedEditableShapesAndDelegates();
925 Q_FOREACH (
KoShape *shape, shapes) {
929 selectedShapes.append(pathShape);
945 PathToolOptionWidget::Types type;
961 bool canBreakAtPoint =
false;
963 bool hasNonSmoothPoints =
false;
964 bool hasNonSymmetricPoints =
false;
965 bool hasNonSplitPoints =
false;
967 bool hasNonLinePoints =
false;
968 bool hasNonCurvePoints =
false;
970 bool canJoinSubpaths =
false;
972 if (!pointData.isEmpty()) {
992 if (pointData.size() == 2) {
996 canJoinSubpaths = checkCanJoinToPoints(pd1, pd2);
1017 bool canSplitAtSegment =
false;
1018 bool canConvertSegmentToLine =
false;
1019 bool canConvertSegmentToCurve=
false;
1021 if (!segments.isEmpty()) {
1023 canSplitAtSegment = segments.size() == 1;
1025 bool hasLines =
false;
1026 bool hasCurves =
false;
1030 hasLines |= segment.
degree() == 1;
1031 hasCurves |= segment.
degree() > 1;
1034 canConvertSegmentToLine = !segments.isEmpty() && hasCurves;
1035 canConvertSegmentToCurve= !segments.isEmpty() && hasLines;
1047 bool haveConvertibleShapes =
false;
1054 haveConvertibleShapes =
true;
1072 d->canvas->snapGuide()->reset();
1110void addActionsGroupIfEnabled(QMenu *menu, QAction *a1, QAction *a2)
1112 if (a1->isEnabled() || a2->isEnabled()) {
1113 menu->addAction(a1);
1114 menu->addAction(a2);
1115 menu->addSeparator();
1119void addActionsGroupIfEnabled(QMenu *menu, QAction *a1, QAction *a2, QAction *a3)
1121 if (a1->isEnabled() || a2->isEnabled()) {
1122 menu->addAction(a1);
1123 menu->addAction(a2);
1124 menu->addAction(a3);
1125 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()
static KisHandleStyle & primarySelection()
void addConnection(Sender sender, Signal signal, Receiver receiver, Method method, Qt::ConnectionType type=Qt::AutoConnection)
QPointer< KoShapeController > shapeController
virtual KoShapeManager * shapeManager() const =0
virtual void addCommand(KUndo2Command *command)=0
virtual KoSelectedShapesProxy * selectedShapesProxy() const =0
selectedShapesProxy() is a special interface for keeping a persistent connections to selectionChanged...
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.