Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tool_move.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 1999 Matthias Elter <me@kde.org>
3 * SPDX-FileCopyrightText: 1999 Michael Koch <koch@kde.org>
4 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
5 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
6 * SPDX-FileCopyrightText: 2016 Michael Abrahams <miabraha@gmail.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include "kis_tool_move.h"
12
13#include <QPoint>
14
15
16#include "kis_cursor.h"
17#include "kis_selection.h"
18#include "kis_canvas2.h"
19#include "kis_image.h"
20
21#include "kis_tool_utils.h"
22#include "kis_paint_layer.h"
27#include "kis_action_registry.h"
28#include "krita_utils.h"
29
30#include <KisViewManager.h>
31#include <KisDocument.h>
32
33#include "kis_node_manager.h"
35#include "kis_signals_blocker.h"
36#include "KisAnimAutoKey.h"
37#include <boost/operators.hpp>
40
41
42struct KisToolMoveState : KisToolChangesTrackerData, boost::equality_comparable<KisToolMoveState>
43{
44 KisToolMoveState(QPoint _accumulatedOffset) : accumulatedOffset(_accumulatedOffset) {}
45 KisToolChangesTrackerData* clone() const override { return new KisToolMoveState(*this); }
46
47 bool operator ==(const KisToolMoveState &rhs) {
49 }
50
52};
53
54
56 : KisTool(canvas, KisCursor::moveCursor())
57 , m_updateCursorCompressor(100, KisSignalCompressor::FIRST_ACTIVE)
58 , m_moveShortcutsHelper(this)
59{
60 setObjectName("tool_move");
61
62 m_showCoordinatesAction = action("movetool-show-coordinates");
63 m_showCoordinatesAction = action("movetool-show-coordinates");
64 connect(&m_updateCursorCompressor, SIGNAL(timeout()), this, SLOT(resetCursorStyle()));
65
66 m_optionsWidget = new MoveToolOptionsWidget(nullptr, currentImage()->xRes(), toolId());
67
68 // See https://bugs.kde.org/show_bug.cgi?id=316896
69 QWidget *specialSpacer = new QWidget(m_optionsWidget);
70 specialSpacer->setObjectName("SpecialSpacer");
71 specialSpacer->setFixedSize(0, 0);
72 m_optionsWidget->layout()->addWidget(specialSpacer);
73
74 m_optionsWidget->setFixedHeight(m_optionsWidget->sizeHint().height());
75
77
79
80 connect(this, SIGNAL(moveInNewPosition(QPoint)), m_optionsWidget, SLOT(slotSetTranslate(QPoint)), Qt::UniqueConnection);
81}
82
88
90{
91 if (!isActive()) return;
92
93 bool canMove = true;
94
104 (m_handlesRect.isEmpty() ||
105 !m_handlesRect.translated(currentOffset()).contains(m_lastCursorPos))) {
106
108 return;
109 }
110 } else {
111 KisResourcesSnapshotSP resources =
112 new KisResourcesSnapshot(this->image(), currentNode(), canvas()->resourceManager());
114
115 KisPaintLayerSP paintLayer =
116 dynamic_cast<KisPaintLayer*>(this->currentNode().data());
117
118 const bool canUseSelectionMode =
119 paintLayer && selection &&
120 !selection->selectedRect().isEmpty() &&
121 !selection->selectedExactRect().isEmpty();
122
123 if (canUseSelectionMode) {
124 canMove = (m_currentMode == MoveSelectedLayer ? paintLayer->isEditable() : true);
125 } else {
126 KisNodeSelectionRecipe nodeSelection =
128 this->selectedNodes(),
131
132 if (nodeSelection.selectNodesToProcess().isEmpty()) {
133 canMove = false;
134 }
135 }
136 }
137
138 if (canMove) {
140 } else {
141 useCursor(Qt::ForbiddenCursor);
142 }
143}
144
145bool KisToolMove::startStrokeImpl(MoveToolMode mode, const QPoint *pos)
146{
147 KisNodeSP node;
148 KisImageSP image = this->image();
149
150 KisResourcesSnapshotSP resources =
151 new KisResourcesSnapshot(image, currentNode(), canvas()->resourceManager());
153
154 KisPaintLayerSP paintLayer =
155 dynamic_cast<KisPaintLayer*>(this->currentNode().data());
156
157
158
159 const bool canUseSelectionMode =
160 paintLayer && selection &&
161 !selection->selectedRect().isEmpty() &&
162 !selection->selectedExactRect().isEmpty();
163
164 if (pos) {
165 // finish stroke by clicking outside image bounds
166 if (m_strokeId && !image->bounds().contains(*pos)) {
167 endStroke();
168 return false;
169 }
170
171 // restart stroke when the mode has changed or the user tried to
172 // pick another layer in "layer under cursor" mode.
173 if (m_strokeId &&
174 (m_currentMode != mode ||
175 m_currentlyUsingSelection != canUseSelectionMode ||
178 !m_handlesRect.translated(currentOffset()).contains(*pos)))) {
179
180 endStroke();
181 }
182 }
183
184 if (m_strokeId) return true;
185
186
187 if (canUseSelectionMode && !nodeEditable()) {
188 // if there is a selection, it would only use the current layer anyway
189 // if the current layer is not editable, don't continue
190 return false;
191 }
192
193 KisNodeList nodes;
194
195 KisStrokeStrategy *strategy;
196
197 bool isMoveSelection = false;
198 if (canUseSelectionMode) {
200
201 MoveSelectionStrokeStrategy *moveStrategy =
202 new MoveSelectionStrokeStrategy(paintLayer,
203 selection,
204 image.data(),
205 image.data());
206
207 connect(moveStrategy,
208 SIGNAL(sigHandlesRectCalculated(const QRect&)),
209 SLOT(slotHandlesRectCalculated(const QRect&)));
210 connect(moveStrategy,
211 SIGNAL(sigStrokeStartedEmpty()),
212 SLOT(slotStrokeStartedEmpty()));
213
214 strategy = moveStrategy;
215 isMoveSelection = true;
216 nodes = {paintLayer};
217
218 } else {
219 KisNodeSelectionRecipe nodeSelection =
220 pos ?
222 this->selectedNodes(),
224 *pos) :
226
227
228 MoveStrokeStrategy *moveStrategy =
229 new MoveStrokeStrategy(nodeSelection, image.data(), image.data());
230 connect(moveStrategy,
231 SIGNAL(sigHandlesRectCalculated(const QRect&)),
232 SLOT(slotHandlesRectCalculated(const QRect&)));
233 connect(moveStrategy,
234 SIGNAL(sigStrokeStartedEmpty()),
235 SLOT(slotStrokeStartedEmpty()));
236 connect(moveStrategy,
237 SIGNAL(sigLayersPicked(const KisNodeList&)),
238 SLOT(slotStrokePickedLayers(const KisNodeList&)));
239
240 strategy = moveStrategy;
241 nodes = nodeSelection.selectedNodes;
242 }
243
244 {
245 KConfigGroup group = KSharedConfig::openConfig()->group(toolId());
246 const bool forceLodMode = group.readEntry("forceLodMode", false);
247 strategy->setForceLodModeIfPossible(forceLodMode);
248 }
249
250 // disable outline feedback until the stroke calculates
251 // correct bounding rect
252 m_handlesRect = QRect();
253 m_strokeId = image->startStroke(strategy);
256 m_currentlyUsingSelection = isMoveSelection;
258 m_accumulatedOffset = QPoint();
259
260 if (!isMoveSelection) {
262 }
263
266 }
268
269 return true;
270}
271
276
277void KisToolMove::notifyGuiAfterMove(bool showFloatingMessage)
278{
279 if (!m_optionsWidget) return;
280 if (m_handlesRect.isEmpty()) return;
281
282 const QPoint currentTopLeft = m_handlesRect.topLeft() + currentOffset();
283
285 Q_EMIT moveInNewPosition(currentTopLeft);
286
287 const bool showCoordinates = m_optionsWidget->showCoordinates();
288
289 if (showCoordinates && showFloatingMessage) {
290 KisCanvas2 *kisCanvas = static_cast<KisCanvas2*>(canvas());
291 kisCanvas->viewManager()->
292 showFloatingMessage(
293 i18nc("floating message in move tool",
294 "X: %1 px, Y: %2 px",
295 QLocale().toString(currentTopLeft.x()),
296 QLocale().toString(currentTopLeft.y())),
297 QIcon(), 1000, KisFloatingMessage::High);
298 }
299}
300
302{
303 if (!m_strokeId) return false;
304
305 bool strokeEnded = false;
306
308 endStroke();
309 strokeEnded = true;
310 }
311
312 return strokeEnded;
313}
314
316{
318
320 KisToolMoveState *lastState = dynamic_cast<KisToolMoveState*>(m_changesTracker.lastState().data());
321 if (lastState && *lastState == *newState) return;
322
324}
325
326void KisToolMove::slotHandlesRectCalculated(const QRect &handlesRect)
327{
328 m_handlesRect = handlesRect;
329 notifyGuiAfterMove(false);
330}
331
333{
338 KisCanvas2 *kisCanvas = static_cast<KisCanvas2*>(canvas());
339 kisCanvas->viewManager()->
340 showFloatingMessage(
341 i18nc("floating message in move tool",
342 "Selected area has no pixels"),
343 QIcon(), 1000, KisFloatingMessage::High);
344 }
345
351 cancelStroke();
352}
353
355{
356 if (nodes.isEmpty()) {
357 useCursor(Qt::ForbiddenCursor);
358 } else {
360 }
361}
362
364{
365 if (mode() == KisTool::PAINT_MODE) return; // Don't interact with dragging
366 if (!currentNode()) return;
367 if (!image()) return;
368 if (!currentNode()->isEditable()) return; // Don't move invisible nodes
369
370 if (startStrokeImpl(MoveSelectedLayer, nullptr)) {
372 }
373
374 // Larger movement if "shift" key is pressed.
375 qreal scale = big ? m_optionsWidget->moveScale() : 1.0;
376 qreal moveStep = m_optionsWidget->moveStep() * scale;
377
378 const QPoint offset =
379 direction == Up ? QPoint( 0, -moveStep) :
380 direction == Down ? QPoint( 0, moveStep) :
381 direction == Left ? QPoint(-moveStep, 0) :
382 QPoint( moveStep, 0) ;
383
384 m_accumulatedOffset += offset;
386
390}
391
392void KisToolMove::activate(const QSet<KoShape*> &shapes)
393{
394 KisTool::activate(shapes);
395
397
398 m_actionConnections.addConnection(action("movetool-move-up"), SIGNAL(triggered(bool)),
399 this, SLOT(slotMoveDiscreteUp()));
400 m_actionConnections.addConnection(action("movetool-move-down"), SIGNAL(triggered(bool)),
401 this, SLOT(slotMoveDiscreteDown()));
402 m_actionConnections.addConnection(action("movetool-move-left"), SIGNAL(triggered(bool)),
403 this, SLOT(slotMoveDiscreteLeft()));
404 m_actionConnections.addConnection(action("movetool-move-right"), SIGNAL(triggered(bool)),
405 this, SLOT(slotMoveDiscreteRight()));
406
407 m_actionConnections.addConnection(action("movetool-move-up-more"), SIGNAL(triggered(bool)),
408 this, SLOT(slotMoveDiscreteUpMore()));
409 m_actionConnections.addConnection(action("movetool-move-down-more"), SIGNAL(triggered(bool)),
410 this, SLOT(slotMoveDiscreteDownMore()));
411 m_actionConnections.addConnection(action("movetool-move-left-more"), SIGNAL(triggered(bool)),
412 this, SLOT(slotMoveDiscreteLeftMore()));
413 m_actionConnections.addConnection(action("movetool-move-right-more"), SIGNAL(triggered(bool)),
414 this, SLOT(slotMoveDiscreteRightMore()));
415
416 m_canvasConnections.addUniqueConnection(qobject_cast<KisCanvas2*>(canvas())->viewManager()->nodeManager(), SIGNAL(sigUiNeedChangeSelectedNodes(KisNodeList)), this, SLOT(slotNodeChanged(KisNodeList)));
417 m_canvasConnections.addUniqueConnection(qobject_cast<KisCanvas2*>(canvas())->viewManager()->selectionManager(), SIGNAL(currentSelectionChanged()), this, SLOT(slotSelectionChanged()));
418
419 connect(m_showCoordinatesAction, SIGNAL(triggered(bool)), m_optionsWidget, SLOT(setShowCoordinates(bool)), Qt::UniqueConnection);
420 connect(m_optionsWidget, SIGNAL(showCoordinatesChanged(bool)), m_showCoordinatesAction, SLOT(setChecked(bool)), Qt::UniqueConnection);
421 connect(m_optionsWidget, SIGNAL(sigSetTranslateX(int)), SLOT(moveBySpinX(int)), Qt::UniqueConnection);
422 connect(m_optionsWidget, SIGNAL(sigSetTranslateY(int)), SLOT(moveBySpinY(int)), Qt::UniqueConnection);
423 connect(m_optionsWidget, SIGNAL(sigRequestCommitOffsetChanges()), this, SLOT(commitChanges()), Qt::UniqueConnection);
424
425 connect(&m_changesTracker,
426 SIGNAL(sigConfigChanged(KisToolChangesTrackerDataSP)),
428
429
431}
432
433void KisToolMove::paint(QPainter& gc, const KoViewConverter &converter)
434{
435 Q_UNUSED(converter);
436
437 if (m_strokeId && !m_handlesRect.isEmpty() && !m_currentlyUsingSelection) {
438 QPainterPath handles;
439 handles.addRect(m_handlesRect.translated(currentOffset()));
440
441 QPainterPath path = pixelToView(handles);
442 paintToolOutline(&gc, path);
443 }
444}
445
447{
451
452 disconnect(m_showCoordinatesAction, 0, this, 0);
453 disconnect(m_optionsWidget, 0, this, 0);
454
455 endStroke();
457}
458
463
468
470{
471 if (!m_strokeId) return;
472
473 if (!m_changesTracker.canUndo()) {
474 cancelStroke();
475 } else {
477 }
478}
479
481{
482 if (!m_strokeId) return;
483
486 }
487}
488
493
498
500{
501 endAction(event);
502}
503
505{
506 // Ctrl+Right click toggles between moving current layer and moving layer w/ content
509
510 if (mode == MoveSelectedLayer) {
512 } else if (mode == MoveFirstLayer) {
514 }
515
516 startAction(event, mode);
517 } else {
518 startAction(event, MoveGroup);
519 }
520}
521
523{
524 Q_UNUSED(action);
525 continueAction(event);
526}
527
529{
530 Q_UNUSED(action);
531 endAction(event);
532}
533
545
547{
548 QPoint pos = convertToPixelCoordAndSnap(event).toPoint();
549 m_dragStart = pos;
550 m_dragPos = pos;
551
552 if (startStrokeImpl(mode, &pos)) {
554
559 }
560
561 } else {
562 event->ignore();
563 m_dragPos = QPoint();
564 m_dragStart = QPoint();
565 }
566 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
567}
568
570{
572
573 if (!m_strokeId) return;
574
575 QPoint pos = convertToPixelCoordAndSnap(event).toPoint();
576 pos = applyModifiers(event->modifiers(), pos);
577 m_dragPos = pos;
578
579 drag(pos);
581
582 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
583}
584
586{
589 if (!m_strokeId) return;
590
591 QPoint pos = convertToPixelCoordAndSnap(event).toPoint();
592 pos = applyModifiers(event->modifiers(), pos);
593 drag(pos);
594
596 m_dragStart = QPoint();
597 m_dragPos = QPoint();
599
604 }
605
607
608 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
609}
610
611void KisToolMove::drag(const QPoint& newPos)
612{
614
615 QPoint offset = m_accumulatedOffset + newPos - m_dragStart;
616
618 new MoveStrokeStrategy::Data(offset));
619}
620
622{
623 if (!m_strokeId) return;
624
627 }
628
632
633 m_strokeId.clear();
638 m_accumulatedOffset = QPoint();
639 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
640}
641
654
659
664
669
674
679
684
689
694
696{
697 if (!m_strokeId) return;
698
701 }
702
706 m_strokeId.clear();
711 m_accumulatedOffset = QPoint();
713 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
714}
715
717{
718 return m_optionsWidget;
719}
720
727
728QPoint KisToolMove::applyModifiers(Qt::KeyboardModifiers modifiers, QPoint pos)
729{
730 QPoint move = pos - m_dragStart;
731
732 // Snap to axis
733 if (modifiers & Qt::ShiftModifier) {
734 move = snapToClosestAxis(move);
735 }
736
737 // "Precision mode" - scale down movement by 1/5
738 if (modifiers & Qt::AltModifier) {
739 const qreal SCALE_FACTOR = .2;
740 move = SCALE_FACTOR * move;
741 }
742
743 return m_dragStart + move;
744}
745
747{
748 if (mode() == KisTool::PAINT_MODE || // Don't interact with dragging
749 !currentNode()->isEditable() || // Don't move invisible nodes
750 m_handlesRect.isEmpty()) {
751 return;
752 }
753
754 // starting a new stroke resets m_handlesRect and it gets updated asynchronously,
755 // but in this case no change is expected
756 int handlesRectX = m_handlesRect.x();
757
758 if (startStrokeImpl(MoveSelectedLayer, nullptr)) {
760 }
761
762 m_accumulatedOffset.rx() = newX - handlesRectX;
763
765
766 notifyGuiAfterMove(false);
768}
769
771{
772 if (mode() == KisTool::PAINT_MODE || // Don't interact with dragging
773 !currentNode()->isEditable() || // Don't move invisible nodes
774 m_handlesRect.isEmpty()) {
775 return;
776 }
777
778 // starting a new stroke resets m_handlesRect and it gets updated asynchronously,
779 // but in this case no change is expected
780 int handlesRectY = m_handlesRect.y();
781
782 if (startStrokeImpl(MoveSelectedLayer, nullptr)) {
784 }
785
786 m_accumulatedOffset.ry() = newY - handlesRectY;
787
789
790 notifyGuiAfterMove(false);
792}
793
795{
796 KisResourcesSnapshotSP resources =
797 new KisResourcesSnapshot(image(), currentNode(), canvas()->resourceManager());
799
801 selection, this);
802 connect(job,
803 SIGNAL(sigCalculationFinished(const QRect&)),
804 SLOT(slotHandlesRectCalculated(const QRect &)));
805
806 KisImageSP image = this->image();
807 image->addSpontaneousJob(job);
808
809 notifyGuiAfterMove(false);
810}
811
813{
814 if (m_strokeId && !tryEndPreviousStroke(nodes)) {
815 return;
816 }
818}
819
825
827{
830
832 actions << actionRegistry->makeQAction("movetool-show-coordinates", this);
833
834 return actions;
835
836}
QAction * makeQAction(const QString &name, QObject *parent=0)
static KisActionRegistry * instance()
void startUpdateStream(KisStrokesFacade *strokesFacade, KisStrokeId strokeId)
KisViewManager * viewManager() const
bool cancelStroke(KisStrokeId id) override
void addJob(KisStrokeId id, KisStrokeJobData *data) override
KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) override
QRect bounds() const override
void addSpontaneousJob(KisSpontaneousJob *spontaneousJob)
void endStroke(KisStrokeId id) override
KisNodeList selectNodesToProcess() const
The KisResourcesSnapshot class takes a snapshot of the various resources like colors and settings use...
KisSelectionSP activeSelection() const
void addUniqueConnection(Sender sender, Signal signal, Receiver receiver, Method method)
void addConnection(Sender sender, Signal signal, Receiver receiver, Method method, Qt::ConnectionType type=Qt::AutoConnection)
void setForceLodModeIfPossible(bool forceLodModeIfPossible)
void commitConfig(KisToolChangesTrackerDataSP state)
KisToolChangesTrackerDataSP lastState() const
QList< QAction * > createActionsImpl() override
createActionsImpl should be reimplemented if the tool needs any actions. The actions should have a va...
QPoint applyModifiers(Qt::KeyboardModifiers modifiers, QPoint pos)
void setShowCoordinates(bool value)
void continuePrimaryAction(KoPointerEvent *event) override
void slotMoveDiscreteLeftMore()
void requestUndoDuringStroke() override
void activate(const QSet< KoShape * > &shapes) override
KisAsynchronousStrokeUpdateHelper m_asyncUpdateHelper
MoveToolMode moveToolMode() const
~KisToolMove() override
void moveBySpinX(int newX)
void moveInNewPosition(QPoint)
bool tryEndPreviousStroke(const KisNodeList &nodes)
void notifyGuiAfterMove(bool showFloatingMessage=true)
void slotMoveDiscreteRight()
void paint(QPainter &gc, const KoViewConverter &converter) override
void deactivate() override
void slotMoveDiscreteUp()
void moveDiscrete(MoveDirection direction, bool big)
void drag(const QPoint &newPos)
void slotHandlesRectCalculated(const QRect &handlesRect)
KisSignalAutoConnectionsStore m_canvasConnections
void slotMoveDiscreteLeft()
void moveBySpinY(int newY)
void slotStrokeStartedEmpty()
KisSignalCompressor m_updateCursorCompressor
QPoint currentOffset() const
bool m_currentlyUsingSelection
void slotMoveDiscreteRightMore()
QWidget * createOptionWidget() override
void endPrimaryAction(KoPointerEvent *event) override
void continueAction(KoPointerEvent *event)
void cancelStroke()
void slotTrackerChangedConfig(KisToolChangesTrackerDataSP state)
void mouseMoveEvent(KoPointerEvent *event) override
MoveToolMode m_currentMode
KisToolUtils::MoveShortcutsHelper m_moveShortcutsHelper
KisToolMove(KoCanvasBase *canvas)
void requestStrokeCancellation() override
QPoint m_accumulatedOffset
Total offset including multiple clicks, up/down/left/right keys, etc. added together.
void beginPrimaryAction(KoPointerEvent *event) override
void resetCursorStyle() override
void requestStrokeEnd() override
void startAction(KoPointerEvent *event, MoveToolMode mode)
QPoint m_dragStart
Point where current cursor dragging began.
void continueAlternateAction(KoPointerEvent *event, AlternateAction action) override
KisNodeList m_currentlyProcessingNodes
QAction * m_showCoordinatesAction
KisSignalAutoConnectionsStore m_actionConnections
void endAction(KoPointerEvent *event)
void slotMoveDiscreteDownMore()
void slotNodeChanged(const KisNodeList &nodes)
void requestRedoDuringStroke() override
void slotMoveDiscreteUpMore()
QRect m_handlesRect
KisToolChangesTracker m_changesTracker
void requestHandlesRectUpdate()
void endAlternateAction(KoPointerEvent *event, AlternateAction action) override
MoveToolOptionsWidget * m_optionsWidget
void beginAlternateAction(KoPointerEvent *event, AlternateAction action) override
bool startStrokeImpl(MoveToolMode mode, const QPoint *pos)
void slotStrokePickedLayers(const KisNodeList &nodes)
QPoint m_lastCursorPos
KisStrokeId m_strokeId
void commitChanges()
void slotMoveDiscreteDown()
void slotSelectionChanged()
QList< QAction * > createActionsImpl() override
createActionsImpl should be reimplemented if the tool needs any actions. The actions should have a va...
static QList< QAction * > createActions()
Qt::KeyboardModifiers modifiers() const
Q_INVOKABLE QString toolId() const
virtual KoToolSelection * selection()
void useCursor(const QCursor &cursor)
QAction * action(const QString &name) const
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
PointType snapToClosestAxis(PointType P)
Definition kis_global.h:199
#define CHECK_MODE_SANITY_OR_RETURN(_mode)
Definition kis_tool.h:27
bool compareListsUnordered(const QList< T > &a, const QList< T > &b)
bool isEditable(bool checkVisibility=true) const
KisToolMoveState(QPoint _accumulatedOffset)
KisToolChangesTrackerData * clone() const override
bool operator==(const KisToolMoveState &rhs)
QPointF convertToPixelCoord(KoPointerEvent *e)
Definition kis_tool.cc:189
KisNodeList selectedNodes() const
Definition kis_tool.cc:376
virtual ToolMode mode() const
Definition kis_tool.cc:407
KisImageWSP currentImage()
Definition kis_tool.cc:393
virtual void resetCursorStyle()
Definition kis_tool.cc:613
bool nodeEditable()
Checks checks if the current node is editable.
Definition kis_tool.cc:651
QPointF pixelToView(const QPoint &pixelCoord) const
Definition kis_tool.cc:269
bool isActive
Definition kis_tool.h:44
KisNodeSP currentNode() const
Definition kis_tool.cc:370
void mouseMoveEvent(KoPointerEvent *event) override
Definition kis_tool.cc:520
void activate(const QSet< KoShape * > &shapes) override
Definition kis_tool.cc:93
void paintToolOutline(QPainter *painter, const KisOptimizedBrushOutline &path)
Definition kis_tool.cc:589
void deactivate() override
Definition kis_tool.cc:131
KisImageWSP image() const
Definition kis_tool.cc:332
@ PAINT_MODE
Definition kis_tool.h:300
@ HOVER_MODE
Definition kis_tool.h:299
QPointF convertToPixelCoordAndSnap(KoPointerEvent *e, const QPointF &offset=QPointF(), bool useModifiers=true)
Definition kis_tool.cc:214
AlternateAction
Definition kis_tool.h:134
@ SampleFgNode
Definition kis_tool.h:137
@ SampleBgImage
Definition kis_tool.h:140
virtual void setMode(ToolMode mode)
Definition kis_tool.cc:403
KisCanvas2 * canvas