diff --git a/libs/ui/tool/kis_tool_polyline_base.cpp b/libs/ui/tool/kis_tool_polyline_base.cpp index 8a806cd10f..ac052a2599 100644 --- a/libs/ui/tool/kis_tool_polyline_base.cpp +++ b/libs/ui/tool/kis_tool_polyline_base.cpp @@ -1,265 +1,270 @@ /* This file is part of the KDE project * Copyright (C) 2009 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "kis_tool_polyline_base.h" #include "kis_canvas2.h" #include #include #include #include "kis_action_registry.h" #define SNAPPING_THRESHOLD 10 #define SNAPPING_HANDLE_RADIUS 8 #define PREVIEW_LINE_WIDTH 1 KisToolPolylineBase::KisToolPolylineBase(KoCanvasBase * canvas, KisToolPolylineBase::ToolType type, const QCursor & cursor) : KisToolShape(canvas, cursor), m_dragging(false), m_type(type), m_closeSnappingActivated(false) { QAction *undo_polygon_selection = KisActionRegistry::instance()->makeQAction("undo_polygon_selection", this); addAction("undo_polygon_selection", undo_polygon_selection); } void KisToolPolylineBase::activate(KoToolBase::ToolActivation activation, const QSet &shapes) { KisToolShape::activate(activation, shapes); connect(action("undo_polygon_selection"), SIGNAL(triggered()), SLOT(undoSelection()), Qt::UniqueConnection); } void KisToolPolylineBase::deactivate() { disconnect(action("undo_polygon_selection"), 0, this, 0); cancelStroke(); KisToolShape::deactivate(); } void KisToolPolylineBase::requestStrokeEnd() { endStroke(); } void KisToolPolylineBase::requestStrokeCancellation() { cancelStroke(); } +bool KisToolPolylineBase::hasUserInteractionRunning() const +{ + return !m_points.isEmpty(); +} + void KisToolPolylineBase::beginPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); if ((m_type == PAINT && (!nodeEditable() || nodePaintAbility() == NONE)) || (m_type == SELECT && !selectionEditable())) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); if(m_dragging && m_closeSnappingActivated) { m_points.append(m_points.first()); endStroke(); } else { m_dragging = true; } } void KisToolPolylineBase::endPrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); setMode(KisTool::HOVER_MODE); if(m_dragging) { m_dragStart = convertToPixelCoordAndSnap(event); m_dragEnd = m_dragStart; m_points.append(m_dragStart); } } void KisToolPolylineBase::beginPrimaryDoubleClickAction(KoPointerEvent *event) { endStroke(); // this action will have no continuation event->ignore(); } void KisToolPolylineBase::beginAlternateAction(KoPointerEvent *event, AlternateAction action) { if (action != ChangeSize || !m_dragging) { KisToolPaint::beginAlternateAction(event, action); } if (m_closeSnappingActivated) { m_points.append(m_points.first()); } endStroke(); } void KisToolPolylineBase::mouseMoveEvent(KoPointerEvent *event) { if (m_dragging && !m_points.empty()) { // erase old lines on canvas QRectF updateRect = dragBoundingRect(); // get current mouse position m_dragEnd = convertToPixelCoordAndSnap(event); // draw new lines on canvas updateRect |= dragBoundingRect(); updateCanvasViewRect(updateRect); QPointF basePoint = pixelToView(m_points.first()); m_closeSnappingActivated = m_points.size() > 1 && (basePoint - pixelToView(m_dragEnd)).manhattanLength() < SNAPPING_THRESHOLD; updateCanvasViewRect(QRectF(basePoint, 2 * QSize(SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH, SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH)).translated(-SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH,-SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH)); KisToolPaint::requestUpdateOutline(event->point, event); } else { KisToolPaint::mouseMoveEvent(event); } } void KisToolPolylineBase::undoSelection() { if(m_dragging) { //Update canvas for drag before undo QRectF updateRect = dragBoundingRect(); updateRect |= dragBoundingRect(); updateCanvasViewRect(updateRect); //Update canvas for last segment QRectF rect; if (m_points.size() > 2) { rect = pixelToView(QRectF(m_points.last(), m_points.at(m_points.size()-2)).normalized()); rect.adjust(-PREVIEW_LINE_WIDTH, -PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH); rect |= rect; updateCanvasViewRect(rect); } if (m_points.size() > 0) { m_points.pop_back(); } if (m_points.size() > 0) { m_dragStart = m_points.last(); } } } void KisToolPolylineBase::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); if (!canvas() || !currentImage()) return; QPointF start, end; QPointF startPos; QPointF endPos; QPainterPath path; if (m_dragging && !m_points.empty()) { startPos = pixelToView(m_dragStart); endPos = pixelToView(m_dragEnd); path.moveTo(startPos); path.lineTo(endPos); } for (vQPointF::iterator it = m_points.begin(); it != m_points.end(); ++it) { if (it == m_points.begin()) { start = (*it); } else { end = (*it); startPos = pixelToView(start); endPos = pixelToView(end); path.moveTo(startPos); path.lineTo(endPos); start = end; } } if (m_closeSnappingActivated) { QPointF basePoint = pixelToView(m_points.first()); path.addEllipse(basePoint, SNAPPING_HANDLE_RADIUS, SNAPPING_HANDLE_RADIUS); } paintToolOutline(&gc, path); KisToolPaint::paint(gc,converter); } void KisToolPolylineBase::updateArea() { updateCanvasPixelRect(image()->bounds()); } void KisToolPolylineBase::endStroke() { if (!m_dragging) return; m_dragging = false; if(m_points.count() > 1) { finishPolyline(m_points); } m_points.clear(); m_closeSnappingActivated = false; updateArea(); } void KisToolPolylineBase::cancelStroke() { if (!m_dragging) return; m_dragging = false; m_points.clear(); m_closeSnappingActivated = false; updateArea(); } QRectF KisToolPolylineBase::dragBoundingRect() { QRectF rect = pixelToView(QRectF(m_dragStart, m_dragEnd).normalized()); rect.adjust(-PREVIEW_LINE_WIDTH, -PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH); return rect; } void KisToolPolylineBase::listenToModifiers(bool listen) { Q_UNUSED(listen) } bool KisToolPolylineBase::listeningToModifiers() { //Never grab modifier keys return false; } diff --git a/libs/ui/tool/kis_tool_polyline_base.h b/libs/ui/tool/kis_tool_polyline_base.h index 91baff9707..fc2572f6b9 100644 --- a/libs/ui/tool/kis_tool_polyline_base.h +++ b/libs/ui/tool/kis_tool_polyline_base.h @@ -1,76 +1,78 @@ /* This file is part of the KDE project * Copyright (C) 2009 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_POLYLINE_BASE_H #define KIS_TOOL_POLYLINE_BASE_H #include #include class KRITAUI_EXPORT KisToolPolylineBase : public KisToolShape { Q_OBJECT public: enum ToolType { PAINT, SELECT }; KisToolPolylineBase(KoCanvasBase * canvas, KisToolPolylineBase::ToolType type, const QCursor & cursor=KisCursor::load("tool_polygon_cursor.png", 6, 6)); void beginPrimaryAction(KoPointerEvent *event) override; void endPrimaryAction(KoPointerEvent *event) override; void beginPrimaryDoubleClickAction(KoPointerEvent *event) override; void mouseMoveEvent(KoPointerEvent *event) override; void beginAlternateAction(KoPointerEvent *event, AlternateAction action) override; void paint(QPainter& gc, const KoViewConverter &converter) override; void activate(ToolActivation activation, const QSet &shapes) override; void deactivate() override; void listenToModifiers(bool listen) override; bool listeningToModifiers() override; void requestStrokeEnd() override; void requestStrokeCancellation() override; + bool hasUserInteractionRunning() const; + protected: virtual void finishPolyline(const QVector& points) = 0; private: void endStroke(); void cancelStroke(); void updateArea(); QRectF dragBoundingRect(); private Q_SLOTS: virtual void undoSelection(); private: QPointF m_dragStart; QPointF m_dragEnd; bool m_dragging; bool m_listenToModifiers; vQPointF m_points; ToolType m_type; bool m_closeSnappingActivated; }; #endif // KIS_TOOL_POLYLINE_BASE_H diff --git a/libs/ui/tool/kis_tool_select_base.h b/libs/ui/tool/kis_tool_select_base.h index afab5b5957..c01db63e0d 100644 --- a/libs/ui/tool/kis_tool_select_base.h +++ b/libs/ui/tool/kis_tool_select_base.h @@ -1,298 +1,329 @@ /* This file is part of the KDE project * Copyright (C) 2009 Boudewijn Rempt * Copyright (C) 2015 Michael Abrahams * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISTOOLSELECTBASE_H #define KISTOOLSELECTBASE_H #include "KoPointerEvent.h" #include "kis_tool.h" #include "kis_canvas2.h" #include "kis_selection.h" #include "kis_selection_options.h" #include "kis_selection_tool_config_widget_helper.h" #include "KisViewManager.h" #include "kis_selection_manager.h" #include "kis_selection_modifier_mapper.h" #include "strokes/move_stroke_strategy.h" #include "kis_image.h" #include "kis_cursor.h" /** * This is a basic template to create selection tools from basic path based drawing tools. * The template overrides the ability to execute alternate actions correctly. * The default behavior for the modifier keys is as follows: * * Shift: add to selection * Alt: subtract from selection * Shift+Alt: intersect current selection * Ctrl: replace selection * * The mapping itself is done in KisSelectionModifierMapper. * * Certain tools also use modifier keys to alter their behavior, e.g. forcing square proportions with the rectangle tool. * The template enables the following rules for forwarding keys: * 1) Any modifier keys held *when the tool is first activated* will determine * the new selection method. This is recorded in m_selectionActionAlternate. A * value of m_selectionActionAlternate = SELECTION_DEFAULT means no modifier was * being pressed when the tool was activated. * * 2) If the underlying tool *does not take modifier keys*, pressing modifier * keys in the middle of a stroke will change the selection method. This is * recorded in m_selectionAction. A value of SELECTION_DEFAULT means no modifier * is being pressed. Applies to the lasso tool and polygon tool. * * 3) If the underlying tool *takes modifier keys,* they will always be * forwarded to the underlying tool, and it is not possible to change the * selection method in the middle of a stroke. */ template class KisToolSelectBase : public BaseClass { public: KisToolSelectBase(KoCanvasBase* canvas, const QString toolName) :BaseClass(canvas), m_widgetHelper(toolName), m_selectionAction(SELECTION_DEFAULT), m_selectionActionAlternate(SELECTION_DEFAULT) { KisSelectionModifierMapper::instance(); } KisToolSelectBase(KoCanvasBase* canvas, const QCursor cursor, const QString toolName) :BaseClass(canvas, cursor), m_widgetHelper(toolName), m_selectionAction(SELECTION_DEFAULT), m_selectionActionAlternate(SELECTION_DEFAULT) { } KisToolSelectBase(KoCanvasBase* canvas, QCursor cursor, QString toolName, KisTool *delegateTool) :BaseClass(canvas, cursor, delegateTool), m_widgetHelper(toolName), m_selectionAction(SELECTION_DEFAULT), m_selectionActionAlternate(SELECTION_DEFAULT) { } QWidget* createOptionWidget() { KisCanvas2* canvas = dynamic_cast(this->canvas()); Q_ASSERT(canvas); m_widgetHelper.createOptionWidget(canvas, this->toolId()); this->connect(this, SIGNAL(isActiveChanged(bool)), &m_widgetHelper, SLOT(slotToolActivatedChanged(bool))); return m_widgetHelper.optionWidget(); } void keyPressEvent(QKeyEvent *event) { if (!m_widgetHelper.processKeyPressEvent(event)) { BaseClass::keyPressEvent(event); } } SelectionMode selectionMode() const { return m_widgetHelper.selectionMode(); } SelectionAction selectionAction() const { if (alternateSelectionAction() == SELECTION_DEFAULT) { return m_widgetHelper.selectionAction(); } return alternateSelectionAction(); } bool antiAliasSelection() const { return m_widgetHelper.optionWidget()->antiAliasSelection(); } SelectionAction alternateSelectionAction() const { return m_selectionActionAlternate; } KisSelectionOptions* selectionOptionWidget() { return m_widgetHelper.optionWidget(); } virtual void setAlternateSelectionAction(SelectionAction action) { m_selectionActionAlternate = action; dbgKrita << "Changing to selection action" << m_selectionActionAlternate; } void activateAlternateAction(KisTool::AlternateAction action) { Q_UNUSED(action); BaseClass::activatePrimaryAction(); } void deactivateAlternateAction(KisTool::AlternateAction action) { Q_UNUSED(action); BaseClass::deactivatePrimaryAction(); } void beginAlternateAction(KoPointerEvent *event, KisTool::AlternateAction action) { Q_UNUSED(action); beginPrimaryAction(event); } void continueAlternateAction(KoPointerEvent *event, KisTool::AlternateAction action) { Q_UNUSED(action); continuePrimaryAction(event); } void endAlternateAction(KoPointerEvent *event, KisTool::AlternateAction action) { Q_UNUSED(action); endPrimaryAction(event); } KisNodeSP locateSelectionMaskUnderCursor(const QPointF &pos) { KisCanvas2* canvas = dynamic_cast(this->canvas()); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(canvas, 0); KisSelectionSP selection = canvas->viewManager()->selection(); if (selection && selection->outlineCacheValid() && selection->outlineCache().contains(pos)) { KisNodeSP parent = selection->parentNode(); if (parent && parent->isEditable()) { return parent; } } return 0; } void mouseMoveEvent(KoPointerEvent *event) { - const QPointF pos = this->convertToPixelCoord(event->point); - KisNodeSP selectionMask = locateSelectionMaskUnderCursor(pos); - if (selectionMask) { - this->useCursor(KisCursor::moveCursor()); - } else { - this->resetCursorStyle(); + if (!this->hasUserInteractionRunning()) { + const QPointF pos = this->convertToPixelCoord(event->point); + KisNodeSP selectionMask = locateSelectionMaskUnderCursor(pos); + if (selectionMask) { + this->useCursor(KisCursor::moveCursor()); + } else { + this->resetCursorStyle(); + } } BaseClass::mouseMoveEvent(event); } virtual void beginPrimaryAction(KoPointerEvent *event) { - const QPointF pos = this->convertToPixelCoord(event->point); - KisCanvas2* canvas = dynamic_cast(this->canvas()); - KIS_SAFE_ASSERT_RECOVER_RETURN(canvas); + if (!this->hasUserInteractionRunning()) { + const QPointF pos = this->convertToPixelCoord(event->point); + KisCanvas2* canvas = dynamic_cast(this->canvas()); + KIS_SAFE_ASSERT_RECOVER_RETURN(canvas); - KisNodeSP selectionMask = locateSelectionMaskUnderCursor(pos); - if (selectionMask) { - KisStrokeStrategy *strategy = new MoveStrokeStrategy({selectionMask}, this->image().data(), this->image().data()); - m_moveStrokeId = this->image()->startStroke(strategy); - m_dragStartPos = pos; + KisNodeSP selectionMask = locateSelectionMaskUnderCursor(pos); + if (selectionMask) { + KisStrokeStrategy *strategy = new MoveStrokeStrategy({selectionMask}, this->image().data(), this->image().data()); + m_moveStrokeId = this->image()->startStroke(strategy); + m_dragStartPos = pos; - return; + return; + } } - keysAtStart = event->modifiers(); setAlternateSelectionAction(KisSelectionModifierMapper::map(keysAtStart)); if (alternateSelectionAction() != SELECTION_DEFAULT) { BaseClass::listenToModifiers(false); } BaseClass::beginPrimaryAction(event); } virtual void continuePrimaryAction(KoPointerEvent *event) { if (m_moveStrokeId) { const QPointF pos = this->convertToPixelCoord(event->point); const QPoint offset((pos - m_dragStartPos).toPoint()); this->image()->addJob(m_moveStrokeId, new MoveStrokeStrategy::Data(offset)); return; } //If modifier keys have changed, tell the base tool it can start capturing modifiers if ((keysAtStart != event->modifiers()) && !BaseClass::listeningToModifiers()) { BaseClass::listenToModifiers(true); } //Always defer to the base class if it signals it is capturing modifier keys if (!BaseClass::listeningToModifiers()) { setAlternateSelectionAction(KisSelectionModifierMapper::map(event->modifiers())); } BaseClass::continuePrimaryAction(event); } void endPrimaryAction(KoPointerEvent *event) { if (m_moveStrokeId) { this->image()->endStroke(m_moveStrokeId); m_moveStrokeId.clear(); return; } keysAtStart = Qt::NoModifier; //reset this with each action BaseClass::endPrimaryAction(event); } void changeSelectionAction(int newSelectionAction) { // Simple sanity check if(newSelectionAction >= SELECTION_REPLACE && newSelectionAction <= SELECTION_INTERSECT && m_selectionAction != newSelectionAction) { m_selectionAction = (SelectionAction)newSelectionAction; } } + bool selectionDragInProgress() const { + return m_moveStrokeId; + } + protected: using BaseClass::canvas; KisSelectionToolConfigWidgetHelper m_widgetHelper; SelectionAction m_selectionAction; SelectionAction m_selectionActionAlternate; private: Qt::KeyboardModifiers keysAtStart; QPointF m_dragStartPos; KisStrokeId m_moveStrokeId; }; +struct FakeBaseTool : KisTool +{ + FakeBaseTool(KoCanvasBase* canvas) + : KisTool(canvas, QCursor()) + { + } + + FakeBaseTool(KoCanvasBase* canvas, const QString &toolName) + : KisTool(canvas, QCursor()) + { + Q_UNUSED(toolName); + } + + FakeBaseTool(KoCanvasBase* canvas, const QCursor &cursor) + : KisTool(canvas, cursor) + { + } + + bool hasUserInteractionRunning() const { + return false; + } + +}; + -typedef KisToolSelectBase KisToolSelect; +typedef KisToolSelectBase KisToolSelect; #endif // KISTOOLSELECTBASE_H diff --git a/plugins/tools/selectiontools/kis_tool_select_contiguous.cc b/plugins/tools/selectiontools/kis_tool_select_contiguous.cc index b90d9d9e0d..58445b668e 100644 --- a/plugins/tools/selectiontools/kis_tool_select_contiguous.cc +++ b/plugins/tools/selectiontools/kis_tool_select_contiguous.cc @@ -1,254 +1,254 @@ /* * kis_tool_select_contiguous - part of Krayon^WKrita * * Copyright (c) 1999 Michael Koch * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2012 José Luis Vergara * 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_contiguous.h" #include #include #include #include #include #include #include #include #include #include "KoPointerEvent.h" #include "KoViewConverter.h" #include "kis_cursor.h" #include "kis_selection_manager.h" #include "kis_image.h" #include "canvas/kis_canvas2.h" #include "kis_layer.h" #include "kis_selection_options.h" #include "kis_paint_device.h" #include "kis_fill_painter.h" #include "kis_pixel_selection.h" #include "kis_selection_tool_helper.h" #include "kis_slider_spin_box.h" #include "tiles3/kis_hline_iterator.h" KisToolSelectContiguous::KisToolSelectContiguous(KoCanvasBase *canvas) - : KisToolSelectBase(canvas, - KisCursor::load("tool_contiguous_selection_cursor.png", 6, 6), - i18n("Contiguous Area Selection")), + : KisToolSelect(canvas, + KisCursor::load("tool_contiguous_selection_cursor.png", 6, 6), + i18n("Contiguous Area Selection")), m_fuzziness(20), m_sizemod(0), m_feather(0), m_limitToCurrentLayer(false) { setObjectName("tool_select_contiguous"); connect(&m_widgetHelper, &KisSelectionToolConfigWidgetHelper::selectionActionChanged, this, &KisToolSelectContiguous::setSelectionAction); } KisToolSelectContiguous::~KisToolSelectContiguous() { } void KisToolSelectContiguous::activate(ToolActivation toolActivation, const QSet &shapes) { KisTool::activate(toolActivation, shapes); m_configGroup = KSharedConfig::openConfig()->group(toolId()); } void KisToolSelectContiguous::beginPrimaryAction(KoPointerEvent *event) { KisToolSelectBase::beginPrimaryAction(event); KisPaintDeviceSP dev; if (!currentNode() || !(dev = currentNode()->projection()) || !currentNode()->visible() || !selectionEditable()) { event->ignore(); return; } QApplication::setOverrideCursor(KisCursor::waitCursor()); QPoint pos = convertToImagePixelCoordFloored(event); QRect rc = currentImage()->bounds(); KisFillPainter fillpainter(dev); fillpainter.setHeight(rc.height()); fillpainter.setWidth(rc.width()); fillpainter.setFillThreshold(m_fuzziness); fillpainter.setFeather(m_feather); fillpainter.setSizemod(m_sizemod); KisImageWSP image = currentImage(); KisPaintDeviceSP sourceDevice = m_limitToCurrentLayer ? dev : image->projection(); image->lock(); KisSelectionSP selection = fillpainter.createFloodSelection(pos.x(), pos.y(), sourceDevice); image->unlock(); // If we're not antialiasing, threshold the entire selection if (!antiAliasSelection()) { QRect r = selection->selectedExactRect(); if (r.isValid()) { KisHLineIteratorSP selectionIt = selection->pixelSelection()->createHLineIteratorNG(r.x(), r.y(), r.width()); for (qint32 y = 0; y < r.height(); y++) { do { if (selectionIt->rawData()[0] > 0) { selection->pixelSelection()->colorSpace()->setOpacity(selectionIt->rawData(), OPACITY_OPAQUE_U8, 1); } } while (selectionIt->nextPixel()); selectionIt->nextRow(); } } } KisCanvas2 * kisCanvas = dynamic_cast(canvas()); if (!kisCanvas || !selection->pixelSelection()) { QApplication::restoreOverrideCursor(); return; } selection->pixelSelection()->invalidateOutlineCache(); KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Contiguous Area")); helper.selectPixelSelection(selection->pixelSelection(), selectionAction()); QApplication::restoreOverrideCursor(); } void KisToolSelectContiguous::paint(QPainter &painter, const KoViewConverter &converter) { Q_UNUSED(painter); Q_UNUSED(converter); } void KisToolSelectContiguous::slotSetFuzziness(int fuzziness) { m_fuzziness = fuzziness; m_configGroup.writeEntry("fuzziness", fuzziness); } void KisToolSelectContiguous::slotSetSizemod(int sizemod) { m_sizemod = sizemod; m_configGroup.writeEntry("sizemod", sizemod); } void KisToolSelectContiguous::slotSetFeather(int feather) { m_feather = feather; m_configGroup.writeEntry("feather", feather); } QWidget* KisToolSelectContiguous::createOptionWidget() { KisToolSelectBase::createOptionWidget(); KisSelectionOptions *selectionWidget = selectionOptionWidget(); selectionWidget->disableSelectionModeOption(); QVBoxLayout * l = dynamic_cast(selectionWidget->layout()); Q_ASSERT(l); if (l) { QGridLayout * gridLayout = new QGridLayout(); l->insertLayout(1, gridLayout); QLabel * lbl = new QLabel(i18n("Fuzziness: "), selectionWidget); gridLayout->addWidget(lbl, 0, 0, 1, 1); KisSliderSpinBox *input = new KisSliderSpinBox(selectionWidget); Q_CHECK_PTR(input); input->setObjectName("fuzziness"); input->setRange(1, 100); input->setSingleStep(1); input->setExponentRatio(2); gridLayout->addWidget(input, 0, 1, 1, 1); lbl = new QLabel(i18n("Grow/shrink selection: "), selectionWidget); gridLayout->addWidget(lbl, 1, 0, 1, 1); KisSliderSpinBox *sizemod = new KisSliderSpinBox(selectionWidget); Q_CHECK_PTR(sizemod); sizemod->setObjectName("sizemod"); //grow/shrink selection sizemod->setRange(-40, 40); sizemod->setSingleStep(1); gridLayout->addWidget(sizemod, 1, 1, 1, 1); lbl = new QLabel(i18n("Feathering radius: "), selectionWidget); gridLayout->addWidget(lbl, 2, 0, 1, 1); KisSliderSpinBox *feather = new KisSliderSpinBox(selectionWidget); Q_CHECK_PTR(feather); feather->setObjectName("feathering"); feather->setRange(0, 40); feather->setSingleStep(1); gridLayout->addWidget(feather, 2, 1, 1, 1); connect (input , SIGNAL(valueChanged(int)), this, SLOT(slotSetFuzziness(int) )); connect (sizemod, SIGNAL(valueChanged(int)), this, SLOT(slotSetSizemod(int) )); connect (feather, SIGNAL(valueChanged(int)), this, SLOT(slotSetFeather(int) )); QCheckBox* limitToCurrentLayer = new QCheckBox(i18n("Limit to current layer"), selectionWidget); l->insertWidget(4, limitToCurrentLayer); connect (limitToCurrentLayer, SIGNAL(stateChanged(int)), this, SLOT(slotLimitToCurrentLayer(int))); // load configuration settings into tool options input->setValue(m_configGroup.readEntry("fuzziness", 20)); // fuzziness sizemod->setValue( m_configGroup.readEntry("sizemod", 0)); //grow/shrink sizemod->setSuffix(i18n(" px")); feather->setValue(m_configGroup.readEntry("feather", 0)); feather->setSuffix(i18n(" px")); limitToCurrentLayer->setChecked(m_configGroup.readEntry("limitToCurrentLayer", false)); } return selectionWidget; } void KisToolSelectContiguous::slotLimitToCurrentLayer(int state) { if (state == Qt::PartiallyChecked) return; m_limitToCurrentLayer = (state == Qt::Checked); m_configGroup.writeEntry("limitToCurrentLayer", state); } void KisToolSelectContiguous::setSelectionAction(int action) { changeSelectionAction(action); } QMenu* KisToolSelectContiguous::popupActionsMenu() { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); Q_ASSERT(kisCanvas); return KisSelectionToolHelper::getSelectionContextMenu(kisCanvas); } diff --git a/plugins/tools/selectiontools/kis_tool_select_contiguous.h b/plugins/tools/selectiontools/kis_tool_select_contiguous.h index 279bbf55b7..717cbbd284 100644 --- a/plugins/tools/selectiontools/kis_tool_select_contiguous.h +++ b/plugins/tools/selectiontools/kis_tool_select_contiguous.h @@ -1,96 +1,96 @@ /* * kis_tool_select_contiguous.h - part of KImageShop^WKrayon^Krita * * Copyright (c) 1999 Michael Koch * Copyright (c) 2002 Patrick Julien * 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_CONTIGUOUS_H__ #define __KIS_TOOL_SELECT_CONTIGUOUS_H__ #include "KoToolFactoryBase.h" #include "kis_tool_select_base.h" #include #include #include /** * The 'magic wand' selection tool -- in fact just * a floodfill that only creates a selection. */ -class KisToolSelectContiguous : public KisToolSelectBase +class KisToolSelectContiguous : public KisToolSelect { Q_OBJECT public: KisToolSelectContiguous(KoCanvasBase *canvas); ~KisToolSelectContiguous() override; QWidget* createOptionWidget() override; void paint(QPainter &painter, const KoViewConverter &converter) override; void beginPrimaryAction(KoPointerEvent *event) override; QMenu* popupActionsMenu() override; protected: bool wantsAutoScroll() const override { return false; } public Q_SLOTS: void activate(ToolActivation toolActivation, const QSet &shapes) override; virtual void slotSetFuzziness(int); virtual void slotSetSizemod(int); virtual void slotSetFeather(int); virtual void slotLimitToCurrentLayer(int); void setSelectionAction(int); //virtual bool antiAliasSelection(); protected: using KisToolSelectBase::m_widgetHelper; private: int m_fuzziness; int m_sizemod; int m_feather; bool m_limitToCurrentLayer; KConfigGroup m_configGroup; }; class KisToolSelectContiguousFactory : public KoToolFactoryBase { public: KisToolSelectContiguousFactory() : KoToolFactoryBase("KisToolSelectContiguous") { setToolTip(i18n("Contiguous Selection Tool")); setSection(TOOL_TYPE_SELECTION); setIconName(koIconNameCStr("tool_contiguous_selection")); setPriority(4); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); } ~KisToolSelectContiguousFactory() override {} KoToolBase * createTool(KoCanvasBase *canvas) override { return new KisToolSelectContiguous(canvas); } }; #endif //__KIS_TOOL_SELECT_CONTIGUOUS_H__ diff --git a/plugins/tools/selectiontools/kis_tool_select_elliptical.cc b/plugins/tools/selectiontools/kis_tool_select_elliptical.cc index 251a039c3a..30e1ea1e43 100644 --- a/plugins/tools/selectiontools/kis_tool_select_elliptical.cc +++ b/plugins/tools/selectiontools/kis_tool_select_elliptical.cc @@ -1,103 +1,108 @@ /* * kis_tool_select_elliptical.cc -- part of Krita * * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * 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_elliptical.h" #include #include "kis_painter.h" #include #include "kis_selection_options.h" #include "kis_canvas2.h" #include "kis_pixel_selection.h" #include "kis_selection_tool_helper.h" #include "kis_shape_tool_helper.h" #include "KisViewManager.h" #include "kis_selection_manager.h" __KisToolSelectEllipticalLocal::__KisToolSelectEllipticalLocal(KoCanvasBase *canvas) : KisToolEllipseBase(canvas, KisToolEllipseBase::SELECT, KisCursor::load("tool_elliptical_selection_cursor.png", 6, 6)) { setObjectName("tool_select_elliptical"); } +bool __KisToolSelectEllipticalLocal::hasUserInteractionRunning() const +{ + return false; +} + void __KisToolSelectEllipticalLocal::finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY) { Q_UNUSED(roundCornersX); Q_UNUSED(roundCornersY); KisCanvas2 * kisCanvas = dynamic_cast(canvas()); Q_ASSERT(kisCanvas); KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Ellipse")); if (helper.tryDeselectCurrentSelection(pixelToView(rect), selectionAction())) { return; } if (selectionMode() == PIXEL_SELECTION) { KisPixelSelectionSP tmpSel = new KisPixelSelection(); KisPainter painter(tmpSel); painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); painter.setAntiAliasPolygonFill(antiAliasSelection()); painter.setFillStyle(KisPainter::FillStyleForegroundColor); painter.setStrokeStyle(KisPainter::StrokeStyleNone); painter.paintEllipse(rect); QPainterPath cache; cache.addEllipse(rect); tmpSel->setOutlineCache(cache); helper.selectPixelSelection(tmpSel, selectionAction()); } else { QRectF ptRect = convertToPt(rect); KoShape* shape = KisShapeToolHelper::createEllipseShape(ptRect); helper.addSelectionShape(shape, selectionAction()); } } KisToolSelectElliptical::KisToolSelectElliptical(KoCanvasBase *canvas): KisToolSelectEllipticalTemplate(canvas, i18n("Elliptical Selection")) { connect(&m_widgetHelper, &KisSelectionToolConfigWidgetHelper::selectionActionChanged, this, &KisToolSelectElliptical::setSelectionAction); } void KisToolSelectElliptical::setSelectionAction(int action) { changeSelectionAction(action); } QMenu* KisToolSelectElliptical::popupActionsMenu() { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); Q_ASSERT(kisCanvas); return KisSelectionToolHelper::getSelectionContextMenu(kisCanvas); } diff --git a/plugins/tools/selectiontools/kis_tool_select_elliptical.h b/plugins/tools/selectiontools/kis_tool_select_elliptical.h index e06b938d84..ed425e90df 100644 --- a/plugins/tools/selectiontools/kis_tool_select_elliptical.h +++ b/plugins/tools/selectiontools/kis_tool_select_elliptical.h @@ -1,93 +1,94 @@ /* * kis_tool_select_elliptical.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_ELLIPTICAL_H__ #define __KIS_TOOL_SELECT_ELLIPTICAL_H__ #include "KoToolFactoryBase.h" #include "kis_tool_ellipse_base.h" #include #include "kis_selection_tool_config_widget_helper.h" #include #include #include #include class __KisToolSelectEllipticalLocal : public KisToolEllipseBase { Q_OBJECT public: __KisToolSelectEllipticalLocal(KoCanvasBase *canvas); + bool hasUserInteractionRunning() const; protected: virtual SelectionMode selectionMode() const = 0; virtual SelectionAction selectionAction() const = 0; virtual bool antiAliasSelection() const = 0; private: void finishRect(const QRectF &rect, qreal roundCornersX, qreal roundCornersY) override; }; typedef KisToolSelectBase<__KisToolSelectEllipticalLocal> KisToolSelectEllipticalTemplate; class KisToolSelectElliptical : public KisToolSelectEllipticalTemplate { Q_OBJECT public: KisToolSelectElliptical(KoCanvasBase* canvas); QMenu* popupActionsMenu() override; public Q_SLOTS: void setSelectionAction(int); }; class KisToolSelectEllipticalFactory : public KoToolFactoryBase { public: KisToolSelectEllipticalFactory() : KoToolFactoryBase("KisToolSelectElliptical") { setToolTip(i18n("Elliptical Selection Tool")); setSection(TOOL_TYPE_SELECTION); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); setIconName(koIconNameCStr("tool_elliptical_selection")); setShortcut(QKeySequence(Qt::Key_J)); setPriority(1); } ~KisToolSelectEllipticalFactory() override {} KoToolBase * createTool(KoCanvasBase *canvas) override { return new KisToolSelectElliptical(canvas); } }; #endif //__KIS_TOOL_SELECT_ELLIPTICAL_H__ diff --git a/plugins/tools/selectiontools/kis_tool_select_outline.cc b/plugins/tools/selectiontools/kis_tool_select_outline.cc index 03f863e41e..3b3f62d942 100644 --- a/plugins/tools/selectiontools/kis_tool_select_outline.cc +++ b/plugins/tools/selectiontools/kis_tool_select_outline.cc @@ -1,272 +1,280 @@ /* * 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" #include "kis_algebra_2d.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_continuedMode(false) { connect(&m_widgetHelper, &KisSelectionToolConfigWidgetHelper::selectionActionChanged, this, &KisToolSelectOutline::setSelectionAction); } KisToolSelectOutline::~KisToolSelectOutline() { } 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) { + KisToolSelect::mouseMoveEvent(event); + if (selectionDragInProgress()) return; + m_lastCursorPos = convertToPixelCoord(event); if (m_continuedMode && mode() != PAINT_MODE) { updateContinuedMode(); } } void KisToolSelectOutline::beginPrimaryAction(KoPointerEvent *event) { - KisToolSelectBase::beginPrimaryAction(event); + if (selectionDragInProgress()) return; + if (!selectionEditable()) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); 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); + if (selectionDragInProgress()) return; + + CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); QPointF point = convertToPixelCoord(event); 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); + const bool hadMoveInProgress = selectionDragInProgress(); KisToolSelectBase::endPrimaryAction(event); + if (hadMoveInProgress) return; + + CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); setMode(KisTool::HOVER_MODE); if (!m_continuedMode) { finishSelectionAction(); } } void KisToolSelectOutline::finishSelectionAction() { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas); kisCanvas->updateCanvas(); QRectF boundingViewRect = pixelToView(KisAlgebra2D::accumulateBounds(m_points)); KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Outline")); if (m_points.count() > 2 && !helper.tryDeselectCurrentSelection(boundingViewRect, selectionAction())) { QApplication::setOverrideCursor(KisCursor::waitCursor()); if (selectionMode() == PIXEL_SELECTION) { KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection()); KisPainter painter(tmpSel); painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); 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, selectionAction()); } QApplication::restoreOverrideCursor(); } m_points.clear(); m_paintPath = QPainterPath(); } void KisToolSelectOutline::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); 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 = 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); } QMenu* KisToolSelectOutline::popupActionsMenu() { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); Q_ASSERT(kisCanvas); return KisSelectionToolHelper::getSelectionContextMenu(kisCanvas); } diff --git a/plugins/tools/selectiontools/kis_tool_select_path.cc b/plugins/tools/selectiontools/kis_tool_select_path.cc index d969ef2982..e647891a65 100644 --- a/plugins/tools/selectiontools/kis_tool_select_path.cc +++ b/plugins/tools/selectiontools/kis_tool_select_path.cc @@ -1,164 +1,176 @@ /* * Copyright (c) 2007 Sven Langkamp * * 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_path.h" #include #include "kis_cursor.h" #include "kis_image.h" #include "kis_painter.h" #include "kis_selection_options.h" #include "kis_canvas_resource_provider.h" #include "kis_canvas2.h" #include "kis_pixel_selection.h" #include "kis_selection_tool_helper.h" #include KisToolSelectPath::KisToolSelectPath(KoCanvasBase * canvas) : KisToolSelectBase(canvas, KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6), i18n("Select path"), (KisTool*) (new __KisToolSelectPathLocalTool(canvas, this))) { } void KisToolSelectPath::requestStrokeEnd() { localTool()->endPathWithoutLastPoint(); } void KisToolSelectPath::requestStrokeCancellation() { localTool()->cancelPath(); } void KisToolSelectPath::mousePressEvent(KoPointerEvent* event) { if (!selectionEditable()) return; DelegatedSelectPathTool::mousePressEvent(event); } // Install an event filter to catch right-click events. // This code is duplicated in kis_tool_path.cc bool KisToolSelectPath::eventFilter(QObject *obj, QEvent *event) { Q_UNUSED(obj); if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) { QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::RightButton) { localTool()->removeLastPoint(); return true; } } else if (event->type() == QEvent::TabletPress) { QTabletEvent *tabletEvent = static_cast(event); if (tabletEvent->button() == Qt::RightButton) { localTool()->removeLastPoint(); return true; } } return false; } QList > KisToolSelectPath::createOptionWidgets() { QList > widgetsList = DelegatedSelectPathTool::createOptionWidgets(); QList > filteredWidgets; Q_FOREACH (QWidget* widget, widgetsList) { if (widget->objectName() != "Stroke widget") { filteredWidgets.push_back(widget); } } return filteredWidgets; } void KisDelegatedSelectPathWrapper::beginPrimaryAction(KoPointerEvent *event) { mousePressEvent(event); } void KisDelegatedSelectPathWrapper::continuePrimaryAction(KoPointerEvent *event){ mouseMoveEvent(event); } void KisDelegatedSelectPathWrapper::endPrimaryAction(KoPointerEvent *event) { mouseReleaseEvent(event); } +bool KisDelegatedSelectPathWrapper::hasUserInteractionRunning() const +{ + /** + * KoCreatePathTool doesn't support moving interventions from KisToolselectBase, + * because it doesn't use begin/continue/endPrimaryAction and uses direct event + * handling instead. + * + * TODO: refactor KoCreatePathTool and port it to action infrastructure + */ + return true; +} + __KisToolSelectPathLocalTool::__KisToolSelectPathLocalTool(KoCanvasBase * canvas, KisToolSelectPath* parentTool) : KoCreatePathTool(canvas), m_selectionTool(parentTool) { setEnableClosePathShortcut(false); } void __KisToolSelectPathLocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter) { Q_UNUSED(converter); KisCanvas2 * kisCanvas = dynamic_cast(canvas()); if (!kisCanvas) return; QTransform matrix; matrix.scale(kisCanvas->image()->xRes(), kisCanvas->image()->yRes()); matrix.translate(pathShape.position().x(), pathShape.position().y()); m_selectionTool->paintToolOutline(&painter, m_selectionTool->pixelToView(matrix.map(pathShape.outline()))); } void __KisToolSelectPathLocalTool::addPathShape(KoPathShape* pathShape) { pathShape->normalize(); pathShape->close(); KisCanvas2 * kisCanvas = dynamic_cast(canvas()); if (!kisCanvas) return; KisImageWSP image = kisCanvas->image(); KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Bezier Curve")); if (m_selectionTool->selectionMode() == PIXEL_SELECTION) { KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection()); KisPainter painter(tmpSel); painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); painter.setFillStyle(KisPainter::FillStyleForegroundColor); painter.setAntiAliasPolygonFill(m_selectionTool->antiAliasSelection()); painter.setStrokeStyle(KisPainter::StrokeStyleNone); QTransform matrix; matrix.scale(image->xRes(), image->yRes()); matrix.translate(pathShape->position().x(), pathShape->position().y()); QPainterPath path = matrix.map(pathShape->outline()); painter.fillPainterPath(path); tmpSel->setOutlineCache(path); helper.selectPixelSelection(tmpSel, m_selectionTool->selectionAction()); delete pathShape; } else { helper.addSelectionShape(pathShape, m_selectionTool->selectionAction()); } } diff --git a/plugins/tools/selectiontools/kis_tool_select_path.h b/plugins/tools/selectiontools/kis_tool_select_path.h index b66f49b1e9..6b811c3cdc 100644 --- a/plugins/tools/selectiontools/kis_tool_select_path.h +++ b/plugins/tools/selectiontools/kis_tool_select_path.h @@ -1,107 +1,109 @@ /* * 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. */ #ifndef KIS_TOOL_SELECT_PATH_H_ #define KIS_TOOL_SELECT_PATH_H_ #include #include #include "kis_tool_select_base.h" #include "kis_delegated_tool.h" #include class KoCanvasBase; class KisToolSelectPath; class __KisToolSelectPathLocalTool : public KoCreatePathTool { public: __KisToolSelectPathLocalTool(KoCanvasBase * canvas, KisToolSelectPath* parentTool); void paintPath(KoPathShape &path, QPainter &painter, const KoViewConverter &converter) override; void addPathShape(KoPathShape* pathShape) override; using KoCreatePathTool::createOptionWidgets; using KoCreatePathTool::endPathWithoutLastPoint; using KoCreatePathTool::endPath; using KoCreatePathTool::cancelPath; using KoCreatePathTool::removeLastPoint; private: KisToolSelectPath* const m_selectionTool; }; typedef KisDelegatedTool DelegatedSelectPathTool; struct KisDelegatedSelectPathWrapper : public DelegatedSelectPathTool { KisDelegatedSelectPathWrapper(KoCanvasBase *canvas, const QCursor &cursor, KisTool* delegateTool) : DelegatedSelectPathTool(canvas, cursor, (__KisToolSelectPathLocalTool*) delegateTool) { } // If an event is explicitly forwarded only as an action (e.g. shift-click is captured by "change size") // we will receive a primary action but no mousePressEvent. Thus these events must be explicitly forwarded. void beginPrimaryAction(KoPointerEvent *event) override; void continuePrimaryAction(KoPointerEvent *event) override; void endPrimaryAction(KoPointerEvent *event) override; + + bool hasUserInteractionRunning() const; }; class KisToolSelectPath : public KisToolSelectBase { Q_OBJECT public: KisToolSelectPath(KoCanvasBase * canvas); void mousePressEvent(KoPointerEvent* event) override; bool eventFilter(QObject *obj, QEvent *event) override; protected: void requestStrokeCancellation() override; void requestStrokeEnd() override; friend class __KisToolSelectPathLocalTool; QList > createOptionWidgets() override; }; class KisToolSelectPathFactory : public KoToolFactoryBase { public: KisToolSelectPathFactory() : KoToolFactoryBase("KisToolSelectPath") { setToolTip(i18n("Bezier Curve Selection Tool")); setSection(TOOL_TYPE_SELECTION); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); setIconName(koIconNameCStr("tool_path_selection")); setPriority(6); } ~KisToolSelectPathFactory() override {} KoToolBase * createTool(KoCanvasBase *canvas) override { return new KisToolSelectPath(canvas); } }; #endif // KIS_TOOL_SELECT_PATH_H_ diff --git a/plugins/tools/selectiontools/kis_tool_select_rectangular.cc b/plugins/tools/selectiontools/kis_tool_select_rectangular.cc index 1882f7fbce..c6b703cb51 100644 --- a/plugins/tools/selectiontools/kis_tool_select_rectangular.cc +++ b/plugins/tools/selectiontools/kis_tool_select_rectangular.cc @@ -1,120 +1,125 @@ /* * kis_tool_select_rectangular.cc -- part of Krita * * Copyright (c) 1999 Michael Koch * Copyright (c) 2001 John Califf * Copyright (c) 2002 Patrick Julien * 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_rectangular.h" #include "kis_painter.h" #include #include "kis_selection_options.h" #include "kis_canvas2.h" #include "kis_pixel_selection.h" #include "kis_selection_tool_helper.h" #include "kis_shape_tool_helper.h" #include "KisViewManager.h" #include "kis_selection_manager.h" __KisToolSelectRectangularLocal::__KisToolSelectRectangularLocal(KoCanvasBase * canvas) : KisToolRectangleBase(canvas, KisToolRectangleBase::SELECT, KisCursor::load("tool_rectangular_selection_cursor.png", 6, 6)) { setObjectName("tool_select_rectangular"); } +bool __KisToolSelectRectangularLocal::hasUserInteractionRunning() const +{ + return false; +} + void __KisToolSelectRectangularLocal::finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY) { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); if (!kisCanvas) return; KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Rectangle")); QRect rc(rect.normalized().toRect()); if (helper.tryDeselectCurrentSelection(pixelToView(rc), selectionAction())) { return; } if (helper.canShortcutToNoop(rc, selectionAction())) { return; } if (selectionMode() == PIXEL_SELECTION) { if (rc.isValid()) { KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection()); QPainterPath cache; if (roundCornersX > 0 || roundCornersY > 0) { cache.addRoundedRect(rc, roundCornersX, roundCornersY); } else { cache.addRect(rc); } { KisPainter painter(tmpSel); painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace())); painter.setAntiAliasPolygonFill(true); painter.setFillStyle(KisPainter::FillStyleForegroundColor); painter.setStrokeStyle(KisPainter::StrokeStyleNone); painter.paintPainterPath(cache); } tmpSel->setOutlineCache(cache); helper.selectPixelSelection(tmpSel, selectionAction()); } } else { QRectF documentRect = convertToPt(rc); const qreal docRoundCornersX = convertToPt(roundCornersX); const qreal docRoundCornersY = convertToPt(roundCornersY); helper.addSelectionShape(KisShapeToolHelper::createRectangleShape(documentRect, docRoundCornersX, docRoundCornersY), selectionAction()); } } KisToolSelectRectangular::KisToolSelectRectangular(KoCanvasBase *canvas): KisToolSelectBase<__KisToolSelectRectangularLocal>(canvas, i18n("Rectangular Selection")) { connect(&m_widgetHelper, &KisSelectionToolConfigWidgetHelper::selectionActionChanged, this, &KisToolSelectRectangular::setSelectionAction); } void KisToolSelectRectangular::setSelectionAction(int action) { changeSelectionAction(action); } QMenu* KisToolSelectRectangular::popupActionsMenu() { KisCanvas2 * kisCanvas = dynamic_cast(canvas()); Q_ASSERT(kisCanvas); return KisSelectionToolHelper::getSelectionContextMenu(kisCanvas); } diff --git a/plugins/tools/selectiontools/kis_tool_select_rectangular.h b/plugins/tools/selectiontools/kis_tool_select_rectangular.h index 4f3eda0cb2..987a9fb7dc 100644 --- a/plugins/tools/selectiontools/kis_tool_select_rectangular.h +++ b/plugins/tools/selectiontools/kis_tool_select_rectangular.h @@ -1,86 +1,90 @@ /* * kis_tool_select_rectangular.h - part of Krita * * Copyright (c) 1999 Michael Koch * 2002 Patrick Julien * * * 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_RECTANGULAR_H_ #define KIS_TOOL_SELECT_RECTANGULAR_H_ #include "KoToolFactoryBase.h" #include "kis_tool_rectangle_base.h" #include #include "kis_selection_tool_config_widget_helper.h" #include #include class __KisToolSelectRectangularLocal : public KisToolRectangleBase { Q_OBJECT public: __KisToolSelectRectangularLocal(KoCanvasBase * canvas); + bool hasUserInteractionRunning() const +; + + protected: virtual SelectionMode selectionMode() const = 0; virtual SelectionAction selectionAction() const = 0; private: void finishRect(const QRectF& rect, qreal roundCornersX, qreal roundCornersY) override; }; class KisToolSelectRectangular : public KisToolSelectBase<__KisToolSelectRectangularLocal> { Q_OBJECT public: KisToolSelectRectangular(KoCanvasBase* canvas); QMenu* popupActionsMenu() override; public Q_SLOTS: void setSelectionAction(int); }; class KisToolSelectRectangularFactory : public KoToolFactoryBase { public: KisToolSelectRectangularFactory() : KoToolFactoryBase("KisToolSelectRectangular") { setToolTip(i18n("Rectangular Selection Tool")); setSection(TOOL_TYPE_SELECTION); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); setIconName(koIconNameCStr("tool_rect_selection")); setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); setPriority(0); } ~KisToolSelectRectangularFactory() override {} KoToolBase * createTool(KoCanvasBase *canvas) override { return new KisToolSelectRectangular(canvas); } }; #endif // KIS_TOOL_SELECT_RECTANGULAR_H_