diff --git a/plugins/tools/selectiontools/kis_tool_select_outline.cc b/plugins/tools/selectiontools/kis_tool_select_outline.cc index 4ff3063ac8..e938325bac 100644 --- a/plugins/tools/selectiontools/kis_tool_select_outline.cc +++ b/plugins/tools/selectiontools/kis_tool_select_outline.cc @@ -1,196 +1,255 @@ /* * kis_tool_select_freehand.h - part of Krayon^WKrita * * Copyright (c) 2000 John Califf * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2007 Sven Langkamp * Copyright (c) 2015 Michael Abrahams * * 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_select_outline.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_painter.h" #include #include "canvas/kis_canvas2.h" #include "kis_pixel_selection.h" #include "kis_selection_tool_helper.h" #define FEEDBACK_LINE_WIDTH 2 KisToolSelectOutline::KisToolSelectOutline(KoCanvasBase * canvas) : KisToolSelect(canvas, KisCursor::load("tool_outline_selection_cursor.png", 5, 5), i18n("Outline Selection")), - m_paintPath(new QPainterPath()) + m_continuedMode(false) { connect(&m_widgetHelper, &KisSelectionToolConfigWidgetHelper::selectionActionChanged, this, &KisToolSelectOutline::setSelectionAction); } KisToolSelectOutline::~KisToolSelectOutline() { - delete m_paintPath; +} + +void KisToolSelectOutline::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Control) { + m_continuedMode = true; + } + + KisToolSelect::keyPressEvent(event); +} + +void KisToolSelectOutline::keyReleaseEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Control || + !(event->modifiers() & Qt::ControlModifier)) { + + m_continuedMode = false; + if (mode() != PAINT_MODE && !m_points.isEmpty()) { + finishSelectionAction(); + } + } + + KisToolSelect::keyReleaseEvent(event); +} + +void KisToolSelectOutline::mouseMoveEvent(KoPointerEvent *event) +{ + m_lastCursorPos = convertToPixelCoord(event); + if (m_continuedMode && mode() != PAINT_MODE) { + updateContinuedMode(); + } } void KisToolSelectOutline::beginPrimaryAction(KoPointerEvent *event) { KisToolSelectBase::beginPrimaryAction(event); if (!selectionEditable()) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); - m_points.clear(); - m_points.append(convertToPixelCoord(event)); - m_paintPath->moveTo(pixelToView(convertToPixelCoord(event))); + if (m_continuedMode && !m_points.isEmpty()) { + m_paintPath.lineTo(pixelToView(convertToPixelCoord(event))); + } else { + m_paintPath.moveTo(pixelToView(convertToPixelCoord(event))); + } + m_points.append(convertToPixelCoord(event)); } void KisToolSelectOutline::continuePrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); KisToolSelectBase::continuePrimaryAction(event); QPointF point = convertToPixelCoord(event); - m_paintPath->lineTo(pixelToView(point)); + m_paintPath.lineTo(pixelToView(point)); m_points.append(point); updateFeedback(); } void KisToolSelectOutline::endPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); KisToolSelectBase::endPrimaryAction(event); setMode(KisTool::HOVER_MODE); + if (!m_continuedMode) { + finishSelectionAction(); + } +} + +void KisToolSelectOutline::finishSelectionAction() +{ KisCanvas2 * kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas); kisCanvas->updateCanvas(); if (m_points.count() > 2) { QApplication::setOverrideCursor(KisCursor::waitCursor()); KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Outline")); if (selectionMode() == PIXEL_SELECTION) { KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection()); KisPainter painter(tmpSel); painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); painter.setPaintOpPreset(currentPaintOpPreset(), currentNode(), currentImage()); painter.setAntiAliasPolygonFill(antiAliasSelection()); painter.setFillStyle(KisPainter::FillStyleForegroundColor); painter.setStrokeStyle(KisPainter::StrokeStyleNone); painter.paintPolygon(m_points); QPainterPath cache; cache.addPolygon(m_points); cache.closeSubpath(); tmpSel->setOutlineCache(cache); helper.selectPixelSelection(tmpSel, selectionAction()); } else { KoPathShape* path = new KoPathShape(); path->setShapeId(KoPathShapeId); QTransform resolutionMatrix; resolutionMatrix.scale(1 / currentImage()->xRes(), 1 / currentImage()->yRes()); path->moveTo(resolutionMatrix.map(m_points[0])); for (int i = 1; i < m_points.count(); i++) path->lineTo(resolutionMatrix.map(m_points[i])); path->close(); path->normalize(); helper.addSelectionShape(path); } QApplication::restoreOverrideCursor(); } m_points.clear(); - delete m_paintPath; - m_paintPath = new QPainterPath(); + m_paintPath = QPainterPath(); } void KisToolSelectOutline::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); - if (mode() == KisTool::PAINT_MODE && !m_points.isEmpty()) { - paintToolOutline(&gc, *m_paintPath); + if ((mode() == KisTool::PAINT_MODE || m_continuedMode) && + !m_points.isEmpty()) { + + QPainterPath outline = m_paintPath; + if (m_continuedMode && mode() != KisTool::PAINT_MODE) { + outline.lineTo(pixelToView(m_lastCursorPos)); + } + paintToolOutline(&gc, outline); } } void KisToolSelectOutline::updateFeedback() { if (m_points.count() > 1) { qint32 lastPointIndex = m_points.count() - 1; QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_points[lastPointIndex]).normalized(); - updateRect.adjust(-FEEDBACK_LINE_WIDTH, -FEEDBACK_LINE_WIDTH, FEEDBACK_LINE_WIDTH, FEEDBACK_LINE_WIDTH); + updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH); + + updateCanvasPixelRect(updateRect); + } +} + +void KisToolSelectOutline::updateContinuedMode() +{ + if (!m_points.isEmpty()) { + qint32 lastPointIndex = m_points.count() - 1; + + QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_lastCursorPos).normalized(); + updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH); updateCanvasPixelRect(updateRect); } } void KisToolSelectOutline::deactivate() { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas); kisCanvas->updateCanvas(); + m_continuedMode = false; + KisTool::deactivate(); } void KisToolSelectOutline::setSelectionAction(int action) { changeSelectionAction(action); } diff --git a/plugins/tools/selectiontools/kis_tool_select_outline.h b/plugins/tools/selectiontools/kis_tool_select_outline.h index bbda8baabd..c0f492acd6 100644 --- a/plugins/tools/selectiontools/kis_tool_select_outline.h +++ b/plugins/tools/selectiontools/kis_tool_select_outline.h @@ -1,84 +1,92 @@ /* * kis_tool_select_freehand.h - part of Krayon^WKrita * * Copyright (c) 2000 John Califf * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2015 Michael Abrahams * * 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_SELECT_OUTLINE_H_ #define KIS_TOOL_SELECT_OUTLINE_H_ #include #include #include #include class QPainterPath; class KisToolSelectOutline : public KisToolSelect { Q_OBJECT public: KisToolSelectOutline(KoCanvasBase *canvas); virtual ~KisToolSelectOutline(); void beginPrimaryAction(KoPointerEvent *event); void continuePrimaryAction(KoPointerEvent *event); void endPrimaryAction(KoPointerEvent *event); virtual void paint(QPainter& gc, const KoViewConverter &converter); + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); + + void mouseMoveEvent(KoPointerEvent *event); public Q_SLOTS: virtual void deactivate(); void setSelectionAction(int); protected: using KisToolSelectBase::m_widgetHelper; private: + void finishSelectionAction(); void updateFeedback(); + void updateContinuedMode(); void updateCanvas(); - QPainterPath * m_paintPath; + QPainterPath m_paintPath; vQPointF m_points; + bool m_continuedMode; + QPointF m_lastCursorPos; }; class KisToolSelectOutlineFactory : public KoToolFactoryBase { public: KisToolSelectOutlineFactory() : KoToolFactoryBase("KisToolSelectOutline") { setToolTip(i18n("Outline Selection Tool")); setSection(TOOL_TYPE_SELECTION); setIconName(koIconNameCStr("tool_outline_selection")); setPriority(3); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); } virtual ~KisToolSelectOutlineFactory() {} virtual KoToolBase * createTool(KoCanvasBase *canvas) { return new KisToolSelectOutline(canvas); } }; #endif //__selecttoolfreehand_h__