Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPencilTool Class Reference

#include <KoPencilTool.h>

+ Inheritance diagram for KoPencilTool:

Public Member Functions

void activate (const QSet< KoShape * > &shapes) override
 
void deactivate () override
 
void keyPressEvent (QKeyEvent *event) override
 
 KoPencilTool (KoCanvasBase *canvas)
 
void mouseMoveEvent (KoPointerEvent *event) override
 
void mousePressEvent (KoPointerEvent *event) override
 
void mouseReleaseEvent (KoPointerEvent *event) override
 
void paint (QPainter &painter, const KoViewConverter &converter) override
 
 ~KoPencilTool () override
 
- Public Member Functions inherited from KoToolBase
QAction * action (const QString &name) const
 
KoCanvasBasecanvas () const
 Returns the canvas the tool is working on.
 
virtual void copy () const
 
QCursor cursor () const
 return the last emitted cursor
 
virtual void customMoveEvent (KoPointerEvent *event)
 
virtual void customPressEvent (KoPointerEvent *event)
 
virtual void customReleaseEvent (KoPointerEvent *event)
 
virtual void cut ()
 
virtual QRectF decorationsRect () const
 
int decorationThickness () const
 decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen magnification, thus the HiDPI settings. Note: to use this effectively, also set the pen to isCosmetic(true);
 
virtual void deleteSelection ()
 
virtual void deselect ()
 deselect the tool should clear the selection if it has one.
 
virtual void dragLeaveEvent (QDragLeaveEvent *event)
 
virtual void dragMoveEvent (QDragMoveEvent *event, const QPointF &point)
 
virtual void dropEvent (QDropEvent *event, const QPointF &point)
 
virtual void explicitUserStrokeEndRequest ()
 explicitUserStrokeEndRequest is called by the input manager when the user presses Enter key or any equivalent. This callback comes before requestStrokeEnd(), which comes from a different source.
 
KoToolFactoryBasefactory () const
 
virtual void focusInEvent (QFocusEvent *event)
 
virtual void focusOutEvent (QFocusEvent *event)
 
virtual bool hasSelection ()
 
virtual void inputMethodEvent (QInputMethodEvent *event)
 
virtual QVariant inputMethodQuery (Qt::InputMethodQuery query) const
 
bool isInTextMode () const
 
bool isOpacityPresetMode () const
 
virtual void keyReleaseEvent (QKeyEvent *event)
 
 KoToolBase (KoCanvasBase *canvas)
 
bool maskSyntheticEvents () const
 
virtual void mouseDoubleClickEvent (KoPointerEvent *event)
 
virtual void mouseTripleClickEvent (KoPointerEvent *event)
 
QList< QPointer< QWidget > > optionWidgets ()
 
virtual bool paste ()
 
virtual QMenu * popupActionsMenu ()
 
virtual KisPopupWidgetInterfacepopupWidget ()
 
virtual bool selectAll ()
 selectAll select all data the tool can select.
 
virtual KoToolSelectionselection ()
 
Q_INVOKABLE QString toolId () const
 
virtual bool wantsAutoScroll () const
 
 ~KoToolBase () override
 

Protected Slots

virtual void slotUpdatePencilCursor ()
 

Protected Member Functions

virtual void addPathShape (KoPathShape *path, bool closePath)
 
QList< QPointer< QWidget > > createOptionWidgets () override
 
KoShapeStrokeSP createStroke ()
 
qreal getFittingError ()
 
KoPathShapepath ()
 
void setFittingError (qreal fittingError)
 
- Protected Member Functions inherited from KoToolBase
virtual QWidget * createOptionWidget ()
 
int grabSensitivity () const
 Convenience function to get the current grab sensitivity.
 
qreal handleDocRadius () const
 
QRectF handleGrabRect (const QPointF &position) const
 
QRectF handlePaintRect (const QPointF &position) const
 
int handleRadius () const
 Convenience function to get the current handle radius.
 
bool isActivated () const
 
 KoToolBase (KoToolBasePrivate &dd)
 
KoPointerEventlastDeliveredPointerEvent () const
 
void setAbstractResource (KoAbstractCanvasResourceInterfaceSP abstractResource)
 
void setConverter (KoDerivedResourceConverterSP converter)
 
void setIsOpacityPresetMode (bool value)
 
void setMaskSyntheticEvents (bool value)
 
void setTextMode (bool value)
 
QHash< int, KoAbstractCanvasResourceInterfaceSPtoolAbstractResources ()
 
QHash< int, KoDerivedResourceConverterSPtoolConverters ()
 
void useCursor (const QCursor &cursor)
 

Private Types

enum  PencilMode { ModeRaw , ModeCurve , ModeStraight }
 

Private Slots

void selectMode (int mode)
 
void setDelta (double delta)
 
void setOptimize (int state)
 

Private Member Functions

void addPoint (const QPointF &point)
 
bool connectPaths (KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd)
 Connects given path with the ones we hit when starting/finishing.
 
KoPathPointendPointAtPosition (const QPointF &position)
 returns the nearest existing path point
 
void finish (bool closePath)
 
qreal lineAngle (const QPointF &p1, const QPointF &p2)
 

Private Attributes

bool m_close {false}
 
qreal m_combineAngle {15.0}
 
KConfigGroup m_configGroup
 
KoPathPointm_existingEndPoint {0}
 an existing path point we finished a new path at
 
KoPathPointm_existingStartPoint {0}
 an existing path point we started a new path at
 
qreal m_fittingError {5.0}
 
KoPathPointm_hoveredPoint {0}
 an existing path end point the mouse is hovering on
 
PencilMode m_mode {ModeCurve}
 
bool m_optimizeCurve {false}
 
bool m_optimizeRaw {false}
 
QList< QPointF > m_points
 
KoPathShapem_shape {0}
 
KoStrokeConfigWidgetm_strokeWidget {0}
 

Additional Inherited Members

- Public Slots inherited from KoToolBase
virtual void canvasResourceChanged (int key, const QVariant &res)
 
virtual void documentResourceChanged (int key, const QVariant &res)
 
virtual void repaintDecorations ()
 
virtual void requestRedoDuringStroke ()
 
virtual void requestStrokeCancellation ()
 
virtual void requestStrokeEnd ()
 
virtual void requestUndoDuringStroke ()
 
void setStatusText (const QString &statusText)
 
void updateOptionsWidgetIcons ()
 
- Signals inherited from KoToolBase
void activateTool (const QString &id)
 
void cursorChanged (const QCursor &cursor)
 
void selectionChanged (bool hasSelection)
 
void statusTextChanged (const QString &statusText)
 
void textModeChanged (bool inTextMode)
 
- Protected Attributes inherited from KoToolBase
KoToolBasePrivated_ptr
 

Detailed Description

Definition at line 21 of file KoPencilTool.h.

Member Enumeration Documentation

◆ PencilMode

Enumerator
ModeRaw 
ModeCurve 
ModeStraight 

Definition at line 73 of file KoPencilTool.h.

Constructor & Destructor Documentation

◆ KoPencilTool()

KoPencilTool::KoPencilTool ( KoCanvasBase * canvas)
explicit

Definition at line 43 of file KoPencilTool.cpp.

45{
46}
KoCanvasBase * canvas() const
Returns the canvas the tool is working on.

◆ ~KoPencilTool()

KoPencilTool::~KoPencilTool ( )
override

Definition at line 48 of file KoPencilTool.cpp.

49{
50}

Member Function Documentation

◆ activate()

void KoPencilTool::activate ( const QSet< KoShape * > & shapes)
overridevirtual

This method is called when this tool instance is activated. For any main window there is only one tool active at a time, which then gets all user input. Switching between tools will call deactivate on one and activate on the new tool allowing the tool to flush items (like a selection) when it is not in use.

Parameters
shapesthe set of shapes that are selected or suggested for editing by a selected shape for the tool to work on. Not all shapes will be meant for this tool.
See also
deactivate()

Reimplemented from KoToolBase.

Definition at line 156 of file KoPencilTool.cpp.

157{
158 KoToolBase::activate(shapes);
159
160 m_points.clear();
161 m_close = false;
163
164 if (m_strokeWidget) {
166 }
167 m_configGroup = KSharedConfig::openConfig()->group(toolId());
168}
QList< QPointF > m_points
virtual void slotUpdatePencilCursor()
KoStrokeConfigWidget * m_strokeWidget
KConfigGroup m_configGroup
Q_INVOKABLE QString toolId() const
virtual void activate(const QSet< KoShape * > &shapes)

References KoStrokeConfigWidget::activate(), KoToolBase::activate(), m_close, m_configGroup, m_points, m_strokeWidget, slotUpdatePencilCursor(), and KoToolBase::toolId().

◆ addPathShape()

void KoPencilTool::addPathShape ( KoPathShape * path,
bool closePath )
protectedvirtual

Add path shape to document. This method can be overridden and change the behaviour of the tool. In that case the subclass takes ownership of pathShape. It gets only called, if there are two or more points in the path.

Reimplemented in __KisToolPencilLocalTool.

Definition at line 369 of file KoPencilTool.cpp.

370{
371 KoShape * startShape = 0;
372 KoShape * endShape = 0;
373
374 if (closePath) {
375 path->close();
376 path->normalize();
377 } else {
378 path->normalize();
381 startShape = m_existingStartPoint->parent();
383 endShape = m_existingEndPoint->parent();
384 }
385 }
386
387 KUndo2Command * cmd = canvas()->shapeController()->addShape(path, 0);
388 if (cmd) {
390 selection->deselectAll();
391 selection->select(path);
392
393 if (startShape)
394 canvas()->shapeController()->removeShape(startShape, cmd);
395 if (endShape && startShape != endShape)
396 canvas()->shapeController()->removeShape(endShape, cmd);
397
398 canvas()->addCommand(cmd);
399 } else {
400 canvas()->updateCanvas(path->boundingRect());
401 delete path;
402 }
403}
QPointer< KoShapeController > shapeController
virtual KoShapeManager * shapeManager() const =0
virtual void updateCanvas(const QRectF &rc)=0
virtual void addCommand(KUndo2Command *command)=0
KoPathShape * parent() const
Get the path shape the point belongs to.
bool connectPaths(KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd)
Connects given path with the ones we hit when starting/finishing.
KoPathPoint * m_existingEndPoint
an existing path point we finished a new path at
KoPathShape * path()
KoPathPoint * m_existingStartPoint
an existing path point we started a new path at
KoSelection * selection
virtual KoToolSelection * selection()

References KoCanvasBase::addCommand(), KoToolBase::canvas(), connectPaths(), m_existingEndPoint, m_existingStartPoint, KoPathPoint::parent(), path(), KoShapeManager::selection, KoToolBase::selection(), KoCanvasBase::shapeController, KoCanvasBase::shapeManager(), and KoCanvasBase::updateCanvas().

◆ addPoint()

void KoPencilTool::addPoint ( const QPointF & point)
private

Definition at line 192 of file KoPencilTool.cpp.

193{
194 if (! m_shape)
195 return;
196
197 // do a moveTo for the first point added
198 if (m_points.empty())
199 m_shape->moveTo(point);
200 // do not allow coincident points
201 else if (point != m_points.last())
202 m_shape->lineTo(point);
203 else
204 return;
205
206 m_points.append(point);
208}
KoPathPoint * lineTo(const QPointF &p)
Adds a new line segment.
KoPathPoint * moveTo(const QPointF &p)
Starts a new Subpath.
QRectF boundingRect() const override
reimplemented
KoPathShape * m_shape

References KoPathShape::boundingRect(), KoToolBase::canvas(), KoPathShape::lineTo(), m_points, m_shape, KoPathShape::moveTo(), and KoCanvasBase::updateCanvas().

◆ connectPaths()

bool KoPencilTool::connectPaths ( KoPathShape * pathShape,
KoPathPoint * pointAtStart,
KoPathPoint * pointAtEnd )
private

Connects given path with the ones we hit when starting/finishing.

Definition at line 491 of file KoPencilTool.cpp.

492{
493 // at least one point must be valid
494 if (!pointAtStart && !pointAtEnd)
495 return false;
496 // do not allow connecting to the same point twice
497 if (pointAtStart == pointAtEnd)
498 pointAtEnd = 0;
499
500 // we have hit an existing path point on start/finish
501 // what we now do is:
502 // 1. combine the new created path with the ones we hit on start/finish
503 // 2. merge the endpoints of the corresponding subpaths
504
505 uint newPointCount = pathShape->subpathPointCount(0);
506 KoPathPointIndex newStartPointIndex(0, 0);
507 KoPathPointIndex newEndPointIndex(0, newPointCount - 1);
508 KoPathPoint * newStartPoint = pathShape->pointByIndex(newStartPointIndex);
509 KoPathPoint * newEndPoint = pathShape->pointByIndex(newEndPointIndex);
510
511 KoPathShape * startShape = pointAtStart ? pointAtStart->parent() : 0;
512 KoPathShape * endShape = pointAtEnd ? pointAtEnd->parent() : 0;
513
514 // combine with the path we hit on start
515 KoPathPointIndex startIndex(-1, -1);
516 if (pointAtStart) {
517 startIndex = startShape->pathPointIndex(pointAtStart);
518 pathShape->combine(startShape);
519 pathShape->moveSubpath(0, pathShape->subpathCount() - 1);
520 }
521 // combine with the path we hit on finish
522 KoPathPointIndex endIndex(-1, -1);
523 if (pointAtEnd) {
524 endIndex = endShape->pathPointIndex(pointAtEnd);
525 if (endShape != startShape) {
526 endIndex.first += pathShape->subpathCount();
527 pathShape->combine(endShape);
528 }
529 }
530 // do we connect twice to a single subpath ?
531 bool connectToSingleSubpath = (startShape == endShape && startIndex.first == endIndex.first);
532
533 if (startIndex.second == 0 && !connectToSingleSubpath) {
534 pathShape->reverseSubpath(startIndex.first);
535 startIndex.second = pathShape->subpathPointCount(startIndex.first) - 1;
536 }
537 if (endIndex.second > 0 && !connectToSingleSubpath) {
538 pathShape->reverseSubpath(endIndex.first);
539 endIndex.second = 0;
540 }
541
542 // after combining we have a path where with the subpaths in the following
543 // order:
544 // 1. the subpaths of the pathshape we started the new path at
545 // 2. the subpath we just created
546 // 3. the subpaths of the pathshape we finished the new path at
547
548 // get the path points we want to merge, as these are not going to
549 // change while merging
550 KoPathPoint * existingStartPoint = pathShape->pointByIndex(startIndex);
551 KoPathPoint * existingEndPoint = pathShape->pointByIndex(endIndex);
552
553 // merge first two points
554 if (existingStartPoint) {
555 KoPathPointData pd1(pathShape, pathShape->pathPointIndex(existingStartPoint));
556 KoPathPointData pd2(pathShape, pathShape->pathPointIndex(newStartPoint));
557 KoPathPointMergeCommand cmd1(pd1, pd2);
558 cmd1.redo();
559 }
560 // merge last two points
561 if (existingEndPoint) {
562 KoPathPointData pd3(pathShape, pathShape->pathPointIndex(newEndPoint));
563 KoPathPointData pd4(pathShape, pathShape->pathPointIndex(existingEndPoint));
564 KoPathPointMergeCommand cmd2(pd3, pd4);
565 cmd2.redo();
566 }
567
568 return true;
569}
unsigned int uint
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
Describe a KoPathPoint by a KoPathShape and its indices.
The undo / redo command for merging two subpath end points.
A KoPathPoint represents a point in a path.
The position of a path point within a path shape.
Definition KoPathShape.h:63
int subpathPointCount(int subpathIndex) const
Returns the number of points in a subpath.
bool reverseSubpath(int subpathIndex)
Reverse subpath.
bool moveSubpath(int oldSubpathIndex, int newSubpathIndex)
Moves the position of a subpath within a path.
int subpathCount() const
Returns the number of subpaths in the path.
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.
int combine(KoPathShape *path)
Combines two path shapes by appending the data of the specified path.

References KoPathShape::combine(), KoPathShape::moveSubpath(), KoPathPoint::parent(), KoPathShape::pathPointIndex(), KoPathShape::pointByIndex(), KoPathPointMergeCommand::redo(), KoPathShape::reverseSubpath(), KoPathShape::subpathCount(), and KoPathShape::subpathPointCount().

◆ createOptionWidgets()

QList< QPointer< QWidget > > KoPencilTool::createOptionWidgets ( )
overrideprotectedvirtual

Reimplemented from KoToolBase.

Definition at line 280 of file KoPencilTool.cpp.

281{
282 m_mode = static_cast<PencilMode>(m_configGroup.readEntry<int>("pencilMode", m_mode));
283 m_optimizeRaw = m_configGroup.readEntry<bool>("optimizeRaw", m_optimizeRaw);
284 m_optimizeCurve = m_configGroup.readEntry<bool>("optimizeCurve", m_optimizeCurve);
285 m_combineAngle = m_configGroup.readEntry<qreal>("combineAngle", m_combineAngle);
286 m_fittingError = m_configGroup.readEntry<qreal>("fittingError", m_fittingError);
287
288 QList<QPointer<QWidget> > widgets;
289 QWidget *optionWidget = new QWidget();
290 QVBoxLayout * layout = new QVBoxLayout(optionWidget);
291
292 QHBoxLayout *modeLayout = new QHBoxLayout;
293 modeLayout->setSpacing(3);
294 QLabel *modeLabel = new QLabel(i18n("Precision:"), optionWidget);
295 QComboBox * modeBox = new QComboBox(optionWidget);
296 modeBox->addItem(i18nc("The raw line data", "Raw"));
297 modeBox->addItem(i18n("Curve"));
298 modeBox->addItem(i18n("Straight"));
299 modeLayout->addWidget(modeLabel);
300 modeLayout->addWidget(modeBox, 1);
301 layout->addLayout(modeLayout);
302
303 QStackedWidget * stackedWidget = new QStackedWidget(optionWidget);
304
305 QWidget * rawBox = new QWidget(stackedWidget);
306 QVBoxLayout * rawLayout = new QVBoxLayout(rawBox);
307 QCheckBox * optimizeRaw = new QCheckBox(i18n("Optimize"), rawBox);
308 optimizeRaw->setChecked(m_optimizeRaw);
309 rawLayout->addWidget(optimizeRaw);
310 rawLayout->setContentsMargins(0, 0, 0, 0);
311
312 QWidget * curveBox = new QWidget(stackedWidget);
313 QHBoxLayout * curveLayout = new QHBoxLayout(curveBox);
314 QCheckBox * optimizeCurve = new QCheckBox(i18n("Optimize"), curveBox);
315 optimizeCurve->setChecked(m_optimizeCurve);
316 QDoubleSpinBox * fittingError = new KisDoubleParseSpinBox(curveBox);
317 fittingError->setSingleStep(0.50);
318 fittingError->setMaximum(400.0);
319 fittingError->setMinimum(0.0);
320 fittingError->setValue(m_fittingError);
321 fittingError->setToolTip(i18n("Exactness:"));
322 curveLayout->addWidget(optimizeCurve);
323 curveLayout->addWidget(fittingError);
324 curveLayout->setContentsMargins(0, 0, 0, 0);
325
326 QWidget *straightBox = new QWidget(stackedWidget);
327 QVBoxLayout *straightLayout = new QVBoxLayout(straightBox);
328 QDoubleSpinBox *combineAngle = new KisDoubleParseSpinBox(straightBox);
329 combineAngle->setSingleStep(0.50);
330 combineAngle->setMaximum(360.0);
331 combineAngle->setMinimum(0.0);
332 combineAngle->setValue(m_combineAngle);
333 combineAngle->setSuffix(" deg");
334 // QT5TODO
335 //combineAngle->setLabel(i18n("Combine angle:"), Qt::AlignLeft | Qt::AlignVCenter);
336 straightLayout->addWidget(combineAngle);
337 straightLayout->setContentsMargins(0, 0, 0, 0);
338
339 stackedWidget->addWidget(rawBox);
340 stackedWidget->addWidget(curveBox);
341 stackedWidget->addWidget(straightBox);
342 layout->addWidget(stackedWidget);
343 layout->addStretch(1);
344
345 connect(modeBox, SIGNAL(activated(int)), stackedWidget, SLOT(setCurrentIndex(int)));
346 connect(modeBox, SIGNAL(activated(int)), this, SLOT(selectMode(int)));
347 connect(optimizeRaw, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
348 connect(optimizeCurve, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
349 connect(fittingError, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
350 connect(combineAngle, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
351
352 modeBox->setCurrentIndex(m_mode);
353 stackedWidget->setCurrentIndex(m_mode);
354 optionWidget->setObjectName(i18n("Pencil"));
355 optionWidget->setWindowTitle(i18n("Pencil"));
356 widgets.append(optionWidget);
357
360 m_strokeWidget->setWindowTitle(i18n("Line"));
361 connect(m_strokeWidget, SIGNAL(sigStrokeChanged()), SLOT(slotUpdatePencilCursor()));
362 if (isActivated()) {
364 }
365 widgets.append(m_strokeWidget);
366 return widgets;
367}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
The KisDoubleParseSpinBox class is a cleverer doubleSpinBox, able to parse arithmetic expressions.
void setDelta(double delta)
void selectMode(int mode)
qreal m_fittingError
PencilMode m_mode
bool m_optimizeCurve
void setOptimize(int state)
qreal m_combineAngle
A widget for configuring the stroke of a shape.
void setNoSelectionTrackingMode(bool value)
bool isActivated() const

References KoStrokeConfigWidget::activate(), KoToolBase::canvas(), connect(), KoToolBase::isActivated(), m_combineAngle, m_configGroup, m_fittingError, m_mode, m_optimizeCurve, m_optimizeRaw, m_strokeWidget, selectMode(), setDelta(), KoStrokeConfigWidget::setNoSelectionTrackingMode(), setOptimize(), and slotUpdatePencilCursor().

◆ createStroke()

KoShapeStrokeSP KoPencilTool::createStroke ( )
protected

Definition at line 435 of file KoPencilTool.cpp.

436{
437 KoShapeStrokeSP stroke;
438 if (m_strokeWidget) {
440 }
441 return stroke;
442}
KoShapeStrokeSP createShapeStroke()

References KoStrokeConfigWidget::createShapeStroke(), and m_strokeWidget.

◆ deactivate()

void KoPencilTool::deactivate ( )
overridevirtual

This method is called whenever this tool is no longer the active tool

See also
activate()

Reimplemented from KoToolBase.

Definition at line 170 of file KoPencilTool.cpp.

171{
172 m_points.clear();
173 delete m_shape;
174 m_shape = 0;
177 m_hoveredPoint = 0;
178
179 if (m_strokeWidget) {
181 }
182
184}
KoPathPoint * m_hoveredPoint
an existing path end point the mouse is hovering on
virtual void deactivate()

References KoToolBase::deactivate(), KoStrokeConfigWidget::deactivate(), m_existingEndPoint, m_existingStartPoint, m_hoveredPoint, m_points, m_shape, and m_strokeWidget.

◆ endPointAtPosition()

KoPathPoint * KoPencilTool::endPointAtPosition ( const QPointF & position)
private

returns the nearest existing path point

Definition at line 449 of file KoPencilTool.cpp.

450{
451 QRectF roi = handleGrabRect(position);
452 QList<KoShape *> shapes = canvas()->shapeManager()->shapesAt(roi);
453
455 qreal minDistance = HUGE_VAL;
456 qreal maxDistance = canvas()->viewConverter()->viewToDocumentX(grabSensitivity());
457
458 Q_FOREACH(KoShape * shape, shapes) {
459 KoPathShape * path = dynamic_cast<KoPathShape*>(shape);
460 if (!path)
461 continue;
462 KoParameterShape *paramShape = dynamic_cast<KoParameterShape*>(shape);
463 if (paramShape && paramShape->isParametricShape())
464 continue;
465
466 KoPathPoint * p = 0;
467 uint subpathCount = path->subpathCount();
468 for (uint i = 0; i < subpathCount; ++i) {
469 if (path->isClosedSubpath(i))
470 continue;
471 p = path->pointByIndex(KoPathPointIndex(i, 0));
472 // check start of subpath
473 qreal d = squareDistance(position, path->shapeToDocument(p->point()));
474 if (d < minDistance && d < maxDistance) {
475 nearestPoint = p;
476 minDistance = d;
477 }
478 // check end of subpath
479 p = path->pointByIndex(KoPathPointIndex(i, path->subpathPointCount(i) - 1));
480 d = squareDistance(position, path->shapeToDocument(p->point()));
481 if (d < minDistance && d < maxDistance) {
482 nearestPoint = p;
483 minDistance = d;
484 }
485 }
486 }
487
488 return nearestPoint;
489}
const Params2D p
qreal squareDistance(const QPointF &p1, const QPointF &p2)
virtual const KoViewConverter * viewConverter() const =0
bool isParametricShape() const
Check if object is a parametric shape.
QList< KoShape * > shapesAt(const QRectF &rect, bool omitHiddenShapes=true, bool containedMode=false)
int grabSensitivity() const
Convenience function to get the current grab sensitivity.
QRectF handleGrabRect(const QPointF &position) const
virtual qreal viewToDocumentX(qreal viewX) const
qreal nearestPoint(const QList< QPointF > controlPoints, const QPointF &point, qreal *resultDistance, QPointF *resultPoint)

References KoToolBase::canvas(), KoToolBase::grabSensitivity(), KoToolBase::handleGrabRect(), KoParameterShape::isParametricShape(), p, KoCanvasBase::shapeManager(), KoShapeManager::shapesAt(), squareDistance(), KoCanvasBase::viewConverter(), and KoViewConverter::viewToDocumentX().

◆ finish()

void KoPencilTool::finish ( bool closePath)
private

Definition at line 219 of file KoPencilTool.cpp.

220{
221 if (m_points.count() < 2)
222 return;
223
224 KoPathShape * path = 0;
225 QList<QPointF> complete;
226 QList<QPointF> *points = &m_points;
227
229 float combineAngle;
230
231 if (m_mode == ModeStraight)
232 combineAngle = m_combineAngle;
233 else
234 combineAngle = 0.50f;
235
236 //Add the first two points
237 complete.append(m_points[0]);
238 complete.append(m_points[1]);
239
240 //Now we need to get the angle of the first line
241 float lastAngle = lineAngle(complete[0], complete[1]);
242
243 uint pointCount = m_points.count();
244 for (uint i = 2; i < pointCount; ++i) {
245 float angle = lineAngle(complete.last(), m_points[i]);
246 if (qAbs(angle - lastAngle) < combineAngle)
247 complete.removeLast();
248 complete.append(m_points[i]);
249 lastAngle = angle;
250 }
251
252 m_points.clear();
253 points = &complete;
254 }
255
256 switch (m_mode) {
257 case ModeCurve: {
258 path = bezierFit(*points, m_fittingError);
259 }
260 break;
261 case ModeStraight:
262 case ModeRaw: {
263 path = new KoPathShape();
264 uint pointCount = points->count();
265 path->moveTo(points->at(0));
266 for (uint i = 1; i < pointCount; ++i)
267 path->lineTo(points->at(i));
268 }
269 break;
270 }
271
272 if (! path)
273 return;
274
275 path->setShapeId(KoPathShapeId);
276 path->setStroke(createStroke());
277 addPathShape(path, closePath);
278}
KoPathShape * bezierFit(const QList< QPointF > &points, float error)
#define KoPathShapeId
Definition KoPathShape.h:20
KoShapeStrokeSP createStroke()
virtual void addPathShape(KoPathShape *path, bool closePath)
qreal lineAngle(const QPointF &p1, const QPointF &p2)

References addPathShape(), bezierFit(), createStroke(), KoPathShapeId, lineAngle(), m_combineAngle, m_fittingError, m_mode, m_optimizeCurve, m_optimizeRaw, m_points, ModeCurve, ModeRaw, and ModeStraight.

◆ getFittingError()

qreal KoPencilTool::getFittingError ( )
protected

Definition at line 571 of file KoPencilTool.cpp.

572{
573 return this->m_fittingError;
574}

References m_fittingError.

◆ keyPressEvent()

void KoPencilTool::keyPressEvent ( QKeyEvent * event)
overridevirtual

Called when a key is pressed. Implementors should call event->ignore() if they do not actually use the event. Default implementation ignores this event.

Parameters
eventstate and reason of this key press

Reimplemented from KoToolBase.

Definition at line 147 of file KoPencilTool.cpp.

148{
149 if (m_shape) {
150 event->accept();
151 } else {
152 event->ignore();
153 }
154}

References m_shape.

◆ lineAngle()

qreal KoPencilTool::lineAngle ( const QPointF & p1,
const QPointF & p2 )
private

Definition at line 210 of file KoPencilTool.cpp.

211{
212 qreal angle = atan2(p2.y() - p1.y(), p2.x() - p1.x());
213 if (angle < 0.0)
214 angle += 2 * M_PI;
215
216 return angle * 180.0 / M_PI;
217}
QPointF p2
QPointF p1
#define M_PI
Definition kis_global.h:111
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement

References M_PI, p1, and p2.

◆ mouseMoveEvent()

void KoPencilTool::mouseMoveEvent ( KoPointerEvent * event)
overridevirtual

Called when the mouse or stylus moved over the canvas. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus move

Implements KoToolBase.

Definition at line 102 of file KoPencilTool.cpp.

103{
104 if (event->buttons() & Qt::LeftButton)
105 addPoint(event->point);
106
107 KoPathPoint * endPoint = endPointAtPosition(event->point);
108 if (m_hoveredPoint != endPoint) {
109 if (m_hoveredPoint) {
110 QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point());
112 }
113 m_hoveredPoint = endPoint;
114 if (m_hoveredPoint) {
115 QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point());
117 }
118 }
119}
QPointF point
void addPoint(const QPointF &point)
KoPathPoint * endPointAtPosition(const QPointF &position)
returns the nearest existing path point
Qt::MouseButtons buttons() const
return buttons pressed (see QMouseEvent::buttons());
QPointF point
The point in document coordinates.
QPointF shapeToDocument(const QPointF &point) const
Transforms point from shape coordinates to document coordinates.
Definition KoShape.cpp:1201
QRectF handlePaintRect(const QPointF &position) const

References addPoint(), KoPointerEvent::buttons(), KoToolBase::canvas(), endPointAtPosition(), KoToolBase::handlePaintRect(), m_hoveredPoint, KoPathPoint::parent(), KoPathPoint::point, KoPointerEvent::point, KoShape::shapeToDocument(), and KoCanvasBase::updateCanvas().

◆ mousePressEvent()

void KoPencilTool::mousePressEvent ( KoPointerEvent * event)
overridevirtual

Called when (one of) the mouse or stylus buttons is pressed. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus press

Implements KoToolBase.

Definition at line 83 of file KoPencilTool.cpp.

84{
86
87 if (!m_shape && stroke && stroke->isVisible()) {
88 m_shape = new KoPathShape();
91 m_points.clear();
92
93 QPointF point = event->point;
97
98 addPoint(point);
99 }
100}
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:1081
void setShapeId(const QString &id)
Definition KoShape.cpp:1062

References addPoint(), createStroke(), endPointAtPosition(), KoPathShapeId, m_existingStartPoint, m_points, m_shape, KoPathPoint::parent(), KoPathPoint::point, KoShape::setShapeId(), KoShape::setStroke(), and KoShape::shapeToDocument().

◆ mouseReleaseEvent()

void KoPencilTool::mouseReleaseEvent ( KoPointerEvent * event)
overridevirtual

Called when (one of) the mouse or stylus buttons is released. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus release

Implements KoToolBase.

Definition at line 121 of file KoPencilTool.cpp.

122{
123 if (! m_shape)
124 return;
125
126 QPointF point = event->point;
130
131 addPoint(point);
132 finish(event->modifiers() & Qt::ShiftModifier);
133
136 m_hoveredPoint = 0;
137
138 // the original path may be different from the one added
139 if (canvas() && m_shape) {
141 }
142 delete m_shape;
143 m_shape = 0;
144 m_points.clear();
145}
void finish(bool closePath)
Qt::KeyboardModifiers modifiers() const

References addPoint(), KoPathShape::boundingRect(), KoToolBase::canvas(), endPointAtPosition(), finish(), m_existingEndPoint, m_existingStartPoint, m_hoveredPoint, m_points, m_shape, KoPointerEvent::modifiers(), KoPathPoint::parent(), KoPathPoint::point, KoShape::shapeToDocument(), and KoCanvasBase::updateCanvas().

◆ paint()

void KoPencilTool::paint ( QPainter & painter,
const KoViewConverter & converter )
overridevirtual

Called by the canvas to paint any decorations that the tool deems needed. The painter has the top left of the canvas as its origin.

Parameters
painterused for painting the shape
converterto convert between internal and view coordinates.

Implements KoToolBase.

Definition at line 52 of file KoPencilTool.cpp.

53{
54 if (m_shape) {
55 painter.save();
56
57 painter.setTransform(m_shape->absoluteTransformation() *
58 converter.documentToView() *
59 painter.transform());
60
61 painter.save();
62 m_shape->paint(painter);
63 painter.restore();
64
65 if (m_shape->stroke()) {
66 painter.save();
67 m_shape->stroke()->paint(m_shape, painter);
68 painter.restore();
69 }
70
71 painter.restore();
72 }
73
74 if (m_hoveredPoint) {
77
80 }
81}
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void setHandleStyle(const KisHandleStyle &style)
static KisHandleStyle & primarySelection()
@ Node
the node point
Definition KoPathPoint.h:49
void paint(KisHandlePainterHelper &handlesHelper, PointTypes types, bool active=true)
void paint(QPainter &painter) const override
reimplemented
virtual KoShapeStrokeModelSP stroke() const
Definition KoShape.cpp:1067
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:1177
int handleRadius() const
Convenience function to get the current handle radius.
int decorationThickness() const
decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen ...
virtual QPointF documentToView(const QPointF &documentPoint) const

References KoShape::absoluteTransformation(), KoShape::createHandlePainterHelperView(), KoToolBase::decorationThickness(), KoViewConverter::documentToView(), KoToolBase::handleRadius(), m_hoveredPoint, m_shape, KoPathPoint::Node, KoPathPoint::paint(), KoPathShape::paint(), KoPathPoint::parent(), KisHandleStyle::primarySelection(), KisHandlePainterHelper::setHandleStyle(), and KoShape::stroke().

◆ path()

KoPathShape * KoPencilTool::path ( )
protected

Definition at line 444 of file KoPencilTool.cpp.

445{
446 return m_shape;
447}

References m_shape.

◆ selectMode

void KoPencilTool::selectMode ( int mode)
privateslot

Definition at line 405 of file KoPencilTool.cpp.

406{
407 m_mode = static_cast<PencilMode>(mode);
408 m_configGroup.writeEntry("pencilMode", mode);
409}

References m_configGroup, and m_mode.

◆ setDelta

void KoPencilTool::setDelta ( double delta)
privateslot

Definition at line 423 of file KoPencilTool.cpp.

424{
425 if (m_mode == ModeCurve) {
426 m_fittingError = delta;
427 m_configGroup.writeEntry("fittingError", m_fittingError);
428 }
429 else if (m_mode == ModeStraight) {
430 m_combineAngle = delta;
431 m_configGroup.writeEntry("combineAngle", m_combineAngle);
432 }
433}

References m_combineAngle, m_configGroup, m_fittingError, m_mode, ModeCurve, and ModeStraight.

◆ setFittingError()

void KoPencilTool::setFittingError ( qreal fittingError)
protected

Definition at line 576 of file KoPencilTool.cpp.

577{
578 this->m_fittingError = fittingError;
579}

References m_fittingError.

◆ setOptimize

void KoPencilTool::setOptimize ( int state)
privateslot

Definition at line 411 of file KoPencilTool.cpp.

412{
413 if (m_mode == ModeRaw) {
414 m_optimizeRaw = state == Qt::Checked ? true : false;
415 m_configGroup.writeEntry("optimizeRaw", m_optimizeRaw);
416 }
417 else {
418 m_optimizeCurve = state == Qt::Checked ? true : false;
419 m_configGroup.writeEntry("optimizeCurve", m_optimizeCurve);
420 }
421}

References m_configGroup, m_mode, m_optimizeCurve, m_optimizeRaw, and ModeRaw.

◆ slotUpdatePencilCursor

void KoPencilTool::slotUpdatePencilCursor ( )
protectedvirtualslot

Reimplemented in __KisToolPencilLocalTool.

Definition at line 186 of file KoPencilTool.cpp.

187{
188 KoShapeStrokeSP stroke = createStroke();
189 useCursor((stroke && stroke->isVisible()) ? Qt::ArrowCursor : Qt::ForbiddenCursor);
190}
void useCursor(const QCursor &cursor)

References createStroke(), and KoToolBase::useCursor().

Member Data Documentation

◆ m_close

bool KoPencilTool::m_close {false}
private

Definition at line 80 of file KoPencilTool.h.

80{false};

◆ m_combineAngle

qreal KoPencilTool::m_combineAngle {15.0}
private

Definition at line 78 of file KoPencilTool.h.

78{15.0};

◆ m_configGroup

KConfigGroup KoPencilTool::m_configGroup
private

Definition at line 90 of file KoPencilTool.h.

◆ m_existingEndPoint

KoPathPoint* KoPencilTool::m_existingEndPoint {0}
private

an existing path point we finished a new path at

Definition at line 86 of file KoPencilTool.h.

86{0};

◆ m_existingStartPoint

KoPathPoint* KoPencilTool::m_existingStartPoint {0}
private

an existing path point we started a new path at

Definition at line 85 of file KoPencilTool.h.

85{0};

◆ m_fittingError

qreal KoPencilTool::m_fittingError {5.0}
private

Definition at line 79 of file KoPencilTool.h.

79{5.0};

◆ m_hoveredPoint

KoPathPoint* KoPencilTool::m_hoveredPoint {0}
private

an existing path end point the mouse is hovering on

Definition at line 87 of file KoPencilTool.h.

87{0};

◆ m_mode

PencilMode KoPencilTool::m_mode {ModeCurve}
private

Definition at line 75 of file KoPencilTool.h.

75{ModeCurve};

◆ m_optimizeCurve

bool KoPencilTool::m_optimizeCurve {false}
private

Definition at line 77 of file KoPencilTool.h.

77{false};

◆ m_optimizeRaw

bool KoPencilTool::m_optimizeRaw {false}
private

Definition at line 76 of file KoPencilTool.h.

76{false};

◆ m_points

QList<QPointF> KoPencilTool::m_points
private

Definition at line 82 of file KoPencilTool.h.

◆ m_shape

KoPathShape* KoPencilTool::m_shape {0}
private

Definition at line 84 of file KoPencilTool.h.

84{0};

◆ m_strokeWidget

KoStrokeConfigWidget* KoPencilTool::m_strokeWidget {0}
private

Definition at line 88 of file KoPencilTool.h.

88{0};

The documentation for this class was generated from the following files: