[calligra/krita-new-move-tool-kazakov] krita: Made the move tool iterational

Boudewijn Rempt boud at valdyas.org
Fri Nov 9 08:19:34 UTC 2012


I'm going to test this now, but because the http://git.reviewboard.kde.org/r/107205/ is part of it, we should also discuss it on calligra-devel. Please also find the bug numbers for the bugs that you refert to -- because that helps the discussion in the wider calligra community.,

On Wednesday 07 November 2012 Nov, Dmitry Kazakov wrote:
> Git commit 40bdd4ab49f58ca46ff8c275878556572116c566 by Dmitry Kazakov.
> Committed on 07/11/2012 at 14:34.
> Pushed by dkazakov into branch 'krita-new-move-tool-kazakov'.
> 
> Made the move tool iterational
> 
> Now the tool does not create new layers and does not create
> numerous undo commands. It works in an iterational way: you move
> the node (or selection) as many times as you wish. After the moving
> done and you switch the tool (or apply any other action) the move
> stroke will be finished and added to your undo history.
> 
> Please test it in 'krita-new-move-tool-kazakov' branch.
> 
> BUG:298584
> CCMAIL:kimageshop at kde.org
> 
> M  +30   -0    krita/image/kis_image.cc
> M  +43   -0    krita/image/kis_image.h
> M  +8    -0    krita/image/kis_stroke_strategy_undo_command_based.cpp
> M  +6    -1    krita/image/kis_stroke_strategy_undo_command_based.h
> M  +1    -0    krita/plugins/tools/defaulttools/CMakeLists.txt
> M  +63   -110  krita/plugins/tools/defaulttools/kis_tool_move.cc
> M  +5    -1    krita/plugins/tools/defaulttools/kis_tool_move.h
> A  +132  -0    krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp     [License: GPL (v2+)]
> A  +49   -0    krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h     [License: GPL (v2+)]
> M  +2    -0    krita/ui/kis_doc2_p.h
> M  +8    -0    krita/ui/kis_filter_handler.cc
> M  +12   -0    krita/ui/tool/kis_tool.cc
> M  +14   -0    krita/ui/tool/kis_tool.h
> 
> http://commits.kde.org/calligra/40bdd4ab49f58ca46ff8c275878556572116c566
> 
> diff --git a/krita/image/kis_image.cc b/krita/image/kis_image.cc
> index 0336f01..077d638 100644
> --- a/krita/image/kis_image.cc
> +++ b/krita/image/kis_image.cc
> @@ -149,6 +149,11 @@ KisImage::~KisImage()
>      dbgImage << "deleting kisimage" << objectName();
>  
>      /**
> +     * Request the tools to end currently running strokes
> +     */
> +    waitForDone();
> +
> +    /**
>       * First delete the nodes, while strokes
>       * and undo are still alive
>       */
> @@ -334,6 +339,8 @@ bool KisImage::locked() const
>  void KisImage::barrierLock()
>  {
>      if (!locked()) {
> +        requestStrokeEnd();
> +
>          if (m_d->scheduler) {
>              m_d->scheduler->barrierLock();
>          }
> @@ -366,6 +373,8 @@ bool KisImage::tryBarrierLock()
>  void KisImage::lock()
>  {
>      if (!locked()) {
> +        requestStrokeEnd();
> +
>          if (m_d->scheduler) {
>              m_d->scheduler->lock();
>          }
> @@ -1321,6 +1330,8 @@ KisImageSignalRouter* KisImage::signalRouter()
>  
>  void KisImage::waitForDone()
>  {
> +    requestStrokeEnd();
> +
>      if (m_d->scheduler) {
>          m_d->scheduler->waitForDone();
>      }
> @@ -1328,6 +1339,15 @@ void KisImage::waitForDone()
>  
>  KisStrokeId KisImage::startStroke(KisStrokeStrategy *strokeStrategy)
>  {
> +    /**
> +     * Ask open strokes to end gracefully. All the strokes clients
> +     * (including the one calling this method right now) will get
> +     * a notification that they should probably end their strokes.
> +     * However this is purely their choice whether to end a stroke
> +     * or not.
> +     */
> +    requestStrokeEnd();
> +
>      KisStrokeId id;
>  
>      if (m_d->scheduler) {
> @@ -1360,6 +1380,16 @@ bool KisImage::cancelStroke(KisStrokeId id)
>      return result;
>  }
>  
> +void KisImage::requestStrokeCancellation()
> +{
> +    emit sigStrokeCancellationRequested();
> +}
> +
> +void KisImage::requestStrokeEnd()
> +{
> +    emit sigStrokeEndRequested();
> +}
> +
>  void KisImage::refreshGraph(KisNodeSP root)
>  {
>      refreshGraph(root, bounds(), bounds());
> diff --git a/krita/image/kis_image.h b/krita/image/kis_image.h
> index ebd27a7..e2601cb 100644
> --- a/krita/image/kis_image.h
> +++ b/krita/image/kis_image.h
> @@ -576,6 +576,31 @@ signals:
>       */
>      void sigLayersChangedAsync();
>  
> +    /**
> +     * Emitted when the UI has requested the cancellation of
> +     * the stroke. The point is, we cannot cancel the stroke
> +     * without its creator knowing about it (which most probably
> +     * cause a crash), so we just forward this request from the UI
> +     * to the creator of the stroke.
> +     *
> +     * If your tool supports cancelling of its work in the middle
> +     * of operation, just listen to this signal and cancel
> +     * the stroke when it comes
> +     */
> +    void sigStrokeCancellationRequested();
> +
> +    /**
> +     * Emitted when the image decides that the stroke should better
> +     * be ended. The point is, we cannot just end the stroke
> +     * without its creator knowing about it (which most probably
> +     * cause a crash), so we just forward this request from the UI
> +     * to the creator of the stroke.
> +     *
> +     * If your tool supports long  strokes that may involve multiple
> +     * mouse actions in one stroke, just listen to this signal and
> +     * end the stroke when it comes.
> +     */
> +    void sigStrokeEndRequested();
>  
>  public slots:
>      KisCompositeProgressProxy* compositeProgressProxy();
> @@ -606,7 +631,25 @@ public slots:
>      void refreshGraph(KisNodeSP root, const QRect& rc, const QRect &cropRect);
>      void initialRefreshGraph();
>  
> +    /**
> +     * This method is be called by the UI (*not* by the creator
> +     * of the stroke) when it thinks current stroke should be
> +     * cancelled. If the creator of the stroke supports cancelling
> +     * of the stroke, it will be notified about the request and
> +     * the stroke will be cancelled
> +     */
> +    void requestStrokeCancellation();
> +
>  private:
> +    /**
> +     * This method is called when image decides that the sroke
> +     * should be ended. If the creator of the stroke supports it,
> +     * it will be notified and the stroke will be cancelled
> +     */
> +    void requestStrokeEnd();
> +
> +private:
> +
>      KisImage(const KisImage& rhs);
>      KisImage& operator=(const KisImage& rhs);
>      void init(KisUndoStore *undoStore, qint32 width, qint32 height, const KoColorSpace * colorSpace);
> diff --git a/krita/image/kis_stroke_strategy_undo_command_based.cpp b/krita/image/kis_stroke_strategy_undo_command_based.cpp
> index 3eb998c..e3f802e 100644
> --- a/krita/image/kis_stroke_strategy_undo_command_based.cpp
> +++ b/krita/image/kis_stroke_strategy_undo_command_based.cpp
> @@ -97,6 +97,14 @@ void KisStrokeStrategyUndoCommandBased::doStrokeCallback(KisStrokeJobData *data)
>      notifyCommandDone(d->command, d->sequentiality(), d->exclusivity());
>  }
>  
> +void KisStrokeStrategyUndoCommandBased::runAndSaveCommand(KUndo2CommandSP command,
> +                                                          KisStrokeJobData::Sequentiality sequentiality,
> +                                                          KisStrokeJobData::Exclusivity exclusivity)
> +{
> +    command->redo();
> +    notifyCommandDone(command, sequentiality, exclusivity);
> +}
> +
>  void KisStrokeStrategyUndoCommandBased::notifyCommandDone(KUndo2CommandSP command,
>                                                            KisStrokeJobData::Sequentiality sequentiality,
>                                                            KisStrokeJobData::Exclusivity exclusivity)
> diff --git a/krita/image/kis_stroke_strategy_undo_command_based.h b/krita/image/kis_stroke_strategy_undo_command_based.h
> index 0751493..da13b11 100644
> --- a/krita/image/kis_stroke_strategy_undo_command_based.h
> +++ b/krita/image/kis_stroke_strategy_undo_command_based.h
> @@ -79,12 +79,17 @@ public:
>      void doStrokeCallback(KisStrokeJobData *data);
>  
>  protected:
> -    void executeCommand(KUndo2CommandSP command, bool undo);
> +    void runAndSaveCommand(KUndo2CommandSP command,
> +                           KisStrokeJobData::Sequentiality sequentiality,
> +                           KisStrokeJobData::Exclusivity exclusivity);
>      void notifyCommandDone(KUndo2CommandSP command,
>                             KisStrokeJobData::Sequentiality sequentiality,
>                             KisStrokeJobData::Exclusivity exclusivity);
>  
>  private:
> +    void executeCommand(KUndo2CommandSP command, bool undo);
> +
> +private:
>      bool m_undo;
>      KUndo2CommandSP m_initCommand;
>      KUndo2CommandSP m_finishCommand;
> diff --git a/krita/plugins/tools/defaulttools/CMakeLists.txt b/krita/plugins/tools/defaulttools/CMakeLists.txt
> index d10daea..6a38fc0 100644
> --- a/krita/plugins/tools/defaulttools/CMakeLists.txt
> +++ b/krita/plugins/tools/defaulttools/CMakeLists.txt
> @@ -15,6 +15,7 @@ set(kritadefaulttools_PART_SRCS
>      kis_tool_path.cc
>      kis_tool_move.cc
>      strokes/move_stroke_strategy.cpp
> +    strokes/move_selection_stroke_strategy.cpp
>      kis_tool_multihand.cpp
>      )
>  
> diff --git a/krita/plugins/tools/defaulttools/kis_tool_move.cc b/krita/plugins/tools/defaulttools/kis_tool_move.cc
> index fc20250..f2f4c4c 100644
> --- a/krita/plugins/tools/defaulttools/kis_tool_move.cc
> +++ b/krita/plugins/tools/defaulttools/kis_tool_move.cc
> @@ -22,29 +22,17 @@
>  #include "kis_tool_move.h"
>  
>  #include <QPoint>
> -#include <kundo2command.h>
> -
> -#include <klocale.h>
>  
>  #include "KoColorSpace.h"
> -#include "KoColor.h"
> -#include "KoCompositeOp.h"
>  
>  #include "kis_cursor.h"
> -#include "kis_layer.h"
>  #include "kis_selection.h"
> -#include "kis_paint_layer.h"
> -#include "kis_group_layer.h"
> -#include "kis_painter.h"
>  #include "kis_canvas2.h"
> -#include "kis_view2.h"
> -#include "kis_node_manager.h"
>  #include "kis_image.h"
>  
> -#include <kis_transaction.h>
> -#include <commands/kis_image_layer_add_command.h>
> -#include <commands/kis_deselect_global_selection_command.h>
> +#include "kis_paint_layer.h"
>  #include "strokes/move_stroke_strategy.h"
> +#include "strokes/move_selection_stroke_strategy.h"
>  
>  KisToolMove::KisToolMove(KoCanvasBase * canvas)
>          :  KisTool(canvas, KisCursor::moveCursor())
> @@ -55,6 +43,7 @@ KisToolMove::KisToolMove(KoCanvasBase * canvas)
>  
>  KisToolMove::~KisToolMove()
>  {
> +    endStroke();
>  }
>  
>  void KisToolMove::paint(QPainter& gc, const KoViewConverter &converter)
> @@ -63,6 +52,22 @@ void KisToolMove::paint(QPainter& gc, const KoViewConverter &converter)
>      Q_UNUSED(converter);
>  }
>  
> +void KisToolMove::deactivate()
> +{
> +    endStroke();
> +    KisTool::deactivate();
> +}
> +
> +void KisToolMove::requestStrokeEnd()
> +{
> +    endStroke();
> +}
> +
> +void KisToolMove::requestStrokeCancellation()
> +{
> +    cancelStroke();
> +}
> +
>  // recursively search a node with a non-transparent pixel
>  KisNodeSP findNode(KisNodeSP node, const QPoint &point, bool wholeGroup)
>  {
> @@ -99,44 +104,6 @@ KisNodeSP findNode(KisNodeSP node, const QPoint &point, bool wholeGroup)
>      return foundNode;
>  }
>  
> -KisLayerSP createSelectionCopy(KisLayerSP srcLayer, KisSelectionSP selection, KisImageWSP image, KisStrokeId strokeId)
> -{
> -    QRect copyRect = srcLayer->extent() | selection->selectedRect();
> -
> -    KisPaintDeviceSP device = new KisPaintDevice(srcLayer->colorSpace());
> -    KisPainter gc(device);
> -    gc.setSelection(selection);
> -    gc.setCompositeOp(COMPOSITE_OVER);
> -    gc.setOpacity(OPACITY_OPAQUE_U8);
> -    gc.bitBlt(copyRect.topLeft(), srcLayer->paintDevice(), copyRect);
> -    gc.end();
> -
> -    KisTransaction transaction("cut", srcLayer->paintDevice());
> -    srcLayer->paintDevice()->clearSelection(selection);
> -    image->addJob(strokeId,
> -                  new KisStrokeStrategyUndoCommandBased::Data(transaction.endAndTake()));
> -
> -    image->addJob(strokeId,
> -        new KisStrokeStrategyUndoCommandBased::Data(
> -            new KisDeselectGlobalSelectionCommand(image)));
> -
> -    KisPaintLayerSP newLayer =
> -        new KisPaintLayer(image, srcLayer->name() + " (moved)",
> -                          srcLayer->opacity(), device);
> -
> -    newLayer->setCompositeOp(srcLayer->compositeOpId());
> -
> -    // No updates while we adding a layer, so let's be "exclusive"
> -    image->addJob(strokeId,
> -        new KisStrokeStrategyUndoCommandBased::Data(
> -            new KisImageLayerAddCommand(image, newLayer,
> -                                        srcLayer->parent(), srcLayer),
> -            false,
> -            KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE));
> -
> -    return newLayer;
> -}
> -
>  void KisToolMove::mousePressEvent(KoPointerEvent *event)
>  {
>      if(PRESS_CONDITION_OM(event, KisTool::HOVER_MODE,
> @@ -145,13 +112,15 @@ void KisToolMove::mousePressEvent(KoPointerEvent *event)
>  
>          setMode(KisTool::PAINT_MODE);
>  
> +        QPoint pos = convertToPixelCoord(event).toPoint();
> +        m_dragStart = pos;
> +        m_lastDragPos = m_dragStart;
> +
> +        if (m_strokeId) return;
> +
>          KisNodeSP node;
> -        KisImageWSP image = currentImage();
> -        if (!image || !image->rootLayer()) {
> -            return;
> -        }
> +        KisImageSP image = this->image();
>  
> -        QPoint pos = convertToPixelCoord(event).toPoint();
>          KisSelectionSP selection = currentSelection();
>  
>          if(!m_optionsWidget->radioSelectedLayer->isChecked() &&
> @@ -161,52 +130,33 @@ void KisToolMove::mousePressEvent(KoPointerEvent *event)
>                  (m_optionsWidget->radioGroup->isChecked() ||
>                   event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier));
>  
> -            node = findNode(image->rootLayer(), pos, wholeGroup);
> +            node = findNode(image->root(), pos, wholeGroup);
>          }
>  
> -        if(!node) {
> -            node = currentNode();
> -            if (!node) {
> -                return;
> -            }
> -        }
> +        if((!node && !(node = currentNode())) || !node->isEditable()) return;
>  
> -        if (!nodeEditable()) {
> -            return;
> -        }
>  
> -        /**
> -         * NOTE: we use deferred initialization of the node of
> -         * the stroke here. First, we set the node to null in
> -         * the constructor, use jobs of undo-command-based
> -         * strategy to initialize the stroke and then we set up
> -         * the node itself.
> -         */
> -        MoveStrokeStrategy *strategy =
> -            new MoveStrokeStrategy(0, image.data(),
> -                                   image->postExecutionUndoAdapter(),
> -                                   image->undoAdapter());
> +        KisStrokeStrategy *strategy;
>  
> -        m_strokeId = image->startStroke(strategy);
> +        KisPaintLayerSP paintLayer =
> +            dynamic_cast<KisPaintLayer*>(node.data());
>  
> -        if (node->inherits("KisLayer") &&
> -            !node->inherits("KisGroupLayer") &&
> -            node->paintDevice() &&
> -            selection &&
> +        if (paintLayer && selection &&
>              !selection->isTotallyUnselected(image->bounds())) {
>  
> -            KisLayerSP oldLayer = dynamic_cast<KisLayer*>(node.data());
> -            KisLayerSP newLayer = createSelectionCopy(oldLayer, selection, image, m_strokeId);
> -
> -            node = newLayer;
> +            strategy =
> +                new MoveSelectionStrokeStrategy(paintLayer,
> +                                                selection,
> +                                                image.data(),
> +                                                image->postExecutionUndoAdapter());
> +        } else {
> +            strategy =
> +                new MoveStrokeStrategy(node, image.data(),
> +                                       image->postExecutionUndoAdapter(),
> +                                       image->undoAdapter());
>          }
>  
> -        // the deferred initialization itself
> -        strategy->setNode(node);
> -        strategy = 0;
> -
> -        m_dragStart = pos;
> -        m_lastDragPos = m_dragStart;
> +        m_strokeId = image->startStroke(strategy);
>      }
>      else {
>          KisTool::mousePressEvent(event);
> @@ -216,16 +166,11 @@ void KisToolMove::mousePressEvent(KoPointerEvent *event)
>  void KisToolMove::mouseMoveEvent(KoPointerEvent *event)
>  {
>      if(MOVE_CONDITION(event, KisTool::PAINT_MODE)) {
> -        if (!m_strokeId)
> -        {
> -            return;
> -        }
> +        if (!m_strokeId) return;
>  
>          QPoint pos = convertToPixelCoord(event).toPoint();
>          pos = applyModifiers(event->modifiers(), pos);
>          drag(pos);
> -
> -        notifyModified();
>      }
>      else {
>          KisTool::mouseMoveEvent(event);
> @@ -236,21 +181,11 @@ void KisToolMove::mouseReleaseEvent(KoPointerEvent *event)
>  {
>      if(RELEASE_CONDITION(event, KisTool::PAINT_MODE, Qt::LeftButton)) {
>          setMode(KisTool::HOVER_MODE);
> -
> -        if (!m_strokeId)
> -        {
> -            return;
> -        }
> +        if (!m_strokeId) return;
>  
>          QPoint pos = convertToPixelCoord(event).toPoint();
>          pos = applyModifiers(event->modifiers(), pos);
>          drag(pos);
> -
> -        KisImageWSP image = currentImage();
> -        image->endStroke(m_strokeId);
> -        m_strokeId.clear();
> -
> -        currentImage()->setModified();
>      }
>      else {
>          KisTool::mouseReleaseEvent(event);
> @@ -268,6 +203,24 @@ void KisToolMove::drag(const QPoint& newPos)
>                    new MoveStrokeStrategy::Data(offset));
>  }
>  
> +void KisToolMove::endStroke()
> +{
> +    if (!m_strokeId) return;
> +
> +    KisImageWSP image = currentImage();
> +    image->endStroke(m_strokeId);
> +    m_strokeId.clear();
> +}
> +
> +void KisToolMove::cancelStroke()
> +{
> +    if (!m_strokeId) return;
> +
> +    KisImageWSP image = currentImage();
> +    image->cancelStroke(m_strokeId);
> +    m_strokeId.clear();
> +}
> +
>  QWidget* KisToolMove::createOptionWidget()
>  {
>      m_optionsWidget = new MoveToolOptionsWidget(0);
> diff --git a/krita/plugins/tools/defaulttools/kis_tool_move.h b/krita/plugins/tools/defaulttools/kis_tool_move.h
> index 4ec1788..4d11710 100644
> --- a/krita/plugins/tools/defaulttools/kis_tool_move.h
> +++ b/krita/plugins/tools/defaulttools/kis_tool_move.h
> @@ -54,6 +54,9 @@ public:
>      KisToolMove(KoCanvasBase * canvas);
>      virtual ~KisToolMove();
>  
> +    void deactivate();
> +    void requestStrokeEnd();
> +    void requestStrokeCancellation();
>  
>  public:
>  
> @@ -67,7 +70,8 @@ public:
>  
>  private:
>      void drag(const QPoint& newPos);
> -
> +    void endStroke();
> +    void cancelStroke();
>      QPoint applyModifiers(Qt::KeyboardModifiers modifiers, QPoint pos);
>  
>  private:
> diff --git a/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp
> new file mode 100644
> index 0000000..9089f02
> --- /dev/null
> +++ b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp
> @@ -0,0 +1,132 @@
> +/*
> + *  Copyright (c) 2012 Dmitry Kazakov <dimula73 at gmail.com>
> + *
> + *  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 "move_selection_stroke_strategy.h"
> +
> +#include <KoColorSpace.h>
> +#include "kis_image.h"
> +#include "kis_paint_layer.h"
> +#include "kis_painter.h"
> +#include "kis_transaction.h"
> +#include <commands/kis_deselect_global_selection_command.h>
> +
> +
> +MoveSelectionStrokeStrategy::MoveSelectionStrokeStrategy(KisPaintLayerSP paintLayer,
> +                                                         KisSelectionSP selection,
> +                                                         KisUpdatesFacade *updatesFacade,
> +                                                         KisPostExecutionUndoAdapter *undoAdapter)
> +    : KisStrokeStrategyUndoCommandBased("Move Selection Stroke", false, undoAdapter),
> +      m_paintLayer(paintLayer),
> +      m_selection(selection),
> +      m_updatesFacade(updatesFacade),
> +      m_undoAdapter(undoAdapter)
> +{
> +    enableJob(KisSimpleStrokeStrategy::JOB_INIT);
> +    enableJob(KisSimpleStrokeStrategy::JOB_FINISH);
> +    enableJob(KisSimpleStrokeStrategy::JOB_CANCEL);
> +}
> +
> +void MoveSelectionStrokeStrategy::initStrokeCallback()
> +{
> +    KisStrokeStrategyUndoCommandBased::initStrokeCallback();
> +
> +    KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice();
> +
> +    KisPaintDeviceSP movedDevice = new KisPaintDevice(m_paintLayer.data(), paintDevice->colorSpace());
> +
> +
> +    QRect copyRect = m_selection->selectedRect();
> +    KisPainter gc(movedDevice);
> +    gc.setSelection(m_selection);
> +    gc.bitBlt(copyRect.topLeft(), paintDevice, copyRect);
> +    gc.end();
> +
> +    KisTransaction cutTransaction(name(), paintDevice);
> +    paintDevice->clearSelection(m_selection);
> +    runAndSaveCommand(KUndo2CommandSP(cutTransaction.endAndTake()),
> +                      KisStrokeJobData::SEQUENTIAL,
> +                      KisStrokeJobData::NORMAL);
> +
> +    KisIndirectPaintingSupport *indirect =
> +        static_cast<KisIndirectPaintingSupport*>(m_paintLayer.data());
> +    indirect->setTemporaryTarget(movedDevice);
> +    indirect->setTemporaryCompositeOp(paintDevice->colorSpace()->compositeOp(COMPOSITE_OVER));
> +    indirect->setTemporaryOpacity(OPACITY_OPAQUE_U8);
> +
> +    m_updatesFacade->blockUpdates();
> +    runAndSaveCommand(
> +        KUndo2CommandSP(new KisDeselectGlobalSelectionCommand(m_paintLayer->image())),
> +        KisStrokeJobData::SEQUENTIAL,
> +        KisStrokeJobData::EXCLUSIVE);
> +    m_updatesFacade->unblockUpdates();
> +}
> +
> +void MoveSelectionStrokeStrategy::finishStrokeCallback()
> +{
> +    KisIndirectPaintingSupport *indirect =
> +        static_cast<KisIndirectPaintingSupport*>(m_paintLayer.data());
> +
> +    KisTransaction transaction(name(), m_paintLayer->paintDevice());
> +    indirect->mergeToLayer(m_paintLayer, (KisUndoAdapter*)0, "");
> +    runAndSaveCommand(KUndo2CommandSP(transaction.endAndTake()),
> +                      KisStrokeJobData::SEQUENTIAL,
> +                      KisStrokeJobData::NORMAL);
> +
> +    indirect->setTemporaryTarget(0);
> +
> +    KisStrokeStrategyUndoCommandBased::finishStrokeCallback();
> +}
> +
> +void MoveSelectionStrokeStrategy::cancelStrokeCallback()
> +{
> +    KisIndirectPaintingSupport *indirect =
> +        static_cast<KisIndirectPaintingSupport*>(m_paintLayer.data());
> +
> +    QRegion dirtyRegion = indirect->temporaryTarget()->region();
> +
> +    indirect->setTemporaryTarget(0);
> +
> +    m_paintLayer->setDirty(dirtyRegion);
> +
> +    KisStrokeStrategyUndoCommandBased::cancelStrokeCallback();
> +}
> +
> +#include "move_stroke_strategy.h"
> +
> +void MoveSelectionStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
> +{
> +    MoveStrokeStrategy::Data *d = dynamic_cast<MoveStrokeStrategy::Data*>(data);
> +
> +    if (d) {
> +        KisIndirectPaintingSupport *indirect =
> +            static_cast<KisIndirectPaintingSupport*>(m_paintLayer.data());
> +
> +        KisPaintDeviceSP movedDevice = indirect->temporaryTarget();
> +
> +        QRegion dirtyRegion = movedDevice->region();
> +        dirtyRegion |= dirtyRegion.translated(d->offset);
> +
> +        movedDevice->setX(movedDevice->x() + d->offset.x());
> +        movedDevice->setY(movedDevice->y() + d->offset.y());
> +
> +        m_paintLayer->setDirty(dirtyRegion);
> +    } else {
> +        KisStrokeStrategyUndoCommandBased::doStrokeCallback(data);
> +    }
> +}
> +
> diff --git a/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h
> new file mode 100644
> index 0000000..440f2bf
> --- /dev/null
> +++ b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h
> @@ -0,0 +1,49 @@
> +/*
> + *  Copyright (c) 2012 Dmitry Kazakov <dimula73 at gmail.com>
> + *
> + *  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 __MOVE_SELECTION_STROKE_STRATEGY_H
> +#define __MOVE_SELECTION_STROKE_STRATEGY_H
> +
> +#include "kis_stroke_strategy_undo_command_based.h"
> +#include "kis_types.h"
> +
> +class KisPostExecutionUndoAdapter;
> +class KisUpdatesFacade;
> +
> +
> +class MoveSelectionStrokeStrategy : public KisStrokeStrategyUndoCommandBased
> +{
> +public:
> +    MoveSelectionStrokeStrategy(KisPaintLayerSP paintLayer,
> +                                KisSelectionSP selection,
> +                                KisUpdatesFacade *updatesFacade,
> +                                KisPostExecutionUndoAdapter *undoAdapter);
> +
> +    void initStrokeCallback();
> +    void finishStrokeCallback();
> +    void cancelStrokeCallback();
> +    void doStrokeCallback(KisStrokeJobData *data);
> +
> +private:
> +    KisPaintLayerSP m_paintLayer;
> +    KisSelectionSP m_selection;
> +    KisUpdatesFacade *m_updatesFacade,;
> +    KisPostExecutionUndoAdapter *m_undoAdapter;
> +};
> +
> +#endif /* __MOVE_SELECTION_STROKE_STRATEGY_H */
> diff --git a/krita/ui/kis_doc2_p.h b/krita/ui/kis_doc2_p.h
> index 19a3e5f..e7ec1c4 100644
> --- a/krita/ui/kis_doc2_p.h
> +++ b/krita/ui/kis_doc2_p.h
> @@ -32,6 +32,7 @@ public:
>  
>      void setIndex(int idx) {
>          KisImageWSP image = this->image();
> +        image->requestStrokeCancellation();
>          if(image->tryBarrierLock()) {
>              KUndo2Stack::setIndex(idx);
>              image->unlock();
> @@ -40,6 +41,7 @@ public:
>  
>      void undo() {
>          KisImageWSP image = this->image();
> +        image->requestStrokeCancellation();
>          if(image->tryBarrierLock()) {
>              KUndo2Stack::undo();
>              image->unlock();
> diff --git a/krita/ui/kis_filter_handler.cc b/krita/ui/kis_filter_handler.cc
> index 2705b9d..e472a40 100644
> --- a/krita/ui/kis_filter_handler.cc
> +++ b/krita/ui/kis_filter_handler.cc
> @@ -102,6 +102,14 @@ KisFilterHandler::~KisFilterHandler()
>  
>  void KisFilterHandler::showDialog()
>  {
> +    /**
> +     * HACK ALERT:
> +     * Until filters are ported to strokes, there should be a barrier
> +     * to finish all the running strokes in the system
> +     */
> +    m_d->view->image()->barrierLock();
> +    m_d->view->image()->unlock();
> +
>      KisPaintDeviceSP dev = m_d->view->activeDevice();
>      if (dev->colorSpace()->willDegrade(m_d->filter->colorSpaceIndependence())) {
>          // Warning bells!
> diff --git a/krita/ui/tool/kis_tool.cc b/krita/ui/tool/kis_tool.cc
> index 86b04ba..cde18c0 100644
> --- a/krita/ui/tool/kis_tool.cc
> +++ b/krita/ui/tool/kis_tool.cc
> @@ -161,14 +161,26 @@ void KisTool::activate(ToolActivation, const QSet<KoShape*> &)
>  
>      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(sigStrokeCancellationRequested()), SLOT(requestStrokeCancellation()));
> +    connect(image(), SIGNAL(sigStrokeEndRequested()), SLOT(requestStrokeEnd()));
>  }
>  
>  void KisTool::deactivate()
>  {
> +    disconnect(image().data(), SIGNAL(sigStrokeCancellationRequested()));
> +    disconnect(image().data(), SIGNAL(sigStrokeEndRequested()));
>      disconnect(actions().value("toggle_fg_bg"), 0, this, 0);
>      disconnect(actions().value("reset_fg_bg"), 0, this, 0);
>  }
>  
> +void KisTool::requestStrokeCancellation()
> +{
> +}
> +
> +void KisTool::requestStrokeEnd()
> +{
> +}
> +
>  void KisTool::resourceChanged(int key, const QVariant & v)
>  {
>  
> diff --git a/krita/ui/tool/kis_tool.h b/krita/ui/tool/kis_tool.h
> index 073c9cb..a2ea4b6 100644
> --- a/krita/ui/tool/kis_tool.h
> +++ b/krita/ui/tool/kis_tool.h
> @@ -224,6 +224,20 @@ protected slots:
>       */
>      virtual void resetCursorStyle();
>  
> +    /**
> +     * 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 slots:
>      void slotToggleFgBg();
>      void slotResetFgBg();
> _______________________________________________
> kimageshop mailing list
> kimageshop at kde.org
> https://mail.kde.org/mailman/listinfo/kimageshop
> 
> 


-- 
Boudewijn Rempt
http://www.valdyas.org, http://www.krita.org, http://www.boudewijnrempt.nl


More information about the kimageshop mailing list