Krita Source Code Documentation
Loading...
Searching...
No Matches
KisLayerUtils::RemoveNodeHelper Class Referenceabstract

#include <kis_layer_utils.h>

+ Inheritance diagram for KisLayerUtils::RemoveNodeHelper:

Classes

struct  ReplacementNode
 

Public Member Functions

virtual ~RemoveNodeHelper ()
 

Protected Member Functions

virtual void addCommandImpl (KUndo2Command *cmd)=0
 
void safeRemoveMultipleNodes (KisNodeList nodes, KisImageSP image)
 
void safeReplaceMultipleNodes (KisNodeList removedNodes, KisImageSP image, std::optional< ReplacementNode > replacementNode)
 

Private Member Functions

bool checkIsSourceForClone (KisNodeSP src, const KisNodeList &nodes)
 

Static Private Member Functions

static bool scanForLastLayer (KisImageWSP image, KisNodeList nodesToRemove)
 

Detailed Description

Definition at line 162 of file kis_layer_utils.h.

Constructor & Destructor Documentation

◆ ~RemoveNodeHelper()

KisLayerUtils::RemoveNodeHelper::~RemoveNodeHelper ( )
virtual

Definition at line 920 of file kis_layer_utils.cpp.

921 {
922 }

Member Function Documentation

◆ addCommandImpl()

virtual void KisLayerUtils::RemoveNodeHelper::addCommandImpl ( KUndo2Command * cmd)
protectedpure virtual

◆ checkIsSourceForClone()

bool KisLayerUtils::RemoveNodeHelper::checkIsSourceForClone ( KisNodeSP src,
const KisNodeList & nodes )
private

Definition at line 1025 of file kis_layer_utils.cpp.

1025 {
1026 foreach (KisNodeSP node, nodes) {
1027 if (node == src) continue;
1028
1029 KisCloneLayer *clone = dynamic_cast<KisCloneLayer*>(node.data());
1030
1031 if (clone && KisNodeSP(clone->copyFrom()) == src) {
1032 return true;
1033 }
1034 }
1035
1036 return false;
1037 }
KisSharedPtr< KisNode > KisNodeSP
Definition kis_types.h:86
KisLayerSP copyFrom

References KisCloneLayer::copyFrom, and KisSharedPtr< T >::data().

◆ safeRemoveMultipleNodes()

void KisLayerUtils::RemoveNodeHelper::safeRemoveMultipleNodes ( KisNodeList nodes,
KisImageSP image )
protected

The removal of two nodes in one go may be a bit tricky, because one of them may be the clone of another. If we remove the source of a clone layer, it will reincarnate into a paint layer. In this case the pointer to the second layer will be lost.

That's why we need to care about the order of the nodes removal: the clone — first, the source — last.

Definition at line 933 of file kis_layer_utils.cpp.

933 {
934 safeReplaceMultipleNodes(nodes, image, std::nullopt);
935 }
void safeReplaceMultipleNodes(KisNodeList removedNodes, KisImageSP image, std::optional< ReplacementNode > replacementNode)

References safeReplaceMultipleNodes().

◆ safeReplaceMultipleNodes()

void KisLayerUtils::RemoveNodeHelper::safeReplaceMultipleNodes ( KisNodeList removedNodes,
KisImageSP image,
std::optional< ReplacementNode > replacementNode )
protected

Definition at line 937 of file kis_layer_utils.cpp.

938 {
939
940 const bool lastLayer = !replacementNode && scanForLastLayer(image, removedNodes);
941
942 auto isNodeWeird = [] (KisNodeSP node) {
943 const bool normalCompositeMode = node->compositeOpId() == COMPOSITE_OVER;
944
945 KisLayer *layer = dynamic_cast<KisLayer*>(node.data());
946 const bool hasInheritAlpha = layer && layer->alphaChannelDisabled();
947 return !normalCompositeMode && !hasInheritAlpha;
948 };
949
950
953 RecipeSP updateRecipe(new Recipe());
954
955 if (replacementNode) {
956 updateRecipe->nodesToAdd.push_back({replacementNode->node,
957 replacementNode->doRedoUpdates,
958 replacementNode->doUndoUpdates});
959 }
960
961 Q_FOREACH (KisNodeSP node, removedNodes) {
962 updateRecipe->nodesToRemove.push_back({node, !isNodeWeird(node), true});
963 }
964
966
967 if (replacementNode) {
969 replacementNode->node,
970 replacementNode->parent,
971 replacementNode->putAfter,
972 false, false));
973
974 Q_FOREACH (KisSelectionMaskSP mask, replacementNode->selectionMasks) {
975 addCommandImpl(new KisImageLayerMoveCommand(image, mask, replacementNode->node, replacementNode->node->lastChild(), false));
977 }
978
979 // relink all the clone layers onto the new replacement node
980 if (replacementNode->relinkClones) {
982
983 Q_FOREACH (KisNodeSP node, removedNodes) {
984 KisLayerSP originalSource = dynamic_cast<KisLayer*>(node.data());
985 if (originalSource) {
986 clones.append(originalSource->registeredClones());
987 }
988 }
989
990 KisLayerSP finalSource = dynamic_cast<KisLayer*>(replacementNode->node.data());
991
992 if (finalSource && !clones.isEmpty()) {
993 addCommandImpl(new KisChangeCloneLayersCommand(implicitCastList<KisCloneLayerSP>(clones), finalSource));
994 }
995 }
996 }
997
998 while (!removedNodes.isEmpty()) {
999 KisNodeList::iterator it = removedNodes.begin();
1000
1001 while (it != removedNodes.end()) {
1002 if (!checkIsSourceForClone(*it, removedNodes)) {
1003 KisNodeSP node = *it;
1004
1005 addCommandImpl(new KisImageLayerRemoveCommand(image, node, false, false));
1006 it = removedNodes.erase(it);
1007 } else {
1008 ++it;
1009 }
1010 }
1011 }
1012
1014
1015 // Hint: we shouldn't include that into the batch update since this layer doesn't trigger any updates
1016 if (lastLayer) {
1017 KisLayerSP newLayer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, image->colorSpace());
1018 addCommandImpl(new KisImageLayerAddCommand(image, newLayer,
1019 image->root(),
1020 KisNodeSP(),
1021 false, false));
1022 }
1023 }
const quint8 OPACITY_OPAQUE_U8
const QString COMPOSITE_OVER
The command for adding a layer.
The command for layer moves inside the layer stack.
const KoColorSpace * colorSpace() const
QString nextLayerName(const QString &baseName="") const
Definition kis_image.cc:715
virtual void addCommandImpl(KUndo2Command *cmd)=0
bool checkIsSourceForClone(KisNodeSP src, const KisNodeList &nodes)
static bool scanForLastLayer(KisImageWSP image, KisNodeList nodesToRemove)
bool alphaChannelDisabled() const
Definition kis_layer.cc:334
const QList< KisCloneLayerWSP > registeredClones() const
Definition kis_layer.cc:484

References addCommandImpl(), KisLayer::alphaChannelDisabled(), checkIsSourceForClone(), KisImage::colorSpace(), COMPOSITE_OVER, KisSharedPtr< T >::data(), KisCommandUtils::FlipFlopCommand::FINALIZING, KisCommandUtils::FlipFlopCommand::INITIALIZING, KisNode::lastChild(), KisImage::nextLayerName(), OPACITY_OPAQUE_U8, KisLayer::registeredClones(), KisNodeFacade::root, and scanForLastLayer().

◆ scanForLastLayer()

bool KisLayerUtils::RemoveNodeHelper::scanForLastLayer ( KisImageWSP image,
KisNodeList nodesToRemove )
staticprivate

Definition at line 1039 of file kis_layer_utils.cpp.

1039 {
1040 bool removeLayers = false;
1041 Q_FOREACH(KisNodeSP nodeToRemove, nodesToRemove) {
1042 if (qobject_cast<KisLayer*>(nodeToRemove.data())) {
1043 removeLayers = true;
1044 break;
1045 }
1046 }
1047 if (!removeLayers) return false;
1048
1049 bool lastLayer = true;
1050 KisNodeSP node = image->root()->firstChild();
1051 while (node) {
1052 if (!nodesToRemove.contains(node) &&
1053 qobject_cast<KisLayer*>(node.data()) &&
1054 !node->isFakeNode()) {
1055
1056 lastLayer = false;
1057 break;
1058 }
1059 node = node->nextSibling();
1060 }
1061
1062 return lastLayer;
1063 }
virtual bool isFakeNode() const
KisNodeSP firstChild() const
Definition kis_node.cpp:361
KisNodeSP nextSibling() const
Definition kis_node.cpp:408

References KisSharedPtr< T >::data(), KisNode::firstChild(), KisBaseNode::isFakeNode(), KisNode::nextSibling(), and KisNodeFacade::root.


The documentation for this class was generated from the following files: