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{
59 setObjectName("tool_move");
60
61 m_showCoordinatesAction = action("movetool-show-coordinates");
62 m_showCoordinatesAction = action("movetool-show-coordinates");
63 connect(&m_updateCursorCompressor, SIGNAL(timeout()), this, SLOT(resetCursorStyle()));
64
65 m_optionsWidget = new MoveToolOptionsWidget(nullptr, currentImage()->xRes(), toolId());
66
67 // See https://bugs.kde.org/show_bug.cgi?id=316896
68 QWidget *specialSpacer = new QWidget(m_optionsWidget);
69 specialSpacer->setObjectName("SpecialSpacer");
70 specialSpacer->setFixedSize(0, 0);
71 m_optionsWidget->layout()->addWidget(specialSpacer);
72
73 m_optionsWidget->setFixedHeight(m_optionsWidget->sizeHint().height());
74
76
78
79 connect(this, SIGNAL(moveInNewPosition(QPoint)), m_optionsWidget, SLOT(slotSetTranslate(QPoint)), Qt::UniqueConnection);
80}
81
87
89{
90 if (!isActive()) return;
91
92 bool canMove = true;
93
103 (m_handlesRect.isEmpty() ||
104 !m_handlesRect.translated(currentOffset()).contains(m_lastCursorPos))) {
105
107 return;
108 }
109 } else {
110 KisResourcesSnapshotSP resources =
111 new KisResourcesSnapshot(this->image(), currentNode(), canvas()->resourceManager());
113
114 KisPaintLayerSP paintLayer =
115 dynamic_cast<KisPaintLayer*>(this->currentNode().data());
116
117 const bool canUseSelectionMode =
118 paintLayer && selection &&
119 !selection->selectedRect().isEmpty() &&
120 !selection->selectedExactRect().isEmpty();
121
122 if (canUseSelectionMode) {
123 canMove = (m_currentMode == MoveSelectedLayer ? paintLayer->isEditable() : true);
124 } else {
125 KisNodeSelectionRecipe nodeSelection =
127 this->selectedNodes(),
130
131 if (nodeSelection.selectNodesToProcess().isEmpty()) {
132 canMove = false;
133 }
134 }
135 }
136
137 if (canMove) {
139 } else {
140 useCursor(Qt::ForbiddenCursor);
141 }
142}
143
144bool KisToolMove::startStrokeImpl(MoveToolMode mode, const QPoint *pos)
145{
146 KisNodeSP node;
147 KisImageSP image = this->image();
148
149 KisResourcesSnapshotSP resources =
150 new KisResourcesSnapshot(image, currentNode(), canvas()->resourceManager());
152
153 KisPaintLayerSP paintLayer =
154 dynamic_cast<KisPaintLayer*>(this->currentNode().data());
155
156
157
158 const bool canUseSelectionMode =
159 paintLayer && selection &&
160 !selection->selectedRect().isEmpty() &&
161 !selection->selectedExactRect().isEmpty();
162
163 if (pos) {
164 // finish stroke by clicking outside image bounds
165 if (m_strokeId && !image->bounds().contains(*pos)) {
166 endStroke();
167 return false;
168 }
169
170 // restart stroke when the mode has changed or the user tried to
171 // pick another layer in "layer under cursor" mode.
172 if (m_strokeId &&
173 (m_currentMode != mode ||
174 m_currentlyUsingSelection != canUseSelectionMode ||
177 !m_handlesRect.translated(currentOffset()).contains(*pos)))) {
178
179 endStroke();
180 }
181 }
182
183 if (m_strokeId) return true;
184
185
186 if (canUseSelectionMode && !nodeEditable()) {
187 // if there is a selection, it would only use the current layer anyway
188 // if the current layer is not editable, don't continue
189 return false;
190 }
191
192 KisNodeList nodes;
193
194 KisStrokeStrategy *strategy;
195
196 bool isMoveSelection = false;
197 if (canUseSelectionMode) {
199
200 MoveSelectionStrokeStrategy *moveStrategy =
201 new MoveSelectionStrokeStrategy(paintLayer,
202 selection,
203 image.data(),
204 image.data());
205
206 connect(moveStrategy,
207 SIGNAL(sigHandlesRectCalculated(const QRect&)),
208 SLOT(slotHandlesRectCalculated(const QRect&)));
209 connect(moveStrategy,
210 SIGNAL(sigStrokeStartedEmpty()),
211 SLOT(slotStrokeStartedEmpty()));
212
213 strategy = moveStrategy;
214 isMoveSelection = true;
215 nodes = {paintLayer};
216
217 } else {
218 KisNodeSelectionRecipe nodeSelection =
219 pos ?
221 this->selectedNodes(),
223 *pos) :
225
226
227 MoveStrokeStrategy *moveStrategy =
228 new MoveStrokeStrategy(nodeSelection, image.data(), image.data());
229 connect(moveStrategy,
230 SIGNAL(sigHandlesRectCalculated(const QRect&)),
231 SLOT(slotHandlesRectCalculated(const QRect&)));
232 connect(moveStrategy,
233 SIGNAL(sigStrokeStartedEmpty()),
234 SLOT(slotStrokeStartedEmpty()));
235 connect(moveStrategy,
236 SIGNAL(sigLayersPicked(const KisNodeList&)),
237 SLOT(slotStrokePickedLayers(const KisNodeList&)));
238
239 strategy = moveStrategy;
240 nodes = nodeSelection.selectedNodes;
241 }
242
243 {
244 KConfigGroup group = KSharedConfig::openConfig()->group(toolId());
245 const bool forceLodMode = group.readEntry("forceLodMode", false);
246 strategy->setForceLodModeIfPossible(forceLodMode);
247 }
248
249 // disable outline feedback until the stroke calculates
250 // correct bounding rect
251 m_handlesRect = QRect();
252 m_strokeId = image->startStroke(strategy);
254 m_currentlyUsingSelection = isMoveSelection;
256 m_accumulatedOffset = QPoint();
257
258 if (!isMoveSelection) {
260 }
261
264 }
266
267 return true;
268}
269
274
275void KisToolMove::notifyGuiAfterMove(bool showFloatingMessage)
276{
277 if (!m_optionsWidget) return;
278 if (m_handlesRect.isEmpty()) return;
279
280 const QPoint currentTopLeft = m_handlesRect.topLeft() + currentOffset();
281
283 Q_EMIT moveInNewPosition(currentTopLeft);
284
285 // TODO: fetch this info not from options widget, but from config
286 const bool showCoordinates = m_optionsWidget->showCoordinates();
287
288 if (showCoordinates && showFloatingMessage) {
289 KisCanvas2 *kisCanvas = static_cast<KisCanvas2*>(canvas());
290 kisCanvas->viewManager()->
291 showFloatingMessage(
292 i18nc("floating message in move tool",
293 "X: %1 px, Y: %2 px",
294 QLocale().toString(currentTopLeft.x()),
295 QLocale().toString(currentTopLeft.y())),
296 QIcon(), 1000, KisFloatingMessage::High);
297 }
298}
299
301{
302 if (!m_strokeId) return false;
303
304 bool strokeEnded = false;
305
307 endStroke();
308 strokeEnded = true;
309 }
310
311 return strokeEnded;
312}
313
315{
317
319 KisToolMoveState *lastState = dynamic_cast<KisToolMoveState*>(m_changesTracker.lastState().data());
320 if (lastState && *lastState == *newState) return;
321
323}
324
325void KisToolMove::slotHandlesRectCalculated(const QRect &handlesRect)
326{
327 m_handlesRect = handlesRect;
328 notifyGuiAfterMove(false);
329}
330
332{
337 KisCanvas2 *kisCanvas = static_cast<KisCanvas2*>(canvas());
338 kisCanvas->viewManager()->
339 showFloatingMessage(
340 i18nc("floating message in move tool",
341 "Selected area has no pixels"),
342 QIcon(), 1000, KisFloatingMessage::High);
343 }
344
350 cancelStroke();
351}
352
354{
355 if (nodes.isEmpty()) {
356 useCursor(Qt::ForbiddenCursor);
357 } else {
359 }
360}
361
363{
364 if (mode() == KisTool::PAINT_MODE) return; // Don't interact with dragging
365 if (!currentNode()) return;
366 if (!image()) return;
367 if (!currentNode()->isEditable()) return; // Don't move invisible nodes
368
369 if (startStrokeImpl(MoveSelectedLayer, nullptr)) {
371 }
372
373 // Larger movement if "shift" key is pressed.
374 qreal scale = big ? m_optionsWidget->moveScale() : 1.0;
375 qreal moveStep = m_optionsWidget->moveStep() * scale;
376
377 const QPoint offset =
378 direction == Up ? QPoint( 0, -moveStep) :
379 direction == Down ? QPoint( 0, moveStep) :
380 direction == Left ? QPoint(-moveStep, 0) :
381 QPoint( moveStep, 0) ;
382
383 m_accumulatedOffset += offset;
385
389}
390
391void KisToolMove::activate(const QSet<KoShape*> &shapes)
392{
393 KisTool::activate(shapes);
394
395 m_actionConnections.addConnection(action("movetool-move-up"), SIGNAL(triggered(bool)),
396 this, SLOT(slotMoveDiscreteUp()));
397 m_actionConnections.addConnection(action("movetool-move-down"), SIGNAL(triggered(bool)),
398 this, SLOT(slotMoveDiscreteDown()));
399 m_actionConnections.addConnection(action("movetool-move-left"), SIGNAL(triggered(bool)),
400 this, SLOT(slotMoveDiscreteLeft()));
401 m_actionConnections.addConnection(action("movetool-move-right"), SIGNAL(triggered(bool)),
402 this, SLOT(slotMoveDiscreteRight()));
403
404 m_actionConnections.addConnection(action("movetool-move-up-more"), SIGNAL(triggered(bool)),
405 this, SLOT(slotMoveDiscreteUpMore()));
406 m_actionConnections.addConnection(action("movetool-move-down-more"), SIGNAL(triggered(bool)),
407 this, SLOT(slotMoveDiscreteDownMore()));
408 m_actionConnections.addConnection(action("movetool-move-left-more"), SIGNAL(triggered(bool)),
409 this, SLOT(slotMoveDiscreteLeftMore()));
410 m_actionConnections.addConnection(action("movetool-move-right-more"), SIGNAL(triggered(bool)),
411 this, SLOT(slotMoveDiscreteRightMore()));
412
413 m_canvasConnections.addUniqueConnection(qobject_cast<KisCanvas2*>(canvas())->viewManager()->nodeManager(), SIGNAL(sigUiNeedChangeSelectedNodes(KisNodeList)), this, SLOT(slotNodeChanged(KisNodeList)));
414 m_canvasConnections.addUniqueConnection(qobject_cast<KisCanvas2*>(canvas())->viewManager()->selectionManager(), SIGNAL(currentSelectionChanged()), this, SLOT(slotSelectionChanged()));
415
416 connect(m_showCoordinatesAction, SIGNAL(triggered(bool)), m_optionsWidget, SLOT(setShowCoordinates(bool)), Qt::UniqueConnection);
417 connect(m_optionsWidget, SIGNAL(showCoordinatesChanged(bool)), m_showCoordinatesAction, SLOT(setChecked(bool)), Qt::UniqueConnection);
418 connect(m_optionsWidget, SIGNAL(sigSetTranslateX(int)), SLOT(moveBySpinX(int)), Qt::UniqueConnection);
419 connect(m_optionsWidget, SIGNAL(sigSetTranslateY(int)), SLOT(moveBySpinY(int)), Qt::UniqueConnection);
420 connect(m_optionsWidget, SIGNAL(sigRequestCommitOffsetChanges()), this, SLOT(commitChanges()), Qt::UniqueConnection);
421
423 SIGNAL(sigConfigChanged(KisToolChangesTrackerDataSP)),
425
426
428}
429
430
431
432void KisToolMove::paint(QPainter& gc, const KoViewConverter &converter)
433{
434 Q_UNUSED(converter);
435
436 if (m_strokeId && !m_handlesRect.isEmpty() && !m_currentlyUsingSelection) {
437 QPainterPath handles;
438 handles.addRect(m_handlesRect.translated(currentOffset()));
439
440 QPainterPath path = pixelToView(handles);
441 paintToolOutline(&gc, path);
442 }
443}
444
446{
449
450 disconnect(m_showCoordinatesAction, 0, this, 0);
451 disconnect(m_optionsWidget, 0, this, 0);
452
453 endStroke();
455}
456
461
466
468{
469 if (!m_strokeId) return;
470
471 if (!m_changesTracker.canUndo()) {
472 cancelStroke();
473 } else {
475 }
476}
477
479{
480 if (!m_strokeId) return;
481
484 }
485}
486
491
496
498{
499 endAction(event);
500}
501
503{
504 // Ctrl+Right click toggles between moving current layer and moving layer w/ content
507
508 if (mode == MoveSelectedLayer) {
510 } else if (mode == MoveFirstLayer) {
512 }
513
514 startAction(event, mode);
515 } else {
516 startAction(event, MoveGroup);
517 }
518}
519
521{
522 Q_UNUSED(action);
523 continueAction(event);
524}
525
527{
528 Q_UNUSED(action);
529 endAction(event);
530}
531
543
545{
546 QPoint pos = convertToPixelCoordAndSnap(event).toPoint();
547 m_dragStart = pos;
548 m_dragPos = pos;
549
550 if (startStrokeImpl(mode, &pos)) {
552
557 }
558
559 } else {
560 event->ignore();
561 m_dragPos = QPoint();
562 m_dragStart = QPoint();
563 }
564 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
565}
566
568{
570
571 if (!m_strokeId) return;
572
573 QPoint pos = convertToPixelCoordAndSnap(event).toPoint();
574 pos = applyModifiers(event->modifiers(), pos);
575 m_dragPos = pos;
576
577 drag(pos);
579
580 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
581}
582
584{
587 if (!m_strokeId) return;
588
589 QPoint pos = convertToPixelCoordAndSnap(event).toPoint();
590 pos = applyModifiers(event->modifiers(), pos);
591 drag(pos);
592
594 m_dragStart = QPoint();
595 m_dragPos = QPoint();
597
602 }
603
605
606 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
607}
608
609void KisToolMove::drag(const QPoint& newPos)
610{
612
613 QPoint offset = m_accumulatedOffset + newPos - m_dragStart;
614
616 new MoveStrokeStrategy::Data(offset));
617}
618
620{
621 if (!m_strokeId) return;
622
625 }
626
629 m_strokeId.clear();
634 m_accumulatedOffset = QPoint();
635 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
636}
637
650
655
660
665
670
675
680
685
690
692{
693 if (!m_strokeId) return;
694
697 }
698
701 m_strokeId.clear();
706 m_accumulatedOffset = QPoint();
708 qobject_cast<KisCanvas2*>(canvas())->updateCanvas();
709}
710
712{
713 return m_optionsWidget;
714}
715
722
723QPoint KisToolMove::applyModifiers(Qt::KeyboardModifiers modifiers, QPoint pos)
724{
725 QPoint move = pos - m_dragStart;
726
727 // Snap to axis
728 if (modifiers & Qt::ShiftModifier) {
729 move = snapToClosestAxis(move);
730 }
731
732 // "Precision mode" - scale down movement by 1/5
733 if (modifiers & Qt::AltModifier) {
734 const qreal SCALE_FACTOR = .2;
735 move = SCALE_FACTOR * move;
736 }
737
738 return m_dragStart + move;
739}
740
742{
743 if (mode() == KisTool::PAINT_MODE || // Don't interact with dragging
744 !currentNode()->isEditable() || // Don't move invisible nodes
745 m_handlesRect.isEmpty()) {
746 return;
747 }
748
749 // starting a new stroke resets m_handlesRect and it gets updated asynchronously,
750 // but in this case no change is expected
751 int handlesRectX = m_handlesRect.x();
752
753 if (startStrokeImpl(MoveSelectedLayer, nullptr)) {
755 }
756
757 m_accumulatedOffset.rx() = newX - handlesRectX;
758
760
761 notifyGuiAfterMove(false);
763}
764
766{
767 if (mode() == KisTool::PAINT_MODE || // Don't interact with dragging
768 !currentNode()->isEditable() || // Don't move invisible nodes
769 m_handlesRect.isEmpty()) {
770 return;
771 }
772
773 // starting a new stroke resets m_handlesRect and it gets updated asynchronously,
774 // but in this case no change is expected
775 int handlesRectY = m_handlesRect.y();
776
777 if (startStrokeImpl(MoveSelectedLayer, nullptr)) {
779 }
780
781 m_accumulatedOffset.ry() = newY - handlesRectY;
782
784
785 notifyGuiAfterMove(false);
787}
788
790{
791 KisResourcesSnapshotSP resources =
792 new KisResourcesSnapshot(image(), currentNode(), canvas()->resourceManager());
794
796 selection, this);
797 connect(job,
798 SIGNAL(sigCalculationFinished(const QRect&)),
799 SLOT(slotHandlesRectCalculated(const QRect &)));
800
801 KisImageSP image = this->image();
802 image->addSpontaneousJob(job);
803
804 notifyGuiAfterMove(false);
805}
806
808{
809 if (m_strokeId && !tryEndPreviousStroke(nodes)) {
810 return;
811 }
813}
814
820
822{
825
826 actions << actionRegistry->makeQAction("movetool-move-up", this);
827 actions << actionRegistry->makeQAction("movetool-move-down", this);
828 actions << actionRegistry->makeQAction("movetool-move-left", this);
829 actions << actionRegistry->makeQAction("movetool-move-right", this);
830 actions << actionRegistry->makeQAction("movetool-move-up-more", this);
831 actions << actionRegistry->makeQAction("movetool-move-down-more", this);
832 actions << actionRegistry->makeQAction("movetool-move-left-more", this);
833 actions << actionRegistry->makeQAction("movetool-move-right-more", this);
834 actions << actionRegistry->makeQAction("movetool-show-coordinates", this);
835
836 return actions;
837
838}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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
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...
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