diff --git a/libs/image/kis_signal_compressor.h b/libs/image/kis_signal_compressor.h index 8811415b78..8d8b2a5c37 100644 --- a/libs/image/kis_signal_compressor.h +++ b/libs/image/kis_signal_compressor.h @@ -1,85 +1,85 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SIGNAL_COMPRESSOR_H #define __KIS_SIGNAL_COMPRESSOR_H #include #include "kritaimage_export.h" class QTimer; /** * Sets a timer to delay or throttle activation of a Qt slot. One example of * where this is used is to limit the amount of expensive redraw activity on the * canvas. * * There are three behaviors to choose from. * * POSTPONE resets the timer after each call. Therefore if the calls are made * quickly enough, the timer will never be activated. * * FIRST_ACTIVE emits the timeout() event immediately and sets a timer of * duration \p delay. If the compressor is triggered during this time, it will - * fire another signal at the end of the delay period. Further events are + * wait until the end of the delay period to fire the signal. Further events are * ignored until the timer elapses. Think of it as a queue with size 1, and * where the leading element is popped every \p delay ms. * * FIRST_INACTIVE emits the timeout() event at the end of a timer of duration \p * delay ms. The compressor becomes inactive and all events are ignored until * the timer has elapsed. * */ class KRITAIMAGE_EXPORT KisSignalCompressor : public QObject { Q_OBJECT public: enum Mode { POSTPONE, /* Calling start() resets the timer to \p delay ms */ FIRST_ACTIVE, /* Emit timeout() signal immediately. Throttle further timeout() to rate of one per \p delay ms */ FIRST_INACTIVE, /* Set a timer \p delay ms, emit timeout() when it elapses. Ignore all events meanwhile. */ UNDEFINED /* KisSignalCompressor is created without an explicit mode */ }; public: KisSignalCompressor(); KisSignalCompressor(int delay, Mode mode, QObject *parent = 0); bool isActive() const; void setMode(Mode mode); void setDelay(int delay); public Q_SLOTS: void start(); void stop(); private Q_SLOTS: void slotTimerExpired(); Q_SIGNALS: void timeout(); private: QTimer m_timer; Mode m_mode; bool m_gotSignals; }; #endif /* __KIS_SIGNAL_COMPRESSOR_H */ diff --git a/plugins/tools/basictools/kis_tool_line.cc b/plugins/tools/basictools/kis_tool_line.cc index 5aa3d4fef3..b11c161cec 100644 --- a/plugins/tools/basictools/kis_tool_line.cc +++ b/plugins/tools/basictools/kis_tool_line.cc @@ -1,344 +1,375 @@ /* * kis_tool_line.cc - part of Krayon * * Copyright (c) 2000 John Califf * Copyright (c) 2002 Patrick Julien * Copyright (c) 2003 Boudewijn Rempt * Copyright (c) 2009 Lukáš Tvrdý * Copyright (c) 2007,2010 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_line.h" #include #include #include #include #include #include #include #include #include #include #include "kis_figure_painting_tool_helper.h" #include "kis_canvas2.h" #include #include #include #include "kis_painting_information_builder.h" #include "kis_tool_line_helper.h" #define ENABLE_RECORDING const KisCoordinatesConverter* getCoordinatesConverter(KoCanvasBase * canvas) { KisCanvas2 *kritaCanvas = dynamic_cast(canvas); return kritaCanvas->coordinatesConverter(); } KisToolLine::KisToolLine(KoCanvasBase * canvas) : KisToolPaint(canvas, KisCursor::load("tool_line_cursor.png", 6, 6)), - m_showOutline(false), + m_showGuideline(true), m_strokeIsRunning(false), m_infoBuilder(new KisConverterPaintingInformationBuilder(getCoordinatesConverter(canvas))), m_helper(new KisToolLineHelper(m_infoBuilder.data(), kundo2_i18n("Draw Line"))), - m_strokeUpdateCompressor(500, KisSignalCompressor::FIRST_ACTIVE), + m_strokeUpdateCompressor(500, KisSignalCompressor::POSTPONE), m_longStrokeUpdateCompressor(1000, KisSignalCompressor::FIRST_INACTIVE) { setObjectName("tool_line"); setSupportOutline(true); connect(&m_strokeUpdateCompressor, SIGNAL(timeout()), SLOT(updateStroke())); connect(&m_longStrokeUpdateCompressor, SIGNAL(timeout()), SLOT(updateStroke())); } KisToolLine::~KisToolLine() { } int KisToolLine::flags() const { return KisTool::FLAG_USES_CUSTOM_COMPOSITEOP|KisTool::FLAG_USES_CUSTOM_PRESET; } void KisToolLine::resetCursorStyle() { KisToolPaint::resetCursorStyle(); overrideCursorIfNotEditable(); } void KisToolLine::activate(ToolActivation activation, const QSet &shapes) { KisToolPaint::activate(activation, shapes); configGroup = KSharedConfig::openConfig()->group(toolId()); } void KisToolLine::deactivate() { KisToolPaint::deactivate(); cancelStroke(); } QWidget* KisToolLine::createOptionWidget() { QWidget* widget = KisToolPaint::createOptionWidget(); m_chkUseSensors = new QCheckBox(i18n("Use sensors")); addOptionWidgetOption(m_chkUseSensors); - m_chkShowOutline = new QCheckBox(i18n("Preview")); - addOptionWidgetOption(m_chkShowOutline); + m_chkShowPreview = new QCheckBox(i18n("Show Preview")); + addOptionWidgetOption(m_chkShowPreview); + + m_chkShowGuideline = new QCheckBox(i18n("Show Guideline")); + addOptionWidgetOption(m_chkShowGuideline); // hook up connections for value changing connect(m_chkUseSensors, SIGNAL(clicked(bool)), this, SLOT(setUseSensors(bool)) ); - connect(m_chkShowOutline, SIGNAL(clicked(bool)), this, SLOT(setShowOutline(bool)) ); + connect(m_chkShowPreview, SIGNAL(clicked(bool)), this, SLOT(setShowPreview(bool)) ); + connect(m_chkShowGuideline, SIGNAL(clicked(bool)), this, SLOT(setShowGuideline(bool)) ); // read values in from configuration m_chkUseSensors->setChecked(configGroup.readEntry("useSensors", true)); - m_chkShowOutline->setChecked(configGroup.readEntry("showOutline", false)); + m_chkShowPreview->setChecked(configGroup.readEntry("showPreview", true)); + m_chkShowGuideline->setChecked(configGroup.readEntry("showGuideline", true)); return widget; } void KisToolLine::setUseSensors(bool value) { configGroup.writeEntry("useSensors", value); } -void KisToolLine::setShowOutline(bool value) +void KisToolLine::setShowGuideline(bool value) { - configGroup.writeEntry("showOutline", value); + m_showGuideline = value; + configGroup.writeEntry("showGuideline", value); +} + +void KisToolLine::setShowPreview(bool value) +{ + configGroup.writeEntry("showPreview", value); } void KisToolLine::requestStrokeCancellation() { cancelStroke(); } void KisToolLine::requestStrokeEnd() { - endStroke(); + // Terminate any in-progress strokes + if (nodePaintAbility() == PAINT && m_helper->isRunning()) { + endStroke(); + } +} + +void KisToolLine::updatePreviewTimer(bool showGuideline) +{ + // If the user disables the guideline, we will want to try to draw some + // preview lines even if they're slow, so set the timer to FIRST_ACTIVE. + if (showGuideline) { + m_strokeUpdateCompressor.setMode(KisSignalCompressor::POSTPONE); + } else { + m_strokeUpdateCompressor.setMode(KisSignalCompressor::FIRST_ACTIVE); + } } + void KisToolLine::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); if(mode() == KisTool::PAINT_MODE) { paintLine(gc,QRect()); } KisToolPaint::paint(gc,converter); } void KisToolLine::beginPrimaryAction(KoPointerEvent *event) { NodePaintAbility nodeAbility = nodePaintAbility(); if (nodeAbility == NONE || !nodeEditable()) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); - m_showOutline = m_chkShowOutline->isChecked() || nodeAbility != PAINT; + // Always show guideline on vector layers + m_showGuideline = m_chkShowGuideline->isChecked() || nodeAbility != PAINT; + updatePreviewTimer(m_showGuideline); m_helper->setEnabled(nodeAbility == PAINT); m_helper->setUseSensors(m_chkUseSensors->isChecked()); m_helper->start(event); m_startPoint = convertToPixelCoordAndSnap(event); m_endPoint = m_startPoint; m_lastUpdatedPoint = m_startPoint; m_strokeIsRunning = true; } void KisToolLine::updateStroke() { if (!m_strokeIsRunning) return; m_helper->repaintLine(canvas()->resourceManager(), image(), currentNode(), image().data(), image()->postExecutionUndoAdapter()); } void KisToolLine::continuePrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); if (!m_strokeIsRunning) return; - // First ensure the old temp line is deleted - updatePreview(); + // First ensure the old guideline is deleted + updateGuideline(); QPointF pos = convertToPixelCoordAndSnap(event); if (event->modifiers() == Qt::AltModifier) { QPointF trans = pos - m_endPoint; m_helper->translatePoints(trans); m_startPoint += trans; m_endPoint += trans; } else if (event->modifiers() == Qt::ShiftModifier) { pos = straightLine(pos); m_helper->addPoint(event, pos); } else { m_helper->addPoint(event, pos); } + m_endPoint = pos; - if ((pixelToView(m_lastUpdatedPoint) - pixelToView(pos)).manhattanLength() > 10) { - m_longStrokeUpdateCompressor.stop(); - m_strokeUpdateCompressor.start(); - m_lastUpdatedPoint = pos; - } else { - m_longStrokeUpdateCompressor.start(); + // Draw preview if requested + if (m_chkShowPreview->isChecked()) { + // If the cursor has moved a significant amount, immediately clear the + // current preview and redraw. Otherwise, do slow redraws periodically. + auto updateDistance = (pixelToView(m_lastUpdatedPoint) - pixelToView(pos)).manhattanLength(); + if (updateDistance > 10) { + m_helper->clearPaint(); + m_longStrokeUpdateCompressor.stop(); + m_strokeUpdateCompressor.start(); + m_lastUpdatedPoint = pos; + } else if (updateDistance > 1) { + m_longStrokeUpdateCompressor.start(); + } } - m_endPoint = pos; - updatePreview(); + + updateGuideline(); KisToolPaint::requestUpdateOutline(event->point, event); } void KisToolLine::endPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); setMode(KisTool::HOVER_MODE); - updatePreview(); - + updateGuideline(); endStroke(); } void KisToolLine::endStroke() { NodePaintAbility nodeAbility = nodePaintAbility(); - if (!m_strokeIsRunning || - (nodeAbility == PAINT && !m_helper->isRunning())|| - m_startPoint == m_endPoint || - nodeAbility == NONE) { - + if (!m_strokeIsRunning || m_startPoint == m_endPoint || nodeAbility == NONE) { return; } if (nodeAbility == PAINT) { updateStroke(); m_helper->end(); } else { KoPathShape* path = new KoPathShape(); path->setShapeId(KoPathShapeId); QTransform resolutionMatrix; resolutionMatrix.scale(1 / currentImage()->xRes(), 1 / currentImage()->yRes()); path->moveTo(resolutionMatrix.map(m_startPoint)); path->lineTo(resolutionMatrix.map(m_endPoint)); path->normalize(); KoShapeStroke* border = new KoShapeStroke(1.0, currentFgColor().toQColor()); path->setStroke(border); KUndo2Command * cmd = canvas()->shapeController()->addShape(path); canvas()->addCommand(cmd); } m_strokeIsRunning = false; m_endPoint = m_startPoint; } void KisToolLine::cancelStroke() { if (!m_strokeIsRunning) return; if (m_startPoint == m_endPoint) return; /** * The actual stroke is run by the timer so it is a legal * situation when m_strokeIsRunning is true, but the actual redraw * stroke is not running. */ if (m_helper->isRunning()) { m_helper->cancel(); } m_strokeIsRunning = false; m_endPoint = m_startPoint; } QPointF KisToolLine::straightLine(QPointF point) { const QPointF lineVector = point - m_startPoint; qreal lineAngle = std::atan2(lineVector.y(), lineVector.x()); if (lineAngle < 0) { lineAngle += 2 * M_PI; } const qreal ANGLE_BETWEEN_CONSTRAINED_LINES = (2 * M_PI) / 24; const quint32 constrainedLineIndex = static_cast((lineAngle / ANGLE_BETWEEN_CONSTRAINED_LINES) + 0.5); const qreal constrainedLineAngle = constrainedLineIndex * ANGLE_BETWEEN_CONSTRAINED_LINES; const qreal lineLength = std::sqrt((lineVector.x() * lineVector.x()) + (lineVector.y() * lineVector.y())); const QPointF constrainedLineVector(lineLength * std::cos(constrainedLineAngle), lineLength * std::sin(constrainedLineAngle)); const QPointF result = m_startPoint + constrainedLineVector; return result; } -void KisToolLine::updatePreview() +void KisToolLine::updateGuideline() { if (canvas()) { QRectF bound(m_startPoint, m_endPoint); canvas()->updateCanvas(convertToPt(bound.normalized().adjusted(-3, -3, 3, 3))); } } void KisToolLine::paintLine(QPainter& gc, const QRect&) { QPointF viewStartPos = pixelToView(m_startPoint); QPointF viewStartEnd = pixelToView(m_endPoint); - if (m_showOutline && canvas()) { + if (m_showGuideline && canvas()) { QPainterPath path; path.moveTo(viewStartPos); path.lineTo(viewStartEnd); paintToolOutline(&gc, path); } } QString KisToolLine::quickHelp() const { return i18n("Alt+Drag will move the origin of the currently displayed line around, Shift+Drag will force you to draw straight lines"); } diff --git a/plugins/tools/basictools/kis_tool_line.h b/plugins/tools/basictools/kis_tool_line.h index 510f4a2e7a..9b52ec5a23 100644 --- a/plugins/tools/basictools/kis_tool_line.h +++ b/plugins/tools/basictools/kis_tool_line.h @@ -1,134 +1,137 @@ /* * kis_tool_line.h - part of Krayon * * Copyright (c) 2000 John Califf * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_LINE_H_ #define KIS_TOOL_LINE_H_ #include "kis_tool_paint.h" #include #include #include #include "kis_global.h" #include "kis_types.h" #include "KoToolFactoryBase.h" #include "flake/kis_node_shape.h" #include "kis_signal_compressor.h" #include #include class QPoint; class KoCanvasBase; class QCheckBox; class KisPaintingInformationBuilder; class KisToolLineHelper; class KisToolLine : public KisToolPaint { Q_OBJECT public: KisToolLine(KoCanvasBase * canvas); virtual ~KisToolLine(); void requestStrokeCancellation(); void requestStrokeEnd(); void beginPrimaryAction(KoPointerEvent *event); void continuePrimaryAction(KoPointerEvent *event); void endPrimaryAction(KoPointerEvent *event); void activate(ToolActivation activation, const QSet &shapes); void deactivate(); virtual int flags() const; virtual void paint(QPainter& gc, const KoViewConverter &converter); virtual QString quickHelp() const; protected Q_SLOTS: virtual void resetCursorStyle(); private Q_SLOTS: void updateStroke(); void setUseSensors(bool value); - void setShowOutline(bool value); + void setShowPreview(bool value); + void setShowGuideline(bool value); private: void paintLine(QPainter& gc, const QRect& rc); QPointF straightLine(QPointF point); - void updatePreview(); + void updateGuideline(); + void updatePreviewTimer(bool showGuide); virtual QWidget* createOptionWidget(); void endStroke(); void cancelStroke(); private: - bool m_showOutline; + bool m_showGuideline; QPointF m_startPoint; QPointF m_endPoint; QPointF m_lastUpdatedPoint; bool m_strokeIsRunning; QCheckBox *m_chkUseSensors; - QCheckBox *m_chkShowOutline; + QCheckBox *m_chkShowPreview; + QCheckBox *m_chkShowGuideline; QScopedPointer m_infoBuilder; QScopedPointer m_helper; KisSignalCompressor m_strokeUpdateCompressor; KisSignalCompressor m_longStrokeUpdateCompressor; KConfigGroup configGroup; }; class KisToolLineFactory : public KoToolFactoryBase { public: KisToolLineFactory() : KoToolFactoryBase("KritaShape/KisToolLine") { setToolTip(i18n("Line Tool")); // Temporarily setToolType(TOOL_TYPE_SHAPE); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); setPriority(1); setIconName(koIconNameCStr("krita_tool_line")); } virtual ~KisToolLineFactory() {} virtual KoToolBase * createTool(KoCanvasBase *canvas) { return new KisToolLine(canvas); } }; #endif //KIS_TOOL_LINE_H_ diff --git a/plugins/tools/basictools/kis_tool_line_helper.cpp b/plugins/tools/basictools/kis_tool_line_helper.cpp index ab043247f6..ec396bfa1e 100644 --- a/plugins/tools/basictools/kis_tool_line_helper.cpp +++ b/plugins/tools/basictools/kis_tool_line_helper.cpp @@ -1,163 +1,171 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_line_helper.h" #include "kis_painting_information_builder.h" #include "kis_image.h" struct KisToolLineHelper::Private { Private(KisPaintingInformationBuilder *_infoBuilder) : infoBuilder(_infoBuilder), useSensors(true), enabled(true) { } QVector linePoints; KisPaintingInformationBuilder *infoBuilder; bool useSensors; bool enabled; }; KisToolLineHelper::KisToolLineHelper(KisPaintingInformationBuilder *infoBuilder, const KUndo2MagicString &transactionText, KisRecordingAdapter *recordingAdapter) : KisToolFreehandHelper(infoBuilder, transactionText, recordingAdapter), m_d(new Private(infoBuilder)) { } KisToolLineHelper::~KisToolLineHelper() { } void KisToolLineHelper::setEnabled(bool value) { m_d->enabled = value; } void KisToolLineHelper::setUseSensors(bool value) { m_d->useSensors = value; } void KisToolLineHelper::repaintLine(KoCanvasResourceManager *resourceManager, KisImageWSP image, KisNodeSP node, KisStrokesFacade *strokesFacade, KisPostExecutionUndoAdapter *undoAdapter) { if (!m_d->enabled) return; cancelPaint(); if (m_d->linePoints.isEmpty()) return; QVector::const_iterator it = m_d->linePoints.constBegin(); QVector::const_iterator end = m_d->linePoints.constEnd(); initPaintImpl(*it, resourceManager, image, node, strokesFacade, undoAdapter); ++it; while (it != end) { paintLine(*(it - 1), *it); ++it; } } void KisToolLineHelper::start(KoPointerEvent *event) { if (!m_d->enabled) return; KisPaintInformation pi = m_d->infoBuilder->startStroke(event, elapsedStrokeTime()); if (!m_d->useSensors) { pi = KisPaintInformation(pi.pos()); } m_d->linePoints.append(pi); } void KisToolLineHelper::addPoint(KoPointerEvent *event, const QPointF &overridePos) { if (!m_d->enabled) return; KisPaintInformation pi = m_d->infoBuilder->continueStroke(event, elapsedStrokeTime()); if (!m_d->useSensors) { pi = KisPaintInformation(pi.pos()); } if (!overridePos.isNull()) { pi.setPos(overridePos); } if (m_d->linePoints.size() > 1) { const QPointF startPos = m_d->linePoints.first().pos(); const QPointF endPos = pi.pos(); const qreal maxDistance = kisDistance(startPos, endPos); const QPointF unit = (endPos - startPos) / maxDistance; QVector::iterator it = m_d->linePoints.begin(); ++it; while (it != m_d->linePoints.end()) { qreal dist = kisDistance(startPos, it->pos()); if (dist < maxDistance) { QPointF pos = startPos + unit * dist; it->setPos(pos); ++it; } else { it = m_d->linePoints.erase(it); } } } m_d->linePoints.append(pi); } void KisToolLineHelper::translatePoints(const QPointF &offset) { if (!m_d->enabled) return; QVector::iterator it = m_d->linePoints.begin(); while (it != m_d->linePoints.end()) { it->setPos(it->pos() + offset); ++it; } } void KisToolLineHelper::end() { if (!m_d->enabled) return; KIS_ASSERT_RECOVER_RETURN(isRunning()); endPaint(); m_d->linePoints.clear(); } void KisToolLineHelper::cancel() { if (!m_d->enabled) return; KIS_ASSERT_RECOVER_RETURN(isRunning()); cancelPaint(); m_d->linePoints.clear(); } + + +void KisToolLineHelper::clearPaint() +{ + if (!m_d->enabled) return; + + cancelPaint(); +} diff --git a/plugins/tools/basictools/kis_tool_line_helper.h b/plugins/tools/basictools/kis_tool_line_helper.h index 5eda5c0a85..56917907e0 100644 --- a/plugins/tools/basictools/kis_tool_line_helper.h +++ b/plugins/tools/basictools/kis_tool_line_helper.h @@ -1,56 +1,57 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_TOOL_LINE_HELPER_H #define __KIS_TOOL_LINE_HELPER_H #include "kis_tool_freehand_helper.h" class KisToolLineHelper : private KisToolFreehandHelper { public: KisToolLineHelper(KisPaintingInformationBuilder *infoBuilder, const KUndo2MagicString &transactionText, KisRecordingAdapter *recordingAdapter = 0); ~KisToolLineHelper(); void setEnabled(bool value); void setUseSensors(bool value); void repaintLine(KoCanvasResourceManager *resourceManager, KisImageWSP image, KisNodeSP node, KisStrokesFacade *strokesFacade, KisPostExecutionUndoAdapter *undoAdapter); void start(KoPointerEvent *event); void addPoint(KoPointerEvent *event, const QPointF &overridePos = QPointF()); void translatePoints(const QPointF &offset); void end(); void cancel(); + void clearPaint(); using KisToolFreehandHelper::isRunning; private: struct Private; Private * const m_d; }; #endif /* __KIS_TOOL_LINE_HELPER_H */