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 889 of file kis_layer_utils.cpp.

890 {
891 }

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 994 of file kis_layer_utils.cpp.

994 {
995 foreach (KisNodeSP node, nodes) {
996 if (node == src) continue;
997
998 KisCloneLayer *clone = dynamic_cast<KisCloneLayer*>(node.data());
999
1000 if (clone && KisNodeSP(clone->copyFrom()) == src) {
1001 return true;
1002 }
1003 }
1004
1005 return false;
1006 }
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 902 of file kis_layer_utils.cpp.

902 {
903 safeReplaceMultipleNodes(nodes, image, std::nullopt);
904 }
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 906 of file kis_layer_utils.cpp.

907 {
908
909 const bool lastLayer = !replacementNode && scanForLastLayer(image, removedNodes);
910
911 auto isNodeWeird = [] (KisNodeSP node) {
912 const bool normalCompositeMode = node->compositeOpId() == COMPOSITE_OVER;
913
914 KisLayer *layer = dynamic_cast<KisLayer*>(node.data());
915 const bool hasInheritAlpha = layer && layer->alphaChannelDisabled();
916 return !normalCompositeMode && !hasInheritAlpha;
917 };
918
919
922 RecipeSP updateRecipe(new Recipe());
923
924 if (replacementNode) {
925 updateRecipe->nodesToAdd.push_back({replacementNode->node,
926 replacementNode->doRedoUpdates,
927 replacementNode->doUndoUpdates});
928 }
929
930 Q_FOREACH (KisNodeSP node, removedNodes) {
931 updateRecipe->nodesToRemove.push_back({node, !isNodeWeird(node), true});
932 }
933
935
936 if (replacementNode) {
938 replacementNode->node,
939 replacementNode->parent,
940 replacementNode->putAfter,
941 false, false));
942
943 Q_FOREACH (KisSelectionMaskSP mask, replacementNode->selectionMasks) {
944 addCommandImpl(new KisImageLayerMoveCommand(image, mask, replacementNode->node, replacementNode->node->lastChild(), false));
946 }
947
948 // relink all the clone layers onto the new replacement node
949 if (replacementNode->relinkClones) {
951
952 Q_FOREACH (KisNodeSP node, removedNodes) {
953 KisLayerSP originalSource = dynamic_cast<KisLayer*>(node.data());
954 if (originalSource) {
955 clones.append(originalSource->registeredClones());
956 }
957 }
958
959 KisLayerSP finalSource = dynamic_cast<KisLayer*>(replacementNode->node.data());
960
961 if (finalSource && !clones.isEmpty()) {
962 addCommandImpl(new KisChangeCloneLayersCommand(implicitCastList<KisCloneLayerSP>(clones), finalSource));
963 }
964 }
965 }
966
967 while (!removedNodes.isEmpty()) {
968 KisNodeList::iterator it = removedNodes.begin();
969
970 while (it != removedNodes.end()) {
971 if (!checkIsSourceForClone(*it, removedNodes)) {
972 KisNodeSP node = *it;
973
974 addCommandImpl(new KisImageLayerRemoveCommand(image, node, false, false));
975 it = removedNodes.erase(it);
976 } else {
977 ++it;
978 }
979 }
980 }
981
983
984 // Hint: we shouldn't include that into the batch update since this layer doesn't trigger any updates
985 if (lastLayer) {
986 KisLayerSP newLayer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, image->colorSpace());
987 addCommandImpl(new KisImageLayerAddCommand(image, newLayer,
988 image->root(),
989 KisNodeSP(),
990 false, false));
991 }
992 }
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:478

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 1008 of file kis_layer_utils.cpp.

1008 {
1009 bool removeLayers = false;
1010 Q_FOREACH(KisNodeSP nodeToRemove, nodesToRemove) {
1011 if (qobject_cast<KisLayer*>(nodeToRemove.data())) {
1012 removeLayers = true;
1013 break;
1014 }
1015 }
1016 if (!removeLayers) return false;
1017
1018 bool lastLayer = true;
1019 KisNodeSP node = image->root()->firstChild();
1020 while (node) {
1021 if (!nodesToRemove.contains(node) &&
1022 qobject_cast<KisLayer*>(node.data()) &&
1023 !node->isFakeNode()) {
1024
1025 lastLayer = false;
1026 break;
1027 }
1028 node = node->nextSibling();
1029 }
1030
1031 return lastLayer;
1032 }
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: