[krita] /: FEATURE: actions for rotate/scale/mirror/shear selection
Dmitry Kazakov
null at kde.org
Sun Sep 9 14:52:43 BST 2018
Git commit 3014d62c9817690ed21384450cb771c75bf60ce4 by Dmitry Kazakov.
Committed on 09/09/2018 at 13:52.
Pushed by dkazakov into branch 'master'.
FEATURE: actions for rotate/scale/mirror/shear selection
Now Rotate/Scale/Mirror/Shear Layer actions also support
handling a selection. If there is a selection active, then
the action will transform selected content only.
Now there are also 8 new actions, that will rotate/scale/
mirror/shear *all* layers without resizing the image. These
actions can also handle selections.
Animation Note:
* when no selection present, the actions transform *all*
the frames of the layers in question
* when there is a selection active, only current frame
is transformed
BUG:365595
Ref T3920
CC:kimageshop at kde.org
M +96 -0 krita/krita.action
M +15 -0 krita/krita4.xmlgui
M +2 -0 libs/image/CMakeLists.txt
R +0 -0 libs/image/commands_new/kis_transaction_based_command.cpp [from: libs/ui/kis_transaction_based_command.cpp - 100% similarity]
R +2 -2 libs/image/commands_new/kis_transaction_based_command.h [from: libs/ui/kis_transaction_based_command.h - 092% similarity]
M +79 -27 libs/image/kis_image.cc
M +6 -7 libs/image/kis_image.h
M +12 -0 libs/image/kis_processing_applicator.cpp
M +5 -0 libs/image/kis_processing_visitor.cpp
M +8 -0 libs/image/kis_processing_visitor.h
A +91 -0 libs/image/processing/KisSelectionBasedProcessingHelper.cpp [License: UNKNOWN] *
A +37 -0 libs/image/processing/KisSelectionBasedProcessingHelper.h [License: UNKNOWN] *
M +26 -9 libs/image/processing/kis_mirror_processing_visitor.cpp
M +10 -0 libs/image/processing/kis_mirror_processing_visitor.h
M +37 -5 libs/image/processing/kis_transform_processing_visitor.cpp
M +8 -1 libs/image/processing/kis_transform_processing_visitor.h
M +11 -4 libs/libkis/Node.cpp
M +1 -1 libs/libkis/Node.h
M +0 -1 libs/ui/CMakeLists.txt
M +1 -1 libs/ui/actions/kis_selection_action_factories.cpp
M +42 -56 libs/ui/kis_node_manager.cpp
M +7 -12 libs/ui/kis_node_manager.h
M +1 -1 libs/ui/operations/kis_filter_selection_operation.cpp
M +0 -104 libs/ui/tests/kis_node_manager_test.cpp
M +0 -6 libs/ui/tests/kis_node_manager_test.h
M +1 -1 libs/ui/tool/kis_selection_tool_helper.cpp
M +1 -1 plugins/dockers/gamutmask/gamutmask_dock.cpp
M +46 -14 plugins/extensions/imagesize/imagesize.cc
M +6 -0 plugins/extensions/imagesize/imagesize.h
M +1 -1 plugins/extensions/pykrita/sip/krita/Node.sip
M +91 -10 plugins/extensions/rotateimage/rotateimage.cc
M +12 -0 plugins/extensions/rotateimage/rotateimage.h
M +25 -4 plugins/extensions/shearimage/shearimage.cc
M +6 -0 plugins/extensions/shearimage/shearimage.h
M +1 -1 plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp
The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.
https://commits.kde.org/krita/3014d62c9817690ed21384450cb771c75bf60ce4
diff --git a/krita/krita.action b/krita/krita.action
index 2a524c374f3..d247f8d0891 100644
--- a/krita/krita.action
+++ b/krita/krita.action
@@ -3303,6 +3303,102 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
+ <Action name="mirrorAllNodesX">
+ <icon>symmetry-horizontal</icon>
+ <text>Mirror All Layers Hori&zontally</text>
+ <whatsThis></whatsThis>
+ <toolTip>Mirror All Layers Horizontally</toolTip>
+ <iconText>Mirror All Layers Horizontally</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="mirrorAllNodesY">
+ <icon>symmetry-vertical</icon>
+ <text>Mirror All Layers &Vertically</text>
+ <whatsThis></whatsThis>
+ <toolTip>Mirror All Layers Vertically</toolTip>
+ <iconText>Mirror All Layers Vertically</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="rotateAllLayers">
+ <icon></icon>
+ <text>&Rotate All Layers...</text>
+ <whatsThis></whatsThis>
+ <toolTip>Rotate All Layers</toolTip>
+ <iconText>Rotate All Layers</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="rotateAllLayersCW90">
+ <icon>object-rotate-right</icon>
+ <text>Rotate All &Layers 90° to the Right</text>
+ <whatsThis></whatsThis>
+ <toolTip>Rotate All Layers 90° to the Right</toolTip>
+ <iconText>Rotate All Layers 90° to the Right</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="rotateAllLayersCCW90">
+ <icon>object-rotate-left</icon>
+ <text>Rotate All Layers &90° to the Left</text>
+ <whatsThis></whatsThis>
+ <toolTip>Rotate All Layers 90° to the Left</toolTip>
+ <iconText>Rotate All Layers 90° to the Left</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="rotateAllLayers180">
+ <icon></icon>
+ <text>Rotate All Layers &180°</text>
+ <whatsThis></whatsThis>
+ <toolTip>Rotate All Layers 180°</toolTip>
+ <iconText>Rotate All Layers 180°</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="scaleAllLayers">
+ <icon></icon>
+ <text>Scale All &Layers to new Size...</text>
+ <whatsThis></whatsThis>
+ <toolTip>Scale All Layers to new Size</toolTip>
+ <iconText>Scale All Layers to new Size</iconText>
+ <activationFlags>100000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
+ <Action name="shearAllLayers">
+ <icon></icon>
+ <text>&Shear All Layers...</text>
+ <whatsThis></whatsThis>
+ <toolTip>Shear All Layers</toolTip>
+ <iconText>Shear All Layers</iconText>
+ <activationFlags>1000</activationFlags>
+ <activationConditions>1</activationConditions>
+ <shortcut></shortcut>
+ <isCheckable>false</isCheckable>
+ <statusTip></statusTip>
+ </Action>
<Action name="offsetlayer">
<icon></icon>
<text>&Offset Layer...</text>
diff --git a/krita/krita4.xmlgui b/krita/krita4.xmlgui
index d050f120370..5e6da25a83f 100644
--- a/krita/krita4.xmlgui
+++ b/krita/krita4.xmlgui
@@ -236,6 +236,21 @@ xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 http://www.kde.org
<Action name="shearlayer"/>
<Action name="offsetlayer"/>
</Menu>
+ <Menu name="LayerTransformAll">
+ <text>Transform &All Layers</text>
+ <Action name="mirrorAllNodesX"/>
+ <Action name="mirrorAllNodesY"/>
+ <Action name="scaleAllLayers"/>
+ <Menu name="Rotate">
+ <text>&Rotate</text>
+ <Action name="rotateAllLayers"/>
+ <Separator/>
+ <Action name="rotateAllLayersCW90"/>
+ <Action name="rotateAllLayersCCW90"/>
+ <Action name="rotateAllLayers180"/>
+ </Menu>
+ <Action name="shearAllLayers"/>
+ </Menu>
<Menu name="LayerSplitAlpha">
<text>S&plit</text>
<Menu name="LayerSplitAlpha">
diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt
index 06d757f161a..9696acc0ce7 100644
--- a/libs/image/CMakeLists.txt
+++ b/libs/image/CMakeLists.txt
@@ -110,12 +110,14 @@ set(kritaimage_LIB_SRCS
commands_new/kis_switch_current_time_command.cpp
commands_new/kis_change_projection_color_command.cpp
commands_new/kis_activate_selection_mask_command.cpp
+ commands_new/kis_transaction_based_command.cpp
processing/kis_do_nothing_processing_visitor.cpp
processing/kis_simple_processing_visitor.cpp
processing/kis_crop_processing_visitor.cpp
processing/kis_crop_selections_processing_visitor.cpp
processing/kis_transform_processing_visitor.cpp
processing/kis_mirror_processing_visitor.cpp
+ processing/KisSelectionBasedProcessingHelper.cpp
filter/kis_filter.cc
filter/kis_filter_category_ids.cpp
filter/kis_filter_configuration.cc
diff --git a/libs/ui/kis_transaction_based_command.cpp b/libs/image/commands_new/kis_transaction_based_command.cpp
similarity index 100%
rename from libs/ui/kis_transaction_based_command.cpp
rename to libs/image/commands_new/kis_transaction_based_command.cpp
diff --git a/libs/ui/kis_transaction_based_command.h b/libs/image/commands_new/kis_transaction_based_command.h
similarity index 92%
rename from libs/ui/kis_transaction_based_command.h
rename to libs/image/commands_new/kis_transaction_based_command.h
index a47b1d40e0a..8c381bb4763 100644
--- a/libs/ui/kis_transaction_based_command.h
+++ b/libs/image/commands_new/kis_transaction_based_command.h
@@ -19,10 +19,10 @@
#ifndef KIS_TRANSACTION_BASED_COMMAND_H
#define KIS_TRANSACTION_BASED_COMMAND_H
-#include <kritaui_export.h>
+#include <kritaimage_export.h>
#include <kundo2command.h>
-class KRITAUI_EXPORT KisTransactionBasedCommand : public KUndo2Command
+class KRITAIMAGE_EXPORT KisTransactionBasedCommand : public KUndo2Command
{
public:
KisTransactionBasedCommand(const KUndo2MagicString &text = KUndo2MagicString(), KUndo2Command *parent = 0);
diff --git a/libs/image/kis_image.cc b/libs/image/kis_image.cc
index fbea2059cde..37b47fc1a4b 100644
--- a/libs/image/kis_image.cc
+++ b/libs/image/kis_image.cc
@@ -741,33 +741,64 @@ void KisImage::scaleImage(const QSize &size, qreal xres, qreal yres, KisFilterSt
applicator.end();
}
-void KisImage::scaleNode(KisNodeSP node, qreal scaleX, qreal scaleY, KisFilterStrategy *filterStrategy)
+void KisImage::scaleNode(KisNodeSP node, const QPointF ¢er, qreal scaleX, qreal scaleY, KisFilterStrategy *filterStrategy, KisSelectionSP selection)
{
KUndo2MagicString actionName(kundo2_i18n("Scale Layer"));
KisImageSignalVector emitSignals;
emitSignals << ModifiedSignal;
+ QPointF offset;
+ {
+ KisTransformWorker worker(0,
+ scaleX, scaleY,
+ 0, 0, 0, 0,
+ 0.0,
+ 0, 0, 0, 0);
+ QTransform transform = worker.transform();
+
+ offset = center - transform.map(center);
+ }
+
KisProcessingApplicator applicator(this, node,
KisProcessingApplicator::RECURSIVE,
emitSignals, actionName);
- KisProcessingVisitorSP visitor =
+ KisTransformProcessingVisitor *visitor =
new KisTransformProcessingVisitor(scaleX, scaleY,
0, 0,
QPointF(),
0,
- 0, 0,
+ offset.x(), offset.y(),
filterStrategy);
- applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ visitor->setSelection(selection);
+
+ if (selection) {
+ applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+ } else {
+ applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ }
+
applicator.end();
}
void KisImage::rotateImpl(const KUndo2MagicString &actionName,
KisNodeSP rootNode,
+ double radians,
bool resizeImage,
- double radians)
+ KisSelectionSP selection)
{
+ // we can either transform (and resize) the whole image or
+ // transform a selection, we cannot do both at the same time
+ KIS_SAFE_ASSERT_RECOVER(!(bool(selection) && resizeImage)) {
+ selection = 0;
+ }
+
+ const QRect baseBounds =
+ resizeImage ? bounds() :
+ selection ? selection->selectedExactRect() :
+ rootNode->exactBounds();
+
QPointF offset;
QSize newSize;
@@ -780,12 +811,12 @@ void KisImage::rotateImpl(const KUndo2MagicString &actionName,
QTransform transform = worker.transform();
if (resizeImage) {
- QRect newRect = transform.mapRect(bounds());
+ QRect newRect = transform.mapRect(baseBounds);
newSize = newRect.size();
offset = -newRect.topLeft();
}
else {
- QPointF origin = QRectF(rootNode->exactBounds()).center();
+ QPointF origin = QRectF(baseBounds).center();
newSize = size();
offset = -(transform.map(origin) - origin);
@@ -793,11 +824,12 @@ void KisImage::rotateImpl(const KUndo2MagicString &actionName,
}
bool sizeChanged = resizeImage &&
- (newSize.width() != width() || newSize.height() != height());
+ (newSize.width() != baseBounds.width() ||
+ newSize.height() != baseBounds.height());
// These signals will be emitted after processing is done
KisImageSignalVector emitSignals;
- if (sizeChanged) emitSignals << ComplexSizeChangedSignal(bounds(), newSize);
+ if (sizeChanged) emitSignals << ComplexSizeChangedSignal(baseBounds, newSize);
emitSignals << ModifiedSignal;
// These flags determine whether updates are transferred to the UI during processing
@@ -813,14 +845,21 @@ void KisImage::rotateImpl(const KUndo2MagicString &actionName,
KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->value("Bicubic");
- KisProcessingVisitorSP visitor =
+ KisTransformProcessingVisitor *visitor =
new KisTransformProcessingVisitor(1.0, 1.0, 0.0, 0.0,
QPointF(),
radians,
offset.x(), offset.y(),
filter);
+ if (selection) {
+ visitor->setSelection(selection);
+ }
- applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ if (selection) {
+ applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+ } else {
+ applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ }
if (sizeChanged) {
applicator.applyCommand(new KisImageResizeCommand(this, newSize));
@@ -831,15 +870,15 @@ void KisImage::rotateImpl(const KUndo2MagicString &actionName,
void KisImage::rotateImage(double radians)
{
- rotateImpl(kundo2_i18n("Rotate Image"), root(), true, radians);
+ rotateImpl(kundo2_i18n("Rotate Image"), root(), radians, true, 0);
}
-void KisImage::rotateNode(KisNodeSP node, double radians)
+void KisImage::rotateNode(KisNodeSP node, double radians, KisSelectionSP selection)
{
if (node->inherits("KisMask")) {
- rotateImpl(kundo2_i18n("Rotate Mask"), node, false, radians);
+ rotateImpl(kundo2_i18n("Rotate Mask"), node, radians, false, selection);
} else {
- rotateImpl(kundo2_i18n("Rotate Layer"), node, false, radians);
+ rotateImpl(kundo2_i18n("Rotate Layer"), node, radians, false, selection);
}
}
@@ -847,8 +886,15 @@ void KisImage::shearImpl(const KUndo2MagicString &actionName,
KisNodeSP rootNode,
bool resizeImage,
double angleX, double angleY,
- const QPointF &origin)
+ KisSelectionSP selection)
{
+ const QRect baseBounds =
+ resizeImage ? bounds() :
+ selection ? selection->selectedExactRect() :
+ rootNode->exactBounds();
+
+ const QPointF origin = QRectF(baseBounds).center();
+
//angleX, angleY are in degrees
const qreal pi = 3.1415926535897932385;
const qreal deg2rad = pi / 180.0;
@@ -866,15 +912,15 @@ void KisImage::shearImpl(const KUndo2MagicString &actionName,
0,
0, 0, 0, 0);
- QRect newRect = worker.transform().mapRect(bounds());
+ QRect newRect = worker.transform().mapRect(baseBounds);
newSize = newRect.size();
if (resizeImage) offset = -newRect.topLeft();
}
- if (newSize == size()) return;
+ if (newSize == baseBounds.size()) return;
KisImageSignalVector emitSignals;
- if (resizeImage) emitSignals << ComplexSizeChangedSignal(bounds(), newSize);
+ if (resizeImage) emitSignals << ComplexSizeChangedSignal(baseBounds, newSize);
emitSignals << ModifiedSignal;
KisProcessingApplicator::ProcessingFlags signalFlags =
@@ -887,14 +933,22 @@ void KisImage::shearImpl(const KUndo2MagicString &actionName,
KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->value("Bilinear");
- KisProcessingVisitorSP visitor =
+ KisTransformProcessingVisitor *visitor =
new KisTransformProcessingVisitor(1.0, 1.0,
tanX, tanY, origin,
0,
offset.x(), offset.y(),
filter);
- applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ if (selection) {
+ visitor->setSelection(selection);
+ }
+
+ if (selection) {
+ applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+ } else {
+ applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ }
if (resizeImage) {
applicator.applyCommand(new KisImageResizeCommand(this, newSize));
@@ -903,23 +957,21 @@ void KisImage::shearImpl(const KUndo2MagicString &actionName,
applicator.end();
}
-void KisImage::shearNode(KisNodeSP node, double angleX, double angleY)
+void KisImage::shearNode(KisNodeSP node, double angleX, double angleY, KisSelectionSP selection)
{
- QPointF shearOrigin = QRectF(bounds()).center();
-
if (node->inherits("KisMask")) {
shearImpl(kundo2_i18n("Shear Mask"), node, false,
- angleX, angleY, shearOrigin);
+ angleX, angleY, selection);
} else {
shearImpl(kundo2_i18n("Shear Layer"), node, false,
- angleX, angleY, shearOrigin);
+ angleX, angleY, selection);
}
}
void KisImage::shear(double angleX, double angleY)
{
shearImpl(kundo2_i18n("Shear Image"), m_d->rootLayer, true,
- angleX, angleY, QPointF());
+ angleX, angleY, 0);
}
void KisImage::convertImageColorSpace(const KoColorSpace *dstColorSpace,
diff --git a/libs/image/kis_image.h b/libs/image/kis_image.h
index ba687623131..148ebd2da89 100644
--- a/libs/image/kis_image.h
+++ b/libs/image/kis_image.h
@@ -285,7 +285,7 @@ public:
* a background, so you cannot expect the image having new size
* right after ths call.
*/
- void scaleNode(KisNodeSP node, qreal scaleX, qreal scaleY, KisFilterStrategy *filterStrategy);
+ void scaleNode(KisNodeSP node, const QPointF ¢er, qreal scaleX, qreal scaleY, KisFilterStrategy *filterStrategy, KisSelectionSP selection);
/**
* @brief start asynchronous operation on rotating the image
@@ -312,7 +312,7 @@ public:
* a background, so you cannot expect the operation being completed
* right after the call
*/
- void rotateNode(KisNodeSP node, double radians);
+ void rotateNode(KisNodeSP node, double radians, KisSelectionSP selection);
/**
* @brief start asynchronous operation on shearing the image
@@ -339,7 +339,7 @@ public:
* a background, so you cannot expect the operation being completed
* right after the call
*/
- void shearNode(KisNodeSP node, double angleX, double angleY);
+ void shearNode(KisNodeSP node, double angleX, double angleY, KisSelectionSP selection);
/**
* Convert the image and all its layers to the dstColorSpace
@@ -1066,11 +1066,10 @@ private:
void emitSizeChanged();
void resizeImageImpl(const QRect& newRect, bool cropLayers);
- void rotateImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode,
- bool resizeImage, double radians);
+ void rotateImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, double radians,
+ bool resizeImage, KisSelectionSP selection);
void shearImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode,
- bool resizeImage, double angleX, double angleY,
- const QPointF &origin);
+ bool resizeImage, double angleX, double angleY, KisSelectionSP selection);
void safeRemoveTwoNodes(KisNodeSP node1, KisNodeSP node2);
diff --git a/libs/image/kis_processing_applicator.cpp b/libs/image/kis_processing_applicator.cpp
index f8d101b1980..08f493c3ed8 100644
--- a/libs/image/kis_processing_applicator.cpp
+++ b/libs/image/kis_processing_applicator.cpp
@@ -207,6 +207,12 @@ void KisProcessingApplicator::applyVisitor(KisProcessingVisitorSP visitor,
KisStrokeJobData::Sequentiality sequentiality,
KisStrokeJobData::Exclusivity exclusivity)
{
+ KUndo2Command *initCommand = visitor->createInitCommand();
+ if (initCommand) {
+ applyCommand(initCommand,
+ KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL);
+ }
+
if(!m_flags.testFlag(RECURSIVE)) {
applyCommand(new KisProcessingCommand(visitor, m_node),
sequentiality, exclusivity);
@@ -220,6 +226,12 @@ void KisProcessingApplicator::applyVisitorAllFrames(KisProcessingVisitorSP visit
KisStrokeJobData::Sequentiality sequentiality,
KisStrokeJobData::Exclusivity exclusivity)
{
+ KUndo2Command *initCommand = visitor->createInitCommand();
+ if (initCommand) {
+ applyCommand(initCommand,
+ KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL);
+ }
+
KisLayerUtils::FrameJobs jobs;
// TODO: implement a nonrecursive case when !m_flags.testFlag(RECURSIVE)
diff --git a/libs/image/kis_processing_visitor.cpp b/libs/image/kis_processing_visitor.cpp
index accd4ae9932..7aa9938ab86 100644
--- a/libs/image/kis_processing_visitor.cpp
+++ b/libs/image/kis_processing_visitor.cpp
@@ -56,3 +56,8 @@ KoUpdater* KisProcessingVisitor::ProgressHelper::updater() const
KisProcessingVisitor::~KisProcessingVisitor()
{
}
+
+KUndo2Command *KisProcessingVisitor::createInitCommand()
+{
+ return 0;
+}
diff --git a/libs/image/kis_processing_visitor.h b/libs/image/kis_processing_visitor.h
index 6d3fe843698..4c5114897b5 100644
--- a/libs/image/kis_processing_visitor.h
+++ b/libs/image/kis_processing_visitor.h
@@ -39,6 +39,7 @@ class KisTransparencyMask;
class KisSelectionMask;
class KisGeneratorLayer;
class KisColorizeMask;
+class KUndo2Command;
/**
* A visitor that processes a single layer; it does not recurse into the
@@ -63,6 +64,13 @@ public:
virtual void visit(KisColorizeMask *mask, KisUndoAdapter *undoAdapter) = 0;
virtual void visit(KisSelectionMask *mask, KisUndoAdapter *undoAdapter) = 0;
+ /**
+ * Create a command that initializes the processing visitor before running
+ * on all the layers. The command is executed sequentially, non-exclusively
+ * on the image by applicator.
+ */
+ virtual KUndo2Command* createInitCommand();
+
public:
class KRITAIMAGE_EXPORT ProgressHelper {
public:
diff --git a/libs/image/processing/KisSelectionBasedProcessingHelper.cpp b/libs/image/processing/KisSelectionBasedProcessingHelper.cpp
new file mode 100644
index 00000000000..17fcb77bab7
--- /dev/null
+++ b/libs/image/processing/KisSelectionBasedProcessingHelper.cpp
@@ -0,0 +1,91 @@
+#include "KisSelectionBasedProcessingHelper.h"
+
+#include "kis_paint_device.h"
+#include "kis_painter.h"
+#include "kis_selection.h"
+#include "kis_transaction_based_command.h"
+#include "kis_transaction.h"
+#include "kis_undo_adapter.h"
+
+KisSelectionBasedProcessingHelper::KisSelectionBasedProcessingHelper(KisSelectionSP selection, Functor func)
+ : m_selection(selection),
+ m_func(func)
+{
+}
+
+void KisSelectionBasedProcessingHelper::setSelection(KisSelectionSP selection)
+{
+ m_selection = selection;
+}
+
+KUndo2Command *KisSelectionBasedProcessingHelper::createInitCommand(Functor func)
+{
+ if (!m_selection) return 0;
+
+ struct ProcessSelectionCommand : KisTransactionBasedCommand {
+ ProcessSelectionCommand(KisSelectionSP selection,
+ KisSelectionSP cutSelection,
+ std::function<void(KisPaintDeviceSP)> func)
+ : m_selection(selection),
+ m_cutSelection(cutSelection),
+ m_func(func)
+ {
+ }
+
+ KUndo2Command* paint() {
+ m_cutSelection->pixelSelection()->makeCloneFromRough(m_selection->pixelSelection(), m_selection->selectedRect());
+
+ KisTransaction t(m_selection->pixelSelection());
+ m_func(m_selection->pixelSelection());
+
+ return t.endAndTake();
+ }
+
+ KisSelectionSP m_selection;
+ KisSelectionSP m_cutSelection;
+ Functor m_func;
+ };
+
+ m_cutSelection = new KisSelection();
+ return new ProcessSelectionCommand(m_selection, m_cutSelection, func);
+}
+
+KUndo2Command *KisSelectionBasedProcessingHelper::createInitCommand()
+{
+ return createInitCommand(m_func);
+}
+
+void KisSelectionBasedProcessingHelper::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter)
+{
+ transformPaintDevice(device, undoAdapter, m_func);
+}
+
+void KisSelectionBasedProcessingHelper::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter, Functor func)
+{
+ KIS_SAFE_ASSERT_RECOVER_RETURN(!!m_selection == !!m_cutSelection);
+
+ if (m_selection && m_cutSelection) {
+ // we have already processed the selection in the init command so try to skip it
+ if (device != static_cast<KisPaintDevice*>(m_selection->pixelSelection().data())) {
+ KisTransaction transaction(device);
+
+ const QRect cutBounds = m_cutSelection->selectedExactRect();
+ const QRect pasteBounds = m_selection->selectedExactRect();
+
+
+ KisPaintDeviceSP tempDev = new KisPaintDevice(device->colorSpace());
+ tempDev->makeCloneFromRough(device, cutBounds);
+
+ func(tempDev);
+
+ device->clearSelection(m_cutSelection);
+ KisPainter::copyAreaOptimized(pasteBounds.topLeft(), tempDev, device, pasteBounds, m_selection);
+ transaction.commit(undoAdapter);
+
+ }
+ } else {
+ KisTransaction transaction(device);
+ func(device);
+ transaction.commit(undoAdapter);
+ }
+}
diff --git a/libs/image/processing/KisSelectionBasedProcessingHelper.h b/libs/image/processing/KisSelectionBasedProcessingHelper.h
new file mode 100644
index 00000000000..20bfa0b8455
--- /dev/null
+++ b/libs/image/processing/KisSelectionBasedProcessingHelper.h
@@ -0,0 +1,37 @@
+#ifndef KISSELECTIONBASEDPROCESSINGHELPER_H
+#define KISSELECTIONBASEDPROCESSINGHELPER_H
+
+#include "kritaimage_export.h"
+#include "kis_types.h"
+
+#include <functional>
+#include <QRect>
+
+class KisUndoAdapter;
+
+
+class KisSelectionBasedProcessingHelper
+{
+public:
+ using Functor = std::function<void(KisPaintDeviceSP)>;
+public:
+ KisSelectionBasedProcessingHelper(KisSelectionSP selection, Functor func);
+
+ void setSelection(KisSelectionSP selection);
+
+ KUndo2Command *createInitCommand();
+ KUndo2Command *createInitCommand(Functor func);
+
+
+ void transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter);
+
+ void transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter, Functor func);
+
+
+private:
+ KisSelectionSP m_selection;
+ KisSelectionSP m_cutSelection;
+ Functor m_func;
+};
+
+#endif // KISSELECTIONBASEDPROCESSINGHELPER_H
diff --git a/libs/image/processing/kis_mirror_processing_visitor.cpp b/libs/image/processing/kis_mirror_processing_visitor.cpp
index 2dc840fba80..814cc2fe240 100644
--- a/libs/image/processing/kis_mirror_processing_visitor.cpp
+++ b/libs/image/processing/kis_mirror_processing_visitor.cpp
@@ -22,33 +22,50 @@
#include "kis_transaction.h"
#include "kis_node.h"
#include "kis_image.h"
+#include "kis_painter.h"
#include "kis_transform_worker.h"
#include "lazybrush/kis_colorize_mask.h"
#include "processing/kis_transform_processing_visitor.h"
+#include "commands_new/kis_transaction_based_command.h"
+#include <functional>
+
KisMirrorProcessingVisitor::KisMirrorProcessingVisitor(const QRect &bounds, Qt::Orientation orientation)
- : m_bounds(bounds), m_orientation(orientation)
+ : m_bounds(bounds),
+ m_orientation(orientation),
+ m_selectionHelper(0, std::bind(&KisMirrorProcessingVisitor::mirrorDevice, this, std::placeholders::_1))
{
+ m_axis = m_orientation == Qt::Horizontal ?
+ m_bounds.x() + 0.5 * m_bounds.width() :
+ m_bounds.y() + 0.5 * m_bounds.height();
}
-void KisMirrorProcessingVisitor::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter)
+KisMirrorProcessingVisitor::KisMirrorProcessingVisitor(KisSelectionSP selection, Qt::Orientation orientation)
+ : KisMirrorProcessingVisitor(selection->selectedExactRect(), orientation)
{
- KisTransaction transaction(device);
+ m_selectionHelper.setSelection(selection);
+}
- qreal axis = m_orientation == Qt::Horizontal ?
- m_bounds.x() + 0.5 * m_bounds.width() :
- m_bounds.y() + 0.5 * m_bounds.height();
+KUndo2Command *KisMirrorProcessingVisitor::createInitCommand()
+{
+ return m_selectionHelper.createInitCommand();
+}
- KisTransformWorker::mirror(device, axis, m_orientation);
- transaction.commit(undoAdapter);
+void KisMirrorProcessingVisitor::mirrorDevice(KisPaintDeviceSP device)
+{
+ KisTransformWorker::mirror(device, m_axis, m_orientation);
+}
+
+void KisMirrorProcessingVisitor::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter)
+{
+ m_selectionHelper.transformPaintDevice(device, undoAdapter);
}
void KisMirrorProcessingVisitor::visitNodeWithPaintDevice(KisNode *node, KisUndoAdapter *undoAdapter)
{
transformPaintDevice(node->paintDevice(), undoAdapter);
-
}
void KisMirrorProcessingVisitor::visitExternalLayer(KisExternalLayer *layer, KisUndoAdapter *undoAdapter)
diff --git a/libs/image/processing/kis_mirror_processing_visitor.h b/libs/image/processing/kis_mirror_processing_visitor.h
index e8f294070c0..e09f64c10e2 100644
--- a/libs/image/processing/kis_mirror_processing_visitor.h
+++ b/libs/image/processing/kis_mirror_processing_visitor.h
@@ -23,11 +23,14 @@
#include <QRect>
#include "kis_types.h"
+#include "KisSelectionBasedProcessingHelper.h"
+
class KRITAIMAGE_EXPORT KisMirrorProcessingVisitor : public KisSimpleProcessingVisitor
{
public:
KisMirrorProcessingVisitor(const QRect &bounds, Qt::Orientation orientation);
+ KisMirrorProcessingVisitor(KisSelectionSP selection, Qt::Orientation orientation);
private:
void visitNodeWithPaintDevice(KisNode *node, KisUndoAdapter *undoAdapter) override;
@@ -35,11 +38,18 @@ private:
void visitColorizeMask(KisColorizeMask *node, KisUndoAdapter *undoAdapter) override;
+ KUndo2Command* createInitCommand() override;
+
+ void mirrorDevice(KisPaintDeviceSP device);
+
private:
void transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter);
QRect m_bounds;
Qt::Orientation m_orientation;
+ qreal m_axis = 0.0;
+
+ KisSelectionBasedProcessingHelper m_selectionHelper;
};
#endif /* __KIS_MIRROR_PROCESSING_VISITOR_H */
diff --git a/libs/image/processing/kis_transform_processing_visitor.cpp b/libs/image/processing/kis_transform_processing_visitor.cpp
index d62099c536f..0e6f61a9cdb 100644
--- a/libs/image/processing/kis_transform_processing_visitor.cpp
+++ b/libs/image/processing/kis_transform_processing_visitor.cpp
@@ -62,9 +62,24 @@ KisTransformProcessingVisitor(qreal xscale, qreal yscale,
, m_filter(filter)
, m_angle(angle)
, m_shapesCorrection(shapesCorrection)
+ , m_selectionHelper(0, KisSelectionBasedProcessingHelper::Functor())
{
}
+void KisTransformProcessingVisitor::setSelection(KisSelectionSP selection)
+{
+ m_selectionHelper.setSelection(selection);
+}
+
+KUndo2Command *KisTransformProcessingVisitor::createInitCommand()
+{
+ return m_selectionHelper.createInitCommand(
+ std::bind(&KisTransformProcessingVisitor::transformOneDevice,
+ this,
+ std::placeholders::_1,
+ (KoUpdater*)0));
+}
+
void KisTransformProcessingVisitor::visit(KisNode *node, KisUndoAdapter *undoAdapter)
{
Q_UNUSED(node);
@@ -186,6 +201,16 @@ void KisTransformProcessingVisitor::transformClones(KisLayer *layer, KisUndoAdap
void KisTransformProcessingVisitor::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *adapter, const ProgressHelper &helper)
{
+ m_selectionHelper.transformPaintDevice(device,
+ adapter,
+ std::bind(&KisTransformProcessingVisitor::transformOneDevice,
+ this,
+ std::placeholders::_1,
+ helper.updater()));
+
+
+ return;
+
KisTransaction transaction(kundo2_i18n("Transform Layer"), device);
KisTransformWorker tw(device, m_sx, m_sy, m_shearx, m_sheary,
@@ -196,12 +221,18 @@ void KisTransformProcessingVisitor::transformPaintDevice(KisPaintDeviceSP device
transaction.commit(adapter);
}
-void KisTransformProcessingVisitor::transformSelection(KisSelectionSP selection, KisUndoAdapter *adapter, const ProgressHelper &helper)
+void KisTransformProcessingVisitor::transformOneDevice(KisPaintDeviceSP device,
+ KoUpdater *updater)
{
- if(selection->hasPixelSelection()) {
- transformPaintDevice(selection->pixelSelection(), adapter, helper);
- }
+ KisTransformWorker tw(device, m_sx, m_sy, m_shearx, m_sheary,
+ m_shearOrigin.x(), m_shearOrigin.y(),
+ m_angle, m_tx, m_ty, updater,
+ m_filter);
+ tw.run();
+}
+void KisTransformProcessingVisitor::transformSelection(KisSelectionSP selection, KisUndoAdapter *adapter, const ProgressHelper &helper)
+{
if (selection->hasShapeSelection()) {
KisTransformWorker tw(selection->projection(), m_sx, m_sy, m_shearx, m_sheary,
m_shearOrigin.x(), m_shearOrigin.y(),
@@ -213,8 +244,9 @@ void KisTransformProcessingVisitor::transformSelection(KisSelectionSP selection,
if (command) {
adapter->addCommand(command);
}
+ } else {
+ transformPaintDevice(selection->pixelSelection(), adapter, helper);
}
selection->updateProjection();
}
-
diff --git a/libs/image/processing/kis_transform_processing_visitor.h b/libs/image/processing/kis_transform_processing_visitor.h
index e72fa64bbdc..d8b8a66e6a3 100644
--- a/libs/image/processing/kis_transform_processing_visitor.h
+++ b/libs/image/processing/kis_transform_processing_visitor.h
@@ -20,7 +20,7 @@
#define __KIS_TRANSFORM_PROCESSING_VISITOR_H
#include "kis_processing_visitor.h"
-
+#include "KisSelectionBasedProcessingHelper.h"
#include <kis_types.h>
@@ -39,6 +39,10 @@ public:
KisFilterStrategy *filter,
const QTransform &shapesCorrection = QTransform());
+ void setSelection(KisSelectionSP selection);
+ KUndo2Command *createInitCommand();
+
+
void visit(KisNode *node, KisUndoAdapter *undoAdapter) override;
void visit(KisPaintLayer *layer, KisUndoAdapter *undoAdapter) override;
void visit(KisGroupLayer *layer, KisUndoAdapter *undoAdapter) override;
@@ -57,6 +61,8 @@ private:
void transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *adapter, const ProgressHelper &helper);
void transformSelection(KisSelectionSP selection, KisUndoAdapter *adapter, const ProgressHelper &helper);
+ void transformOneDevice(KisPaintDeviceSP device, KoUpdater *updater);
+
private:
qreal m_sx, m_sy;
qint32 m_tx, m_ty;
@@ -65,6 +71,7 @@ private:
KisFilterStrategy *m_filter;
qreal m_angle;
QTransform m_shapesCorrection;
+ KisSelectionBasedProcessingHelper m_selectionHelper;
};
#endif /* __KIS_TRANSFORM_PROCESSING_VISITOR_H */
diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp
index 3341db586bb..521dc6e5082 100644
--- a/libs/libkis/Node.cpp
+++ b/libs/libkis/Node.cpp
@@ -50,6 +50,7 @@
#include <kis_raster_keyframe_channel.h>
#include <kis_keyframe.h>
+#include "kis_selection.h"
#include "Krita.h"
#include "Node.h"
@@ -546,7 +547,7 @@ Node* Node::mergeDown()
return new Node(d->image, d->node->prevSibling());
}
-void Node::scaleNode(int width, int height, QString strategy)
+void Node::scaleNode(const QPointF &origin, int width, int height, QString strategy)
{
if (!d->node) return;
if (!qobject_cast<KisLayer*>(d->node.data())) return;
@@ -555,7 +556,13 @@ void Node::scaleNode(int width, int height, QString strategy)
KisFilterStrategy *actualStrategy = KisFilterStrategyRegistry::instance()->get(strategy);
if (!actualStrategy) actualStrategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
- d->image->scaleNode(d->node, width, height, actualStrategy);
+ const QRect bounds(d->node->exactBounds());
+
+ d->image->scaleNode(d->node,
+ origin,
+ qreal(width) / bounds.width(),
+ qreal(height) / bounds.height(),
+ actualStrategy, 0);
}
void Node::rotateNode(double radians)
@@ -564,7 +571,7 @@ void Node::rotateNode(double radians)
if (!qobject_cast<KisLayer*>(d->node.data())) return;
if (!d->node->parent()) return;
- d->image->rotateNode(d->node, radians);
+ d->image->rotateNode(d->node, radians, 0);
}
void Node::cropNode(int x, int y, int w, int h)
@@ -583,7 +590,7 @@ void Node::shearNode(double angleX, double angleY)
if (!qobject_cast<KisLayer*>(d->node.data())) return;
if (!d->node->parent()) return;
- d->image->shearNode(d->node, angleX, angleY);
+ d->image->shearNode(d->node, angleX, angleY, 0);
}
QImage Node::thumbnail(int w, int h)
diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h
index 790ee974c6e..11019b73d49 100644
--- a/libs/libkis/Node.h
+++ b/libs/libkis/Node.h
@@ -489,7 +489,7 @@ public Q_SLOTS:
* <li>Mitchell</li>
* </ul>
*/
- void scaleNode(int width, int height, QString strategy);
+ void scaleNode(const QPointF &origin, int width, int height, QString strategy);
/**
* @brief rotateNode rotate this layer by the given radians.
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index bb15a54a192..74973e3ba86 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -294,7 +294,6 @@ set(kritaui_LIB_SRCS
actions/KisPasteActionFactory.cpp
input/kis_touch_shortcut.cpp
kis_document_undo_store.cpp
- kis_transaction_based_command.cpp
kis_gui_context_command.cpp
kis_gui_context_command_p.cpp
input/kis_tablet_debugger.cpp
diff --git a/libs/ui/actions/kis_selection_action_factories.cpp b/libs/ui/actions/kis_selection_action_factories.cpp
index 5a0b4bb13b3..5952680035d 100644
--- a/libs/ui/actions/kis_selection_action_factories.cpp
+++ b/libs/ui/actions/kis_selection_action_factories.cpp
@@ -54,7 +54,7 @@
#include "kis_canvas2.h"
#include "kis_canvas_controller.h"
#include "kis_selection_manager.h"
-#include "kis_transaction_based_command.h"
+#include "commands_new/kis_transaction_based_command.h"
#include "kis_selection_filters.h"
#include "kis_shape_selection.h"
#include "kis_shape_layer.h"
diff --git a/libs/ui/kis_node_manager.cpp b/libs/ui/kis_node_manager.cpp
index bf1eab182d1..45acb4cf796 100644
--- a/libs/ui/kis_node_manager.cpp
+++ b/libs/ui/kis_node_manager.cpp
@@ -251,12 +251,20 @@ void KisNodeManager::setup(KActionCollection * actionCollection, KisActionManage
m_d->layerManager.setup(actionManager);
m_d->maskManager.setup(actionCollection, actionManager);
- KisAction * action = actionManager->createAction("mirrorNodeX");
+ KisAction * action = 0;
+
+ action = actionManager->createAction("mirrorNodeX");
connect(action, SIGNAL(triggered()), this, SLOT(mirrorNodeX()));
action = actionManager->createAction("mirrorNodeY");
connect(action, SIGNAL(triggered()), this, SLOT(mirrorNodeY()));
+ action = actionManager->createAction("mirrorAllNodesX");
+ connect(action, SIGNAL(triggered()), this, SLOT(mirrorAllNodesX()));
+
+ action = actionManager->createAction("mirrorAllNodesY");
+ connect(action, SIGNAL(triggered()), this, SLOT(mirrorAllNodesY()));
+
action = actionManager->createAction("activateNextLayer");
connect(action, SIGNAL(triggered()), this, SLOT(activateNextNode()));
@@ -904,7 +912,7 @@ void KisNodeManager::mirrorNodeX()
} else if (node->inherits("KisMask")) {
commandName = kundo2_i18n("Mirror Mask X");
}
- mirrorNode(node, commandName, Qt::Horizontal);
+ mirrorNode(node, commandName, Qt::Horizontal, m_d->view->selection());
}
void KisNodeManager::mirrorNodeY()
@@ -917,7 +925,21 @@ void KisNodeManager::mirrorNodeY()
} else if (node->inherits("KisMask")) {
commandName = kundo2_i18n("Mirror Mask Y");
}
- mirrorNode(node, commandName, Qt::Vertical);
+ mirrorNode(node, commandName, Qt::Vertical, m_d->view->selection());
+}
+
+void KisNodeManager::mirrorAllNodesX()
+{
+ KisNodeSP node = m_d->view->image()->root();
+ mirrorNode(node, kundo2_i18n("Mirror All Layers X"),
+ Qt::Vertical, m_d->view->selection());
+}
+
+void KisNodeManager::mirrorAllNodesY()
+{
+ KisNodeSP node = m_d->view->image()->root();
+ mirrorNode(node, kundo2_i18n("Mirror All Layers Y"),
+ Qt::Vertical, m_d->view->selection());
}
void KisNodeManager::activateNextNode()
@@ -979,56 +1001,10 @@ void KisNodeManager::switchToPreviouslyActiveNode()
}
}
-void KisNodeManager::rotate(double radians)
-{
- if(!m_d->view->image()) return;
-
- KisNodeSP node = activeNode();
- if (!node) return;
-
- if (!m_d->view->blockUntilOperationsFinished(m_d->view->image())) return;
-
- m_d->view->image()->rotateNode(node, radians);
-}
-
-void KisNodeManager::rotate180()
-{
- rotate(M_PI);
-}
-
-void KisNodeManager::rotateLeft90()
-{
- rotate(-M_PI / 2);
-}
-
-void KisNodeManager::rotateRight90()
-{
- rotate(M_PI / 2);
-}
-
-void KisNodeManager::shear(double angleX, double angleY)
-{
- if (!m_d->view->image()) return;
-
- KisNodeSP node = activeNode();
- if (!node) return;
-
- if(!m_d->view->blockUntilOperationsFinished(m_d->view->image())) return;
-
- m_d->view->image()->shearNode(node, angleX, angleY);
-}
-
-void KisNodeManager::scale(double sx, double sy, KisFilterStrategy *filterStrategy)
-{
- KisNodeSP node = activeNode();
- KIS_ASSERT_RECOVER_RETURN(node);
-
- m_d->view->image()->scaleNode(node, sx, sy, filterStrategy);
-
- nodesUpdated();
-}
-
-void KisNodeManager::mirrorNode(KisNodeSP node, const KUndo2MagicString& actionName, Qt::Orientation orientation)
+void KisNodeManager::mirrorNode(KisNodeSP node,
+ const KUndo2MagicString& actionName,
+ Qt::Orientation orientation,
+ KisSelectionSP selection)
{
KisImageSignalVector emitSignals;
emitSignals << ModifiedSignal;
@@ -1037,10 +1013,20 @@ void KisNodeManager::mirrorNode(KisNodeSP node, const KUndo2MagicString& actionN
KisProcessingApplicator::RECURSIVE,
emitSignals, actionName);
- KisProcessingVisitorSP visitor =
- new KisMirrorProcessingVisitor(m_d->view->image()->bounds(), orientation);
+ KisProcessingVisitorSP visitor;
+
+ if (selection) {
+ visitor = new KisMirrorProcessingVisitor(selection, orientation);
+ } else {
+ visitor = new KisMirrorProcessingVisitor(m_d->view->image()->bounds(), orientation);
+ }
+
+ if (!selection) {
+ applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
+ } else {
+ applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+ }
- applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
applicator.end();
nodesUpdated();
diff --git a/libs/ui/kis_node_manager.h b/libs/ui/kis_node_manager.h
index dabe293cb2b..29c80823d02 100644
--- a/libs/ui/kis_node_manager.h
+++ b/libs/ui/kis_node_manager.h
@@ -180,7 +180,13 @@ public Q_SLOTS:
void removeNode();
void mirrorNodeX();
void mirrorNodeY();
- void mirrorNode(KisNodeSP node, const KUndo2MagicString& commandName, Qt::Orientation orientation);
+ void mirrorAllNodesX();
+ void mirrorAllNodesY();
+
+
+ void mirrorNode(KisNodeSP node, const KUndo2MagicString& commandName, Qt::Orientation orientation, KisSelectionSP selection);
+
+
void activateNextNode();
void activatePreviousNode();
void switchToPreviouslyActiveNode();
@@ -195,11 +201,6 @@ public Q_SLOTS:
*/
void lowerNode();
- void rotate(double radians);
- void rotate180();
- void rotateLeft90();
- void rotateRight90();
-
void saveNodeAsImage();
void saveVectorLayerAsImage();
@@ -235,12 +236,6 @@ public Q_SLOTS:
void selectUnlockedNodes();
public:
-
-
- void shear(double angleX, double angleY);
-
- void scale(double sx, double sy, KisFilterStrategy *filterStrategy);
-
void removeSingleNode(KisNodeSP node);
KisLayerSP createPaintLayer();
diff --git a/libs/ui/operations/kis_filter_selection_operation.cpp b/libs/ui/operations/kis_filter_selection_operation.cpp
index d0e3226bb9c..ed02df14574 100644
--- a/libs/ui/operations/kis_filter_selection_operation.cpp
+++ b/libs/ui/operations/kis_filter_selection_operation.cpp
@@ -19,7 +19,7 @@
#include "kis_filter_selection_operation.h"
-#include <kis_transaction_based_command.h>
+#include <commands_new/kis_transaction_based_command.h>
#include <KisViewManager.h>
#include <kis_stroke_job_strategy.h>
#include <kis_selection_filters.h>
diff --git a/libs/ui/tests/kis_node_manager_test.cpp b/libs/ui/tests/kis_node_manager_test.cpp
index c8c293d0836..9486dfbf0ea 100644
--- a/libs/ui/tests/kis_node_manager_test.cpp
+++ b/libs/ui/tests/kis_node_manager_test.cpp
@@ -68,80 +68,6 @@ public:
KisNodeManager *nodeManager;
};
-void testRotateNode(bool useShapeLayer, const QString &name)
-{
- NodeManagerTester t;
- if(useShapeLayer) {
- t.activateShapeLayer();
- }
-
- t.nodeManager->rotate(M_PI / 6.0);
- QTest::qWait(1000);
- t.image->waitForDone();
- QVERIFY(t.checkLayersFuzzy(name));
-
- t.checkUndoWait();
- t.startConcurrentTask();
-
- t.nodeManager->rotate(M_PI / 6.0);
- QTest::qWait(1000);
- t.image->waitForDone();
-
- if (!useShapeLayer) {
- QEXPECT_FAIL("", "The user may run Rotate Layer concurrently. It will cause wrong image/selection size fetched for the crop. There is some barrier needed. At least it doesn't crash.", Continue);
- }
- QVERIFY(t.checkLayersFuzzy(name));
-}
-
-void testShearNode(bool useShapeLayer, const QString &name)
-{
- NodeManagerTester t;
- if(useShapeLayer) {
- t.activateShapeLayer();
- }
-
- t.nodeManager->shear(30, 0);
- QTest::qWait(1000);
- t.image->waitForDone();
- QVERIFY(t.checkLayersFuzzy(name));
-
- t.checkUndoWait();
- t.startConcurrentTask();
-
- t.nodeManager->shear(30, 0);
- QTest::qWait(1000);
- t.image->waitForDone();
-
- QEXPECT_FAIL("", "The user may run Shear Layer concurrently. It will cause wrong image/selection size fetched for the crop. There is some barrier needed. At least it doesn't crash.", Continue);
- QVERIFY(t.checkLayersFuzzy(name));
-}
-
-void testScaleNode(bool useShapeLayer, const QString &name)
-{
- KisFilterStrategy *strategy = new KisBicubicFilterStrategy();
-
- NodeManagerTester t;
- if(useShapeLayer) {
- t.activateShapeLayer();
- }
-
- t.nodeManager->scale(0.5, 0.5, strategy);
- QTest::qWait(1000);
- t.image->waitForDone();
- QVERIFY(t.checkLayersFuzzy(name));
-
- t.checkUndoWait();
- t.startConcurrentTask();
-
- t.nodeManager->scale(0.5, 0.5, strategy);
- QTest::qWait(1000);
- t.image->waitForDone();
-
- QVERIFY(t.checkLayersFuzzy(name));
-
- delete strategy;
-}
-
void testMirrorNode(bool useShapeLayer, const QString &name, bool mirrorX)
{
NodeManagerTester t;
@@ -173,21 +99,6 @@ void testMirrorNode(bool useShapeLayer, const QString &name, bool mirrorX)
QVERIFY(t.checkLayersFuzzy(name));
}
-void KisNodeManagerTest::testRotatePaintNode()
-{
- testRotateNode(false, "paint_rotated_30");
-}
-
-void KisNodeManagerTest::testShearPaintNode()
-{
- testShearNode(false, "paint_shear_30");
-}
-
-void KisNodeManagerTest::testScalePaintNode()
-{
- testScaleNode(false, "paint_scale_0.5");
-}
-
void KisNodeManagerTest::testMirrorXPaintNode()
{
testMirrorNode(false, "paint_mirrorX", true);
@@ -198,21 +109,6 @@ void KisNodeManagerTest::testMirrorYPaintNode()
testMirrorNode(false, "paint_mirrorY", false);
}
-void KisNodeManagerTest::testRotateShapeNode()
-{
- testRotateNode(true, "shape_rotated_30");
-}
-
-void KisNodeManagerTest::testShearShapeNode()
-{
- testShearNode(true, "shape_shear_30");
-}
-
-void KisNodeManagerTest::testScaleShapeNode()
-{
- testScaleNode(true, "shape_scale_0.5");
-}
-
void KisNodeManagerTest::testMirrorShapeNode()
{
testMirrorNode(true, "shape_mirrorX", true);
diff --git a/libs/ui/tests/kis_node_manager_test.h b/libs/ui/tests/kis_node_manager_test.h
index 0401b95a1b4..458d512213a 100644
--- a/libs/ui/tests/kis_node_manager_test.h
+++ b/libs/ui/tests/kis_node_manager_test.h
@@ -25,15 +25,9 @@ class KisNodeManagerTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
- void testRotatePaintNode();
- void testShearPaintNode();
- void testScalePaintNode();
void testMirrorXPaintNode();
void testMirrorYPaintNode();
- void testRotateShapeNode();
- void testShearShapeNode();
- void testScaleShapeNode();
void testMirrorShapeNode();
void testConvertCloneToPaintLayer();
diff --git a/libs/ui/tool/kis_selection_tool_helper.cpp b/libs/ui/tool/kis_selection_tool_helper.cpp
index 198fae9ac7b..fa3684dd249 100644
--- a/libs/ui/tool/kis_selection_tool_helper.cpp
+++ b/libs/ui/tool/kis_selection_tool_helper.cpp
@@ -36,7 +36,7 @@
#include <kis_icon.h>
#include "kis_processing_applicator.h"
-#include "kis_transaction_based_command.h"
+#include "commands_new/kis_transaction_based_command.h"
#include "kis_gui_context_command.h"
#include "kis_command_utils.h"
#include "commands/kis_deselect_global_selection_command.h"
diff --git a/plugins/dockers/gamutmask/gamutmask_dock.cpp b/plugins/dockers/gamutmask/gamutmask_dock.cpp
index 781b0244f97..5343eefe7ad 100644
--- a/plugins/dockers/gamutmask/gamutmask_dock.cpp
+++ b/plugins/dockers/gamutmask/gamutmask_dock.cpp
@@ -352,7 +352,7 @@ KoGamutMask *GamutMaskDock::createMaskResource(KoGamutMask* sourceMask, QString
newMask = new KoGamutMask();
QString defaultPreviewPath = KoResourcePaths::findResource("ko_gamutmasks", "empty_mask_preview.png");
- KIS_SAFE_ASSERT_RECOVER(!(defaultPreviewPath.isEmpty() || defaultPreviewPath.isNull() || !QFile::exists(defaultPreviewPath)));
+ KIS_SAFE_ASSERT_RECOVER_NOOP(!(defaultPreviewPath.isEmpty() || defaultPreviewPath.isNull() || !QFile::exists(defaultPreviewPath)));
newMask->setImage(QImage(defaultPreviewPath, "PNG"));
}
diff --git a/plugins/extensions/imagesize/imagesize.cc b/plugins/extensions/imagesize/imagesize.cc
index 7adb79aaa0e..236afc02f17 100644
--- a/plugins/extensions/imagesize/imagesize.cc
+++ b/plugins/extensions/imagesize/imagesize.cc
@@ -57,6 +57,9 @@ ImageSize::ImageSize(QObject *parent, const QVariantList &)
action = createAction("layersize");
connect(action, SIGNAL(triggered()), this, SLOT(slotLayerSize()));
+ action = createAction("scaleAllLayers");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotScaleAllLayers()));
+
action = createAction("selectionscale");
connect(action, SIGNAL(triggered()), this, SLOT(slotSelectionScale()));
}
@@ -70,6 +73,8 @@ void ImageSize::slotImageSize()
KisImageSP image = viewManager()->image().toStrongRef();
if (!image) return;
+ if(!viewManager()->blockUntilOperationsFinished(image)) return;
+
DlgImageSize * dlgImageSize = new DlgImageSize(viewManager()->mainWindow(), image->width(), image->height(), image->yRes());
Q_CHECK_PTR(dlgImageSize);
dlgImageSize->setObjectName("ImageSize");
@@ -88,9 +93,10 @@ void ImageSize::slotImageSize()
void ImageSize::slotCanvasSize()
{
KisImageWSP image = viewManager()->image();
-
if (!image) return;
+ if(!viewManager()->blockUntilOperationsFinished(image)) return;
+
DlgCanvasSize * dlgCanvasSize = new DlgCanvasSize(viewManager()->mainWindow(), image->width(), image->height(), image->yRes());
Q_CHECK_PTR(dlgCanvasSize);
@@ -105,17 +111,25 @@ void ImageSize::slotCanvasSize()
delete dlgCanvasSize;
}
-void ImageSize::slotLayerSize()
+void ImageSize::scaleLayerImpl(KisNodeSP rootNode)
{
KisImageWSP image = viewManager()->image();
-
if (!image) return;
- KisPaintDeviceSP dev = viewManager()->activeLayer()->projection();
- Q_ASSERT(dev);
- QRect rc = dev->exactBounds();
+ if(!viewManager()->blockUntilOperationsFinished(image)) return;
- DlgLayerSize * dlgLayerSize = new DlgLayerSize(viewManager()->mainWindow(), "LayerSize", rc.width(), rc.height(), image->yRes());
+ QRect bounds;
+ KisSelectionSP selection = viewManager()->selection();
+
+ if (selection) {
+ bounds = selection->selectedExactRect();
+ } else {
+ KisPaintDeviceSP dev = rootNode->projection();
+ KIS_SAFE_ASSERT_RECOVER_RETURN(dev);
+ bounds = dev->exactBounds();
+ }
+
+ DlgLayerSize * dlgLayerSize = new DlgLayerSize(viewManager()->mainWindow(), "LayerSize", bounds.width(), bounds.height(), image->yRes());
Q_CHECK_PTR(dlgLayerSize);
dlgLayerSize->setCaption(i18n("Resize Layer"));
@@ -123,19 +137,36 @@ void ImageSize::slotLayerSize()
qint32 w = dlgLayerSize->width();
qint32 h = dlgLayerSize->height();
- viewManager()->nodeManager()->scale((double)w / ((double)(rc.width())),
- (double)h / ((double)(rc.height())),
- dlgLayerSize->filterType());
+ viewManager()->image()->scaleNode(rootNode,
+ QRectF(bounds).center(),
+ qreal(w) / bounds.width(),
+ qreal(h) / bounds.height(),
+ dlgLayerSize->filterType(),
+ selection);
}
delete dlgLayerSize;
}
+void ImageSize::slotLayerSize()
+{
+ scaleLayerImpl(viewManager()->activeNode());
+}
+
+void ImageSize::slotScaleAllLayers()
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ scaleLayerImpl(image->root());
+}
+
void ImageSize::slotSelectionScale()
{
KisImageSP image = viewManager()->image();
- if (!image) {
- return;
- }
+ if (!image) return;
+
+ if(!viewManager()->blockUntilOperationsFinished(image)) return;
+
KisLayerSP layer = viewManager()->activeLayer();
KIS_ASSERT_RECOVER_RETURN(image && layer);
@@ -156,9 +187,10 @@ void ImageSize::slotSelectionScale()
qint32 h = dlgSize->height();
image->scaleNode(selectionMask,
+ QRectF(rc).center(),
qreal(w) / rc.width(),
qreal(h) / rc.height(),
- dlgSize->filterType());
+ dlgSize->filterType(), 0);
}
delete dlgSize;
}
diff --git a/plugins/extensions/imagesize/imagesize.h b/plugins/extensions/imagesize/imagesize.h
index 892fc333eeb..bcf1093031d 100644
--- a/plugins/extensions/imagesize/imagesize.h
+++ b/plugins/extensions/imagesize/imagesize.h
@@ -23,6 +23,7 @@
#include <QVariant>
#include <KisActionPlugin.h>
+#include "kis_types.h"
class ImageSize : public KisActionPlugin
{
@@ -31,12 +32,17 @@ public:
ImageSize(QObject *parent, const QVariantList &);
~ImageSize() override;
+private:
+ void scaleLayerImpl(KisNodeSP rootNode);
+
private Q_SLOTS:
void slotImageSize();
void slotCanvasSize();
void slotLayerSize();
void slotSelectionScale();
+
+ void slotScaleAllLayers();
};
#endif // IMAGESIZE_H
diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip
index fdd535229e5..b52cb24d5c9 100644
--- a/plugins/extensions/pykrita/sip/krita/Node.sip
+++ b/plugins/extensions/pykrita/sip/krita/Node.sip
@@ -55,7 +55,7 @@ public Q_SLOTS:
Node *duplicate() /Factory/;
void save(const QString &filename, double xRes, double yRes);
Node *mergeDown() /Factory/;
- void scaleNode(int width, int height, QString strategy);
+ void scaleNode(const QPointF &origin, int width, int height, QString strategy);
void rotateNode(double radians);
void cropNode(int x, int y, int w, int h);
void shearNode(double angleX, double angleY);
diff --git a/plugins/extensions/rotateimage/rotateimage.cc b/plugins/extensions/rotateimage/rotateimage.cc
index 97dd9bdeca7..795060f92fd 100644
--- a/plugins/extensions/rotateimage/rotateimage.cc
+++ b/plugins/extensions/rotateimage/rotateimage.cc
@@ -35,6 +35,7 @@
#include <kis_canvas_resource_provider.h>
#include <kis_group_layer.h>
#include <kis_action.h>
+#include <kis_selection.h>
#include "dlg_rotateimage.h"
@@ -66,13 +67,25 @@ RotateImage::RotateImage(QObject *parent, const QVariantList &)
connect(action, SIGNAL(triggered()), this, SLOT(slotRotateLayer()));
action = createAction("rotateLayer180");
- connect(action, SIGNAL(triggered()), viewManager()->nodeManager(), SLOT(rotate180()));
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateLayer180()));
action = createAction("rotateLayerCW90");
- connect(action, SIGNAL(triggered()), viewManager()->nodeManager(), SLOT(rotateRight90()));
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateLayerCW90()));
action = createAction("rotateLayerCCW90");
- connect(action, SIGNAL(triggered()), viewManager()->nodeManager(), SLOT(rotateLeft90()));
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateLayerCCW90()));
+
+ action = createAction("rotateAllLayers");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateAllLayers()));
+
+ action = createAction("rotateAllLayersCW90");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateAllLayersCW90()));
+
+ action = createAction("rotateAllLayersCCW90");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateAllLayersCCW90()));
+
+ action = createAction("rotateAllLayers180");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotRotateAllLayers180()));
}
RotateImage::~RotateImage()
@@ -82,9 +95,10 @@ RotateImage::~RotateImage()
void RotateImage::slotRotateImage()
{
KisImageWSP image = viewManager()->image();
-
if (!image) return;
+ if (!viewManager()->blockUntilOperationsFinished(image)) return;
+
DlgRotateImage * dlgRotateImage = new DlgRotateImage(viewManager()->mainWindow(), "RotateImage");
Q_CHECK_PTR(dlgRotateImage);
@@ -116,22 +130,28 @@ void RotateImage::slotMirrorImageVertical()
{
KisImageWSP image = viewManager()->image();
if (!image) return;
- viewManager()->nodeManager()->mirrorNode(image->rootLayer(), kundo2_i18n("Mirror Image Vertically"), Qt::Vertical);
+ viewManager()->nodeManager()->mirrorNode(image->rootLayer(),
+ kundo2_i18n("Mirror Image Vertically"),
+ Qt::Vertical, 0);
}
void RotateImage::slotMirrorImageHorizontal()
{
KisImageWSP image = viewManager()->image();
if (!image) return;
- viewManager()->nodeManager()->mirrorNode(image->rootLayer(), kundo2_i18n("Mirror Image Horizontally"), Qt::Horizontal);
+ viewManager()->nodeManager()->mirrorNode(image->rootLayer(),
+ kundo2_i18n("Mirror Image Horizontally"),
+ Qt::Horizontal, 0);
}
-void RotateImage::slotRotateLayer()
+
+void RotateImage::rotateLayerCustomImpl(KisNodeSP rootNode)
{
KisImageWSP image = viewManager()->image();
-
if (!image) return;
+ if (!viewManager()->blockUntilOperationsFinished(image)) return;
+
DlgRotateImage * dlgRotateImage = new DlgRotateImage(viewManager()->mainWindow(), "RotateLayer");
Q_CHECK_PTR(dlgRotateImage);
@@ -139,10 +159,71 @@ void RotateImage::slotRotateLayer()
if (dlgRotateImage->exec() == QDialog::Accepted) {
double angle = dlgRotateImage->angle() * M_PI / 180;
- viewManager()->nodeManager()->rotate(angle);
-
+ image->rotateNode(rootNode, angle, viewManager()->selection());
}
delete dlgRotateImage;
}
+void RotateImage::rotateLayerImpl(KisNodeSP rootNode, qreal radians)
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ if (!viewManager()->blockUntilOperationsFinished(image)) return;
+
+ image->rotateNode(rootNode, radians, viewManager()->selection());
+}
+
+void RotateImage::slotRotateLayer()
+{
+ rotateLayerCustomImpl(viewManager()->activeLayer());
+}
+
+void RotateImage::slotRotateAllLayers()
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ rotateLayerCustomImpl(image->root());
+}
+
+void RotateImage::slotRotateLayerCW90()
+{
+ rotateLayerImpl(viewManager()->activeLayer(), M_PI / 2);
+}
+
+void RotateImage::slotRotateLayerCCW90()
+{
+ rotateLayerImpl(viewManager()->activeLayer(), -M_PI / 2);
+}
+
+void RotateImage::slotRotateLayer180()
+{
+ rotateLayerImpl(viewManager()->activeLayer(), M_PI);
+}
+
+void RotateImage::slotRotateAllLayersCW90()
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ rotateLayerImpl(image->root(), M_PI / 2);
+}
+
+void RotateImage::slotRotateAllLayersCCW90()
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ rotateLayerImpl(image->root(), -M_PI / 2);
+}
+
+void RotateImage::slotRotateAllLayers180()
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ rotateLayerImpl(image->root(), M_PI);
+}
+
#include "rotateimage.moc"
diff --git a/plugins/extensions/rotateimage/rotateimage.h b/plugins/extensions/rotateimage/rotateimage.h
index b0e88dcb23d..22e4d5e8019 100644
--- a/plugins/extensions/rotateimage/rotateimage.h
+++ b/plugins/extensions/rotateimage/rotateimage.h
@@ -23,6 +23,7 @@
#include <QVariant>
#include <KisActionPlugin.h>
+#include "kis_types.h"
class RotateImage : public KisActionPlugin
{
@@ -31,6 +32,10 @@ public:
RotateImage(QObject *parent, const QVariantList &);
~RotateImage() override;
+private:
+ void rotateLayerCustomImpl(KisNodeSP rootNode);
+ void rotateLayerImpl(KisNodeSP rootNode, qreal radians);
+
private Q_SLOTS:
void slotRotateImage();
@@ -40,6 +45,13 @@ private Q_SLOTS:
void slotMirrorImageVertical();
void slotMirrorImageHorizontal();
void slotRotateLayer();
+ void slotRotateLayerCW90();
+ void slotRotateLayerCCW90();
+ void slotRotateLayer180();
+ void slotRotateAllLayers();
+ void slotRotateAllLayersCW90();
+ void slotRotateAllLayersCCW90();
+ void slotRotateAllLayers180();
};
#endif // ROTATEIMAGE_H
diff --git a/plugins/extensions/shearimage/shearimage.cc b/plugins/extensions/shearimage/shearimage.cc
index ff009807d27..a89bca0d11e 100644
--- a/plugins/extensions/shearimage/shearimage.cc
+++ b/plugins/extensions/shearimage/shearimage.cc
@@ -28,6 +28,7 @@
#include <kis_node_manager.h>
#include <kis_image_manager.h>
#include <kis_action.h>
+#include "kis_selection.h"
#include "dlg_shearimage.h"
@@ -41,6 +42,9 @@ ShearImage::ShearImage(QObject *parent, const QVariantList &)
action = createAction("shearlayer");
connect(action, SIGNAL(triggered()), this, SLOT(slotShearLayer()));
+
+ action = createAction("shearAllLayers");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotShearAllLayers()));
}
ShearImage::~ShearImage()
@@ -50,9 +54,10 @@ ShearImage::~ShearImage()
void ShearImage::slotShearImage()
{
KisImageWSP image = viewManager()->image();
-
if (!image) return;
+ if (!viewManager()->blockUntilOperationsFinished(image)) return;
+
DlgShearImage * dlgShearImage = new DlgShearImage(viewManager()->mainWindow(), "ShearImage");
Q_CHECK_PTR(dlgShearImage);
@@ -66,12 +71,13 @@ void ShearImage::slotShearImage()
delete dlgShearImage;
}
-void ShearImage::slotShearLayer()
+void ShearImage::shearLayerImpl(KisNodeSP rootNode)
{
KisImageWSP image = viewManager()->image();
-
if (!image) return;
+ if (!viewManager()->blockUntilOperationsFinished(image)) return;
+
DlgShearImage * dlgShearImage = new DlgShearImage(viewManager()->mainWindow(), "ShearLayer");
Q_CHECK_PTR(dlgShearImage);
@@ -80,10 +86,25 @@ void ShearImage::slotShearLayer()
if (dlgShearImage->exec() == QDialog::Accepted) {
qint32 angleX = dlgShearImage->angleX();
qint32 angleY = dlgShearImage->angleY();
- viewManager()->nodeManager()->shear(angleX, angleY);
+ image->shearNode(rootNode,
+ angleX, angleY,
+ viewManager()->selection());
}
delete dlgShearImage;
}
+void ShearImage::slotShearLayer()
+{
+ shearLayerImpl(viewManager()->activeNode());
+}
+
+void ShearImage::slotShearAllLayers()
+{
+ KisImageWSP image = viewManager()->image();
+ if (!image) return;
+
+ shearLayerImpl(image->root());
+}
+
#include "shearimage.moc"
diff --git a/plugins/extensions/shearimage/shearimage.h b/plugins/extensions/shearimage/shearimage.h
index 49487245135..452958849cc 100644
--- a/plugins/extensions/shearimage/shearimage.h
+++ b/plugins/extensions/shearimage/shearimage.h
@@ -23,6 +23,8 @@
#include <QVariant>
#include <KisActionPlugin.h>
+#include "kis_types.h"
+
class ShearImage : public KisActionPlugin
{
@@ -31,10 +33,14 @@ public:
ShearImage(QObject *parent, const QVariantList &);
~ShearImage() override;
+private:
+ void shearLayerImpl(KisNodeSP rootNode);
+
private Q_SLOTS:
void slotShearImage();
void slotShearLayer();
+ void slotShearAllLayers();
};
#endif // SHEARIMAGE_H
diff --git a/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp b/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp
index 656ba388cab..b969bcd7eab 100644
--- a/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp
+++ b/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp
@@ -31,7 +31,7 @@
#include "kundo2magicstring.h"
#include "kundo2stack.h"
-#include "kis_transaction_based_command.h"
+#include "commands_new/kis_transaction_based_command.h"
#include "kis_transaction.h"
#include "kis_processing_applicator.h"
More information about the kimageshop
mailing list