File indexing completed on 2024-12-22 04:10:02

0001 /*
0002  *  SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
0003  *  SPDX-FileCopyrightText: 2007 Sven Langkamp <sven.langkamp@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "kis_image_layer_remove_command_impl.h"
0009 #include "kis_image.h"
0010 
0011 #include <klocalizedstring.h>
0012 #include "kis_layer.h"
0013 #include "kis_clone_layer.h"
0014 #include "kis_paint_layer.h"
0015 
0016 struct Q_DECL_HIDDEN KisImageLayerRemoveCommandImpl::Private {
0017     Private(KisImageLayerRemoveCommandImpl *_q) : q(_q) {}
0018 
0019     KisImageLayerRemoveCommandImpl *q;
0020 
0021     KisNodeSP node;
0022     KisNodeSP prevParent;
0023     KisNodeSP prevAbove;
0024 
0025     QList<KisCloneLayerSP> clonesList;
0026     QList<KisLayerSP> reincarnatedNodes;
0027 
0028     void restoreClones();
0029     void processClones(KisNodeSP node);
0030     void moveChildren(KisNodeSP src, KisNodeSP dst);
0031     void moveClones(KisLayerSP src, KisLayerSP dst);
0032 };
0033 
0034 KisImageLayerRemoveCommandImpl::KisImageLayerRemoveCommandImpl(KisImageWSP image, KisNodeSP node, KUndo2Command *parent)
0035     : KisImageCommand(kundo2_i18n("Remove Layer"), image, parent),
0036       m_d(new Private(this))
0037 {
0038     m_d->node = node;
0039     m_d->prevParent = node->parent();
0040     m_d->prevAbove = node->prevSibling();
0041 }
0042 
0043 KisImageLayerRemoveCommandImpl::~KisImageLayerRemoveCommandImpl()
0044 {
0045     delete m_d;
0046 }
0047 
0048 void KisImageLayerRemoveCommandImpl::redo()
0049 {
0050     KisImageSP image = m_image.toStrongRef();
0051     if (!image) {
0052         return;
0053     }
0054     m_d->processClones(m_d->node);
0055     image->removeNode(m_d->node);
0056 }
0057 
0058 void KisImageLayerRemoveCommandImpl::undo()
0059 {
0060     KisImageSP image = m_image.toStrongRef();
0061     if (!image) {
0062         return;
0063     }
0064     m_d->restoreClones(); // so that we can get prevAbove back, if it is our clone
0065     image->addNode(m_d->node, m_d->prevParent, m_d->prevAbove);
0066 }
0067 
0068 void KisImageLayerRemoveCommandImpl::Private::restoreClones()
0069 {
0070     Q_ASSERT(reincarnatedNodes.size() == clonesList.size());
0071     KisImageSP image = q->m_image.toStrongRef();
0072     if (!image) {
0073         return;
0074     }
0075     for (int i = 0; i < reincarnatedNodes.size(); i++) {
0076         KisCloneLayerSP clone = clonesList[i];
0077         KisLayerSP newNode = reincarnatedNodes[i];
0078 
0079         image->addNode(clone, newNode->parent(), newNode);
0080         moveChildren(newNode, clone);
0081         moveClones(newNode, clone);
0082         image->removeNode(newNode);
0083     }
0084 }
0085 
0086 void KisImageLayerRemoveCommandImpl::Private::processClones(KisNodeSP node)
0087 {
0088     KisLayerSP layer(qobject_cast<KisLayer*>(node.data()));
0089     if(!layer || !layer->hasClones()) return;
0090 
0091     if(reincarnatedNodes.isEmpty()) {
0092         /**
0093          * Initialize the list of reincarnates nodes
0094          */
0095         Q_FOREACH (KisCloneLayerWSP _clone, layer->registeredClones()) {
0096             KisCloneLayerSP clone = _clone;
0097             Q_ASSERT(clone);
0098 
0099             clonesList.append(clone);
0100             reincarnatedNodes.append(clone->reincarnateAsPaintLayer());
0101         }
0102     }
0103 
0104     KisImageSP image = q->m_image.toStrongRef();
0105     if (!image) {
0106         return;
0107     }
0108 
0109     /**
0110      * Move the children and transitive clones to the
0111      * reincarnated nodes
0112      */
0113     for (int i = 0; i < reincarnatedNodes.size(); i++) {
0114         KisCloneLayerSP clone = clonesList[i];
0115         KisLayerSP newNode = reincarnatedNodes[i];
0116 
0117         image->addNode(newNode, clone->parent(), clone);
0118         moveChildren(clone, newNode);
0119         moveClones(clone, newNode);
0120         image->removeNode(clone);
0121     }
0122 }
0123 
0124 void KisImageLayerRemoveCommandImpl::Private::moveChildren(KisNodeSP src, KisNodeSP dst)
0125 {
0126     KisImageSP image = q->m_image.toStrongRef();
0127     if (!image) {
0128         return;
0129     }
0130     KisNodeSP child = src->firstChild();
0131     while(child) {
0132         image->moveNode(child, dst, dst->lastChild());
0133         child = child->nextSibling();
0134     }
0135 }
0136 
0137 void KisImageLayerRemoveCommandImpl::Private::moveClones(KisLayerSP src, KisLayerSP dst)
0138 {
0139     Q_FOREACH (KisCloneLayerWSP _clone, src->registeredClones()) {
0140         KisCloneLayerSP clone = _clone;
0141         Q_ASSERT(clone);
0142 
0143         clone->setCopyFrom(dst);
0144     }
0145 }