[krita/kazakov/svg-loading] /: Implement smooth switching between Selection and Editing tools

Dmitry Kazakov null at kde.org
Fri Feb 17 19:21:41 UTC 2017


Git commit eba0ca815785eaf8a4fd280363b51c3eaf16c04a by Dmitry Kazakov.
Committed on 17/02/2017 at 19:21.
Pushed by dkazakov into branch 'kazakov/svg-loading'.

Implement smooth switching between Selection and Editing tools

Now possible shortcuts are possible:

* Selection <- Enter    -> Editing
* Selection <- Esc      -- Editing
* Selection <- DblClick -> Editing
* Just select the tool in the toolbox

This path also implements selection of the shapes in
the Editing tool.

CC:kimageshop at kde.org

M  +16   -0    libs/flake/KoSelection.cpp
M  +6    -0    libs/flake/KoSelection.h
M  +0    -28   libs/flake/KoShapeManager.cpp
M  +0    -8    libs/flake/KoShapeManager.h
M  +16   -0    libs/flake/KoToolBase.cpp
M  +25   -0    libs/flake/KoToolBase.h
M  +2    -10   libs/flake/KoToolManager.cpp
M  +22   -1    libs/flake/KoToolProxy.cpp
M  +10   -0    libs/flake/KoToolProxy.h
M  +54   -26   libs/flake/tools/KoPathTool.cpp
M  +19   -29   libs/flake/tools/KoPathTool.h
M  +1    -1    libs/flake/tools/KoPathToolFactory.cpp
M  +2    -3    libs/ui/canvas/kis_canvas2.cpp
M  +7    -0    libs/ui/canvas/kis_tool_proxy.cpp
M  +1    -0    libs/ui/canvas/kis_tool_proxy.h
M  +1    -22   libs/ui/tool/kis_tool.cc
M  +0    -25   libs/ui/tool/kis_tool.h
M  +16   -24   plugins/tools/defaulttool/defaulttool/DefaultTool.cpp
M  +6    -5    plugins/tools/defaulttool/defaulttool/DefaultTool.h

https://commits.kde.org/krita/eba0ca815785eaf8a4fd280363b51c3eaf16c04a

diff --git a/libs/flake/KoSelection.cpp b/libs/flake/KoSelection.cpp
index 81f1ce44dea..923560a5281 100644
--- a/libs/flake/KoSelection.cpp
+++ b/libs/flake/KoSelection.cpp
@@ -194,6 +194,22 @@ const QList<KoShape *> KoSelection::selectedEditableShapes() const
     return shapes;
 }
 
+const QList<KoShape *> KoSelection::selectedEditableShapesAndDelegates() const
+{
+    QList<KoShape*> shapes;
+    Q_FOREACH (KoShape *shape, selectedShapes()) {
+        QSet<KoShape *> delegates = shape->toolDelegates();
+        if (delegates.isEmpty()) {
+            shapes.append(shape);
+        } else {
+            Q_FOREACH (KoShape *delegatedShape, delegates) {
+                shapes.append(delegatedShape);
+            }
+        }
+    }
+    return shapes;
+}
+
 bool KoSelection::isSelected(const KoShape *shape) const
 {
     Q_D(const KoSelection);
diff --git a/libs/flake/KoSelection.h b/libs/flake/KoSelection.h
index 0fa4a018e19..e5919cebedb 100644
--- a/libs/flake/KoSelection.h
+++ b/libs/flake/KoSelection.h
@@ -113,6 +113,12 @@ public:
     const QList<KoShape*> selectedEditableShapes() const;
 
     /**
+     * Same as selectedEditableShapes() but also includes shapes delegates.
+     * Used for
+     */
+    const QList<KoShape*> selectedEditableShapesAndDelegates() const;
+
+    /**
      * Return the first selected shape, or 0 if there is nothing selected.
      * @param strip if StrippedSelection, the returned list will not include any children
      *    of a grouped shape if the group-parent is itself also in the set.
diff --git a/libs/flake/KoShapeManager.cpp b/libs/flake/KoShapeManager.cpp
index 691d6c4b69b..92d4cfd8345 100644
--- a/libs/flake/KoShapeManager.cpp
+++ b/libs/flake/KoShapeManager.cpp
@@ -580,34 +580,6 @@ KoSelection *KoShapeManager::selection() const
     return d->selection;
 }
 
-void KoShapeManager::suggestChangeTool(KoPointerEvent *event)
-{
-    QList<KoShape*> shapes;
-
-    KoShape *clicked = shapeAt(event->point);
-    if (clicked) {
-        if (! selection()->isSelected(clicked)) {
-            selection()->deselectAll();
-            selection()->select(clicked);
-        }
-        shapes.append(clicked);
-    }
-
-    QList<KoShape*> shapes2;
-    foreach (KoShape *shape, shapes) {
-        QSet<KoShape*> delegates = shape->toolDelegates();
-        if (delegates.isEmpty()) {
-            shapes2.append(shape);
-        } else {
-            foreach (KoShape *delegatedShape, delegates) {
-                shapes2.append(delegatedShape);
-            }
-        }
-    }
-    KoToolManager::instance()->switchToolRequested(
-        KoToolManager::instance()->preferredToolForSelection(shapes2));
-}
-
 void KoShapeManager::setPaintingStrategy(KoShapeManagerPaintingStrategy *strategy)
 {
     delete d->strategy;
diff --git a/libs/flake/KoShapeManager.h b/libs/flake/KoShapeManager.h
index ca164c82bbd..afcb51002de 100644
--- a/libs/flake/KoShapeManager.h
+++ b/libs/flake/KoShapeManager.h
@@ -173,14 +173,6 @@ public:
     void notifyShapeChanged(KoShape *shape);
 
     /**
-     * Switch to editing the shape that is at the position of the event.
-     * This method will check select a shape at the event position and switch to the default tool
-     * for that shape, or switch to the default tool if there is no shape at the position.
-     * @param event the event that holds the point where to look for a shape.
-     */
-    void suggestChangeTool(KoPointerEvent *event);
-
-    /**
      * Paint a shape
      *
      * @param shape the shape to paint
diff --git a/libs/flake/KoToolBase.cpp b/libs/flake/KoToolBase.cpp
index 45a7a7529db..4bb43b541fe 100644
--- a/libs/flake/KoToolBase.cpp
+++ b/libs/flake/KoToolBase.cpp
@@ -393,6 +393,22 @@ bool KoToolBase::isInTextMode() const
     return d->isInTextMode;
 }
 
+void KoToolBase::requestUndoDuringStroke()
+{
+    /**
+     * Default implementation just cancells the stroke
+     */
+    requestStrokeCancellation();
+}
+
+void KoToolBase::requestStrokeCancellation()
+{
+}
+
+void KoToolBase::requestStrokeEnd()
+{
+}
+
 bool KoToolBase::maskSyntheticEvents() const
 {
     Q_D(const KoToolBase);
diff --git a/libs/flake/KoToolBase.h b/libs/flake/KoToolBase.h
index 16a5df8c6d2..6cd05324293 100644
--- a/libs/flake/KoToolBase.h
+++ b/libs/flake/KoToolBase.h
@@ -332,6 +332,31 @@ public:
       */
     bool isInTextMode() const;
 
+    /**
+     * Called when the user requested undo while the stroke is
+     * active. If you tool supports undo of the part of its actions,
+     * override this method and do the needed work there.
+     *
+     * NOTE: Default implementation forwards this request to
+     *       requestStrokeCancellation() method, so that the stroke
+     *       would be cancelled.
+     */
+    virtual void requestUndoDuringStroke();
+
+    /**
+     * Called when the user requested the cancellation of the current
+     * stroke. If you tool supports cancelling, override this method
+     * and do the needed work there
+     */
+    virtual void requestStrokeCancellation();
+
+    /**
+     * Called when the image decided that the stroke should better be
+     * ended. If you tool supports long strokes, override this method
+     * and do the needed work there
+     */
+    virtual void requestStrokeEnd();
+
 public Q_SLOTS:
 
     /**
diff --git a/libs/flake/KoToolManager.cpp b/libs/flake/KoToolManager.cpp
index 174f70ce86c..a71e6a1884e 100644
--- a/libs/flake/KoToolManager.cpp
+++ b/libs/flake/KoToolManager.cpp
@@ -382,8 +382,6 @@ QString KoToolManager::preferredToolForSelection(const QList<KoShape*> &shapes)
     Q_FOREACH (ToolHelper *helper, d->tools) {
         if (helper->priority() >= prio)
             continue;
-        if (helper->section() == KoToolFactoryBase::mainToolType())
-            continue;
 
         bool toolWillWork = false;
         foreach (const QString &type, types) {
@@ -392,6 +390,7 @@ QString KoToolManager::preferredToolForSelection(const QList<KoShape*> &shapes)
                 break;
             }
         }
+
         if (toolWillWork) {
             toolType = helper->id();
             prio = helper->priority();
@@ -681,14 +680,7 @@ void KoToolManager::Private::postSwitchTool(bool temporary)
         KoSelection *selection = canvasData->activeTool->canvas()->shapeManager()->selection();
         Q_ASSERT(selection);
 
-        Q_FOREACH (KoShape *shape, selection->selectedShapes()) {
-            QSet<KoShape*> delegates = shape->toolDelegates();
-            if (delegates.isEmpty()) { // no delegates, just the orig shape
-                shapesToOperateOn << shape;
-            } else {
-                shapesToOperateOn += delegates;
-            }
-        }
+        shapesToOperateOn = QSet<KoShape*>::fromList(selection->selectedEditableShapesAndDelegates());
     }
 
     if (canvasData->canvas->canvas()) {
diff --git a/libs/flake/KoToolProxy.cpp b/libs/flake/KoToolProxy.cpp
index c126521ffdb..0b71e3580a2 100644
--- a/libs/flake/KoToolProxy.cpp
+++ b/libs/flake/KoToolProxy.cpp
@@ -557,7 +557,7 @@ QStringList KoToolProxy::supportedPasteMimeTypes() const
 void KoToolProxy::deleteSelection()
 {
     if (d->activeTool)
-        return d->activeTool->deleteSelection();
+        d->activeTool->deleteSelection();
 }
 
 void KoToolProxy::processEvent(QEvent *e) const
@@ -571,6 +571,27 @@ void KoToolProxy::processEvent(QEvent *e) const
     }
 }
 
+void KoToolProxy::requestUndoDuringStroke()
+{
+    if (d->activeTool) {
+        d->activeTool->requestUndoDuringStroke();
+    }
+}
+
+void KoToolProxy::requestStrokeCancellation()
+{
+    if (d->activeTool) {
+        d->activeTool->requestStrokeCancellation();
+    }
+}
+
+void KoToolProxy::requestStrokeEnd()
+{
+    if (d->activeTool) {
+        d->activeTool->requestStrokeEnd();
+    }
+}
+
 KoToolProxyPrivate *KoToolProxy::priv()
 {
     return d;
diff --git a/libs/flake/KoToolProxy.h b/libs/flake/KoToolProxy.h
index 8b14b7b4475..234fbdfe168 100644
--- a/libs/flake/KoToolProxy.h
+++ b/libs/flake/KoToolProxy.h
@@ -162,6 +162,16 @@ public:
     /// \internal
     KoToolProxyPrivate *priv();
 
+protected Q_SLOTS:
+    /// Forwarded to the current KoToolBase
+    void requestUndoDuringStroke();
+
+    /// Forwarded to the current KoToolBase
+    void requestStrokeCancellation();
+
+    /// Forwarded to the current KoToolBase
+    void requestStrokeEnd();
+
 Q_SIGNALS:
     /**
      * A tool can have a selection that is copy-able, this signal is emitted when that status changes.
diff --git a/libs/flake/tools/KoPathTool.cpp b/libs/flake/tools/KoPathTool.cpp
index 8a7bc209d62..fbf0996c498 100644
--- a/libs/flake/tools/KoPathTool.cpp
+++ b/libs/flake/tools/KoPathTool.cpp
@@ -106,6 +106,7 @@ KoPathTool::KoPathTool(KoCanvasBase *canvas)
         , m_handleRadius(3)
         , m_activeSegment(0)
         , m_currentStrategy(0)
+        , m_activatedTemporarily(false)
 {
     QActionGroup *points = new QActionGroup(this);
     // m_pointTypeGroup->setExclusive(true);
@@ -491,9 +492,23 @@ void KoPathTool::mousePressEvent(KoPointerEvent *event)
                 delete m_activeSegment;
                 m_activeSegment = 0;
             } else {
-                Q_ASSERT(m_currentStrategy == 0);
-                m_currentStrategy = new KoPathPointRubberSelectStrategy(this, event->point);
-                event->accept();
+
+                KoShapeManager *shapeManager = canvas()->shapeManager();
+                KoSelection *selection = shapeManager->selection();
+
+                KoShape *shape = shapeManager->shapeAt(event->point, KoFlake::ShapeOnTop);
+                if (shape && !selection->isSelected(shape)) {
+
+                    if (!(event->modifiers() & Qt::ShiftModifier)) {
+                        selection->deselectAll();
+                    }
+
+                    selection->select(shape);
+                } else {
+                    KIS_ASSERT_RECOVER_RETURN(m_currentStrategy == 0);
+                    m_currentStrategy = new KoPathPointRubberSelectStrategy(this, event->point);
+                    event->accept();
+                }
             }
         }
     }
@@ -745,6 +760,8 @@ void KoPathTool::mouseDoubleClickEvent(KoPointerEvent *event)
         }
         updateActions();
         event->accept();
+    } else if (!m_activeHandle && !m_activeSegment && m_activatedTemporarily) {
+        emit done();
     }
 }
 
@@ -800,11 +817,30 @@ KoPathTool::PathSegment* KoPathTool::segmentAtPoint(const QPointF &point)
 void KoPathTool::activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes)
 {
     Q_D(KoToolBase);
-    Q_UNUSED(toolActivation);
+
+    m_activatedTemporarily = toolActivation == TemporaryActivation;
+
     // retrieve the actual global handle radius
     m_handleRadius = handleRadius();
     d->canvas->snapGuide()->reset();
 
+    useCursor(m_selectCursor);
+    connect(d->canvas->shapeManager()->selection(), SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()));
+
+    initializeWithShapes(shapes.toList());
+}
+
+void KoPathTool::slotSelectionChanged()
+{
+    Q_D(KoToolBase);
+    QList<KoShape*> shapes =
+        d->canvas->shapeManager()->selection()->selectedEditableShapesAndDelegates();
+
+    initializeWithShapes(shapes);
+}
+
+void KoPathTool::initializeWithShapes(const QList<KoShape*> shapes)
+{
     repaintDecorations();
     QList<KoPathShape*> selectedShapes;
     Q_FOREACH (KoShape *shape, shapes) {
@@ -818,32 +854,12 @@ void KoPathTool::activate(ToolActivation toolActivation, const QSet<KoShape*> &s
             selectedShapes.append(pathShape);
         }
     }
-    if (selectedShapes.isEmpty()) {
-        emit done();
-        return;
-    }
+
     m_pointSelection.setSelectedShapes(selectedShapes);
-    useCursor(m_selectCursor);
-    connect(d->canvas->shapeManager()->selection(), SIGNAL(selectionChanged()), this, SLOT(activate()));
     updateOptionsWidget();
     updateActions();
 }
 
-void KoPathTool::activate()
-{
-    Q_D(KoToolBase);
-    QSet<KoShape*> shapes;
-    Q_FOREACH (KoShape *shape, d->canvas->shapeManager()->selection()->selectedShapes()) {
-        QSet<KoShape*> delegates = shape->toolDelegates();
-        if (delegates.isEmpty()) {
-            shapes << shape;
-        } else {
-            shapes += delegates;
-        }
-    }
-    activate(DefaultActivation, shapes);
-}
-
 void KoPathTool::updateOptionsWidget()
 {
     PathToolOptionWidget::Types type;
@@ -888,7 +904,7 @@ void KoPathTool::updateActions()
 void KoPathTool::deactivate()
 {
     Q_D(KoToolBase);
-    disconnect(d->canvas->shapeManager()->selection(), SIGNAL(selectionChanged()), this, SLOT(activate()));
+    disconnect(d->canvas->shapeManager()->selection(), SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()));
     m_pointSelection.clear();
     m_pointSelection.setSelectedShapes(QList<KoPathShape*>());
     delete m_activeHandle;
@@ -942,3 +958,15 @@ KoToolSelection * KoPathTool::selection()
 {
     return &m_pointSelection;
 }
+
+void KoPathTool::requestStrokeCancellation()
+{
+    requestStrokeEnd();
+}
+
+void KoPathTool::requestStrokeEnd()
+{
+    if (m_activatedTemporarily) {
+        emit done();
+    }
+}
diff --git a/libs/flake/tools/KoPathTool.h b/libs/flake/tools/KoPathTool.h
index 95ab452b604..adbc0dd7d75 100644
--- a/libs/flake/tools/KoPathTool.h
+++ b/libs/flake/tools/KoPathTool.h
@@ -46,34 +46,20 @@ public:
     explicit KoPathTool(KoCanvasBase *canvas);
     ~KoPathTool();
 
-    /// reimplemented
-    virtual void paint(QPainter &painter, const KoViewConverter &converter);
-
-    /// reimplemented
-    virtual void repaintDecorations();
-
-    /// reimplemented
-    virtual void mousePressEvent(KoPointerEvent *event);
-    /// reimplemented
-    virtual void mouseMoveEvent(KoPointerEvent *event);
-    /// reimplemented
-    virtual void mouseReleaseEvent(KoPointerEvent *event);
-    /// reimplemented
-    virtual void keyPressEvent(QKeyEvent *event);
-    /// reimplemented
-    virtual void keyReleaseEvent(QKeyEvent *event);
-    /// reimplemented
-    virtual void mouseDoubleClickEvent(KoPointerEvent *event);
-    /// reimplemented
-    virtual void activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes);
-    /// reimplemented
-    virtual void deactivate();
-
-    /// reimplemented
-    virtual void deleteSelection();
-
-    /// reimplemented
-    virtual KoToolSelection* selection();
+    void paint(QPainter &painter, const KoViewConverter &converter) override;
+    void repaintDecorations() override;
+    void mousePressEvent(KoPointerEvent *event) override;
+    void mouseMoveEvent(KoPointerEvent *event) override;
+    void mouseReleaseEvent(KoPointerEvent *event) override;
+    void keyPressEvent(QKeyEvent *event) override;
+    void keyReleaseEvent(QKeyEvent *event) override;
+    void mouseDoubleClickEvent(KoPointerEvent *event) override;
+    void activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes) override;
+    void deactivate() override;
+    void deleteSelection() override;
+    KoToolSelection* selection() override;
+    void requestStrokeCancellation() override;
+    void requestStrokeEnd() override;
 
     /// repaints the specified rect
     void repaint(const QRectF &repaintRect);
@@ -109,7 +95,10 @@ private Q_SLOTS:
     void updateActions();
     void pointToLine();
     void pointToCurve();
-    void activate();
+    void slotSelectionChanged();
+
+private:
+    void initializeWithShapes(const QList<KoShape*> shapes);
 
 protected:
     KoPathToolSelection m_pointSelection; ///< the point selection
@@ -145,6 +134,7 @@ private:
     QAction *m_actionMergePoints;
     QAction *m_actionConvertToPath;
     QCursor m_moveCursor;
+    bool m_activatedTemporarily;
 
     Q_DECLARE_PRIVATE(KoToolBase)
 };
diff --git a/libs/flake/tools/KoPathToolFactory.cpp b/libs/flake/tools/KoPathToolFactory.cpp
index 9079d8cfc56..81596f9a801 100644
--- a/libs/flake/tools/KoPathToolFactory.cpp
+++ b/libs/flake/tools/KoPathToolFactory.cpp
@@ -31,7 +31,7 @@ KoPathToolFactory::KoPathToolFactory()
     setSection(mainToolType());
     setIconName(koIconNameCStr("shape_handling"));
     setPriority(1);
-    setActivationShapeId("flake/always");
+    setActivationShapeId("flake/always,KoPathShape");
 }
 
 KoPathToolFactory::~KoPathToolFactory()
diff --git a/libs/ui/canvas/kis_canvas2.cpp b/libs/ui/canvas/kis_canvas2.cpp
index ca631680974..86960950bb4 100644
--- a/libs/ui/canvas/kis_canvas2.cpp
+++ b/libs/ui/canvas/kis_canvas2.cpp
@@ -148,8 +148,6 @@ KisCanvas2::KisCanvas2(KisCoordinatesConverter *coordConverter, KoCanvasResource
 
     m_d->updateSignalCompressor.setDelay(10);
     m_d->updateSignalCompressor.setMode(KisSignalCompressor::FIRST_ACTIVE);
-
-
 }
 
 void KisCanvas2::setup()
@@ -455,9 +453,10 @@ void KisCanvas2::createCanvas(bool useOpenGL)
 
 void KisCanvas2::initializeImage()
 {
-    KisImageWSP image = m_d->view->image();
+    KisImageSP image = m_d->view->image();
 
     m_d->coordinatesConverter->setImage(image);
+    m_d->toolProxy.initializeImage(image);
 
     connect(image, SIGNAL(sigImageUpdated(QRect)), SLOT(startUpdateCanvasProjection(QRect)), Qt::DirectConnection);
     connect(this, SIGNAL(sigCanvasCacheUpdated()), SLOT(updateCanvasProjection()));
diff --git a/libs/ui/canvas/kis_tool_proxy.cpp b/libs/ui/canvas/kis_tool_proxy.cpp
index 255511c2aee..dd0263bbd27 100644
--- a/libs/ui/canvas/kis_tool_proxy.cpp
+++ b/libs/ui/canvas/kis_tool_proxy.cpp
@@ -30,6 +30,13 @@ KisToolProxy::KisToolProxy(KoCanvasBase *canvas, QObject *parent)
 {
 }
 
+void KisToolProxy::initializeImage(KisImageSP image)
+{
+    connect(image, SIGNAL(sigUndoDuringStrokeRequested()), SLOT(requestUndoDuringStroke()), Qt::UniqueConnection);
+    connect(image, SIGNAL(sigStrokeCancellationRequested()), SLOT(requestStrokeCancellation()), Qt::UniqueConnection);
+    connect(image, SIGNAL(sigStrokeEndRequested()), SLOT(requestStrokeEnd()), Qt::UniqueConnection);
+}
+
 QPointF KisToolProxy::tabletToDocument(const QPointF &globalPos)
 {
     const QPointF pos = globalPos - QPointF(canvas()->canvasWidget()->mapToGlobal(QPoint(0, 0)));
diff --git a/libs/ui/canvas/kis_tool_proxy.h b/libs/ui/canvas/kis_tool_proxy.h
index 08ca79dd043..97f7dfee84e 100644
--- a/libs/ui/canvas/kis_tool_proxy.h
+++ b/libs/ui/canvas/kis_tool_proxy.h
@@ -34,6 +34,7 @@ public:
 
 public:
     KisToolProxy(KoCanvasBase *canvas, QObject *parent = 0);
+    void initializeImage(KisImageSP image);
 
     void forwardHoverEvent(QEvent *event);
 
diff --git a/libs/ui/tool/kis_tool.cc b/libs/ui/tool/kis_tool.cc
index 5eb901ff1d6..05dcf85fdf4 100644
--- a/libs/ui/tool/kis_tool.cc
+++ b/libs/ui/tool/kis_tool.cc
@@ -153,9 +153,7 @@ void KisTool::activate(ToolActivation toolActivation, const QSet<KoShape*> &shap
 
     connect(actions().value("toggle_fg_bg"), SIGNAL(triggered()), SLOT(slotToggleFgBg()), Qt::UniqueConnection);
     connect(actions().value("reset_fg_bg"), SIGNAL(triggered()), SLOT(slotResetFgBg()), Qt::UniqueConnection);
-    connect(image(), SIGNAL(sigUndoDuringStrokeRequested()), SLOT(requestUndoDuringStroke()), Qt::UniqueConnection);
-    connect(image(), SIGNAL(sigStrokeCancellationRequested()), SLOT(requestStrokeCancellation()), Qt::UniqueConnection);
-    connect(image(), SIGNAL(sigStrokeEndRequested()), SLOT(requestStrokeEnd()), Qt::UniqueConnection);
+
 
     d->m_isActive = true;
     emit isActiveChanged();
@@ -165,9 +163,6 @@ void KisTool::deactivate()
 {
     bool result = true;
 
-    result &= disconnect(image().data(), SIGNAL(sigUndoDuringStrokeRequested()), this, 0);
-    result &= disconnect(image().data(), SIGNAL(sigStrokeCancellationRequested()), this, 0);
-    result &= disconnect(image().data(), SIGNAL(sigStrokeEndRequested()), this, 0);
     result &= disconnect(actions().value("toggle_fg_bg"), 0, this, 0);
     result &= disconnect(actions().value("reset_fg_bg"), 0, this, 0);
 
@@ -180,22 +175,6 @@ void KisTool::deactivate()
     emit isActiveChanged();
 }
 
-void KisTool::requestUndoDuringStroke()
-{
-    /**
-     * Default implementation just cancells the stroke
-     */
-    requestStrokeCancellation();
-}
-
-void KisTool::requestStrokeCancellation()
-{
-}
-
-void KisTool::requestStrokeEnd()
-{
-}
-
 void KisTool::canvasResourceChanged(int key, const QVariant & v)
 {
     switch (key) {
diff --git a/libs/ui/tool/kis_tool.h b/libs/ui/tool/kis_tool.h
index 0f321ab8bcb..5fd99384493 100644
--- a/libs/ui/tool/kis_tool.h
+++ b/libs/ui/tool/kis_tool.h
@@ -331,31 +331,6 @@ protected Q_SLOTS:
      */
     virtual void resetCursorStyle();
 
-    /**
-     * Called when the user requested undo while the stroke is
-     * active. If you tool supports undo of the part of its actions,
-     * override this method and do the needed work there.
-     *
-     * NOTE: Default implementation forwards this request to
-     *       requestStrokeCancellation() method, so that the stroke
-     *       would be cancelled.
-     */
-    virtual void requestUndoDuringStroke();
-
-    /**
-     * Called when the user requested the cancellation of the current
-     * stroke. If you tool supports cancelling, override this method
-     * and do the needed work there
-     */
-    virtual void requestStrokeCancellation();
-
-    /**
-     * Called when the image decided that the stroke should better be
-     * ended. If you tool supports long strokes, override this method
-     * and do the needed work there
-     */
-    virtual void requestStrokeEnd();
-
 private Q_SLOTS:
     void slotToggleFgBg();
     void slotResetFgBg();
diff --git a/plugins/tools/defaulttool/defaulttool/DefaultTool.cpp b/plugins/tools/defaulttool/defaulttool/DefaultTool.cpp
index 4d01a6d7180..02713f87d6e 100644
--- a/plugins/tools/defaulttool/defaulttool/DefaultTool.cpp
+++ b/plugins/tools/defaulttool/defaulttool/DefaultTool.cpp
@@ -716,34 +716,20 @@ void DefaultTool::mouseReleaseEvent(KoPointerEvent *event)
 
 void DefaultTool::mouseDoubleClickEvent(KoPointerEvent *event)
 {
-    QList<KoShape *> shapes;
-    Q_FOREACH (KoShape *shape, koSelection()->selectedShapes()) {
-        if (shape->boundingRect().contains(event->point) && // first 'cheap' check
-                shape->outline().contains(event->point)) { // this is more expensive but weeds out the almost hits
-            shapes.append(shape);
-        }
-    }
-    if (shapes.count() == 0) { // nothing in the selection was clicked on.
-        KoShape *shape = canvas()->shapeManager()->shapeAt(event->point, KoFlake::ShapeOnTop);
-        if (shape) {
-            shapes.append(shape);
-        } // there used to be guides... :'''(
-    }
+    KoShapeManager *shapeManager = canvas()->shapeManager();
+    KoSelection *selection = shapeManager->selection();
 
-    QList<KoShape *> shapes2;
-    foreach (KoShape *shape, shapes) {
-        QSet<KoShape *> delegates = shape->toolDelegates();
-        if (delegates.isEmpty()) {
-            shapes2.append(shape);
-        } else {
-            foreach (KoShape *delegatedShape, delegates) {
-                shapes2.append(delegatedShape);
-            }
+    KoShape *shape = shapeManager->shapeAt(event->point, KoFlake::ShapeOnTop);
+    if (shape && !selection->isSelected(shape)) {
+
+        if (!(event->modifiers() & Qt::ShiftModifier)) {
+            selection->deselectAll();
         }
+
+        selection->select(shape);
     }
 
-    KoToolManager::instance()->switchToolRequested(
-        KoToolManager::instance()->preferredToolForSelection(shapes2));
+    requestStrokeEnd();
 }
 
 bool DefaultTool::moveSelection(int direction, Qt::KeyboardModifiers modifiers)
@@ -1416,3 +1402,9 @@ uint DefaultTool::editableShapesCount(const QList<KoShape *> &shapes)
 
     return count;
 }
+
+void DefaultTool::requestStrokeEnd()
+{
+    QList<KoShape *> shapes = koSelection()->selectedEditableShapesAndDelegates();
+    emit activateTemporary(KoToolManager::instance()->preferredToolForSelection(shapes));
+}
diff --git a/plugins/tools/defaulttool/defaulttool/DefaultTool.h b/plugins/tools/defaulttool/defaulttool/DefaultTool.h
index 001f57b8ba0..f83097682fd 100644
--- a/plugins/tools/defaulttool/defaulttool/DefaultTool.h
+++ b/plugins/tools/defaulttool/defaulttool/DefaultTool.h
@@ -117,12 +117,13 @@ private Q_SLOTS:
 
 public: // Events
 
-    virtual void mousePressEvent(KoPointerEvent *event);
-    virtual void mouseMoveEvent(KoPointerEvent *event);
-    virtual void mouseReleaseEvent(KoPointerEvent *event);
-    virtual void mouseDoubleClickEvent(KoPointerEvent *event);
+    void mousePressEvent(KoPointerEvent *event) override;
+    void mouseMoveEvent(KoPointerEvent *event) override;
+    void mouseReleaseEvent(KoPointerEvent *event) override;
+    void mouseDoubleClickEvent(KoPointerEvent *event) override;
 
-    virtual void keyPressEvent(QKeyEvent *event);
+    void keyPressEvent(QKeyEvent *event) override;
+    void requestStrokeEnd() override;
 
 protected:
     QList<QPointer<QWidget> > createOptionWidgets();


More information about the kimageshop mailing list