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

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Agata Cacko <cacko.azh@gmail.com>
0003  *  SPDX-FileCopyrightText: 2022 Deif Lou <ginoba@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #ifndef __KIS_MERGE_LABELED_LAYERS_H
0009 #define __KIS_MERGE_LABELED_LAYERS_H
0010 
0011 #include <QList>
0012 #include <QString>
0013 #include <QSharedPointer>
0014 
0015 #include "kundo2command.h"
0016 #include "kritaimage_export.h"
0017 #include "kis_types.h"
0018 #include "kis_image.h"
0019 
0020 class KisUpdatesFacade;
0021 
0022 class KRITAIMAGE_EXPORT KisMergeLabeledLayersCommand : public KUndo2Command
0023 {
0024 public:
0025     /**
0026      * @brief Policies to stablish how the groups should be treated
0027      */
0028     enum GroupSelectionPolicy
0029     {
0030         /**
0031          * @brief Groups will be taken into account if their color label matches
0032          *        one of the selected color labels, even when the group has
0033          *        "no-color-label" as label
0034          */
0035         GroupSelectionPolicy_SelectAlways,
0036         /**
0037          * @brief Groups will be taken into account only if they have set
0038          *        an explicit color label. This ignores groups that have
0039          *        "no-color-label" as color label and the "no-color-label" label
0040          *        is included in the selected labels list
0041          */
0042         GroupSelectionPolicy_SelectIfColorLabeled,
0043         /**
0044          * @brief Groups will not be taken into account
0045          */
0046         GroupSelectionPolicy_NeverSelect
0047     };
0048 
0049     /**
0050      * @brief Basic info about a node. This is used to compare and see if the
0051      *        node changed
0052      */
0053     struct ReferenceNodeInfo
0054     {
0055         QUuid nodeId;
0056         int sequenceNumber;
0057         int opacity;
0058 
0059         bool operator==(const ReferenceNodeInfo &other) const
0060         {
0061             return nodeId == other.nodeId && sequenceNumber == other.sequenceNumber && opacity == other.opacity;
0062         }
0063     };
0064 
0065     using ReferenceNodeInfoList = QList<ReferenceNodeInfo>;
0066     using ReferenceNodeInfoListSP = QSharedPointer<ReferenceNodeInfoList>;
0067 
0068     /**
0069      * @brief Construct a new KisMergeLabeledLayersCommand that does not use
0070      *        a cache
0071      * @param image The image with the reference layers
0072      * @param newRefPaintDevice The resulting device that will contain the
0073      *                          merged result
0074      * @param selectedLabels The color labels of the reference layers
0075      * @param groupSelectionPolicy How to treat groups
0076      */
0077     KisMergeLabeledLayersCommand(KisImageSP image,
0078                                  KisPaintDeviceSP newRefPaintDevice,
0079                                  QList<int> selectedLabels,
0080                                  GroupSelectionPolicy groupSelectionPolicy = GroupSelectionPolicy_SelectAlways);
0081 
0082     /**
0083      * @brief Construct a new KisMergeLabeledLayersCommand that uses a cache
0084      * @param image The image with the reference layers
0085      * @param prevRefNodeInfoList The reference node info that is used to
0086      *                            compare with the current one to see if the
0087      *                            cache device can be used instead of generating
0088      *                            a new one
0089      * @param newRefNodeInfoList The resulting list of reference node info
0090      * @param prevRefPaintDevice The device that is used as a cache if possible
0091      * @param newRefPaintDevice The resulting device that will contain the
0092      *                          merged result
0093      * @param selectedLabels The color labels of the reference layers
0094      * @param groupSelectionPolicy How to treat groups
0095      * @param forceRegeneration If true, the cache is ignored and the merged
0096      *                          result is regenerated
0097      */
0098     KisMergeLabeledLayersCommand(KisImageSP image,
0099                                  ReferenceNodeInfoListSP prevRefNodeInfoList,
0100                                  ReferenceNodeInfoListSP newRefNodeInfoList,
0101                                  KisPaintDeviceSP prevRefPaintDevice,
0102                                  KisPaintDeviceSP newRefPaintDevice,
0103                                  QList<int> selectedLabels,
0104                                  GroupSelectionPolicy groupSelectionPolicy = GroupSelectionPolicy_SelectAlways,
0105                                  bool forceRegeneration = false);
0106                                  
0107     ~KisMergeLabeledLayersCommand() override;
0108 
0109     void undo() override;
0110     void redo() override;
0111 
0112     static KisPaintDeviceSP createRefPaintDevice(KisImageSP originalImage, QString name = "Merge Labeled Layers Reference Paint Device");
0113 
0114 private:
0115     void mergeLabeledLayers();
0116     bool hastToCheckForChangesInNodes() const;
0117     QPair<KisNodeSP, QPair<bool, bool>> collectNode(KisNodeSP node) const;
0118     bool collectNodes(KisNodeSP node, QList<KisNodeSP> &nodeList, ReferenceNodeInfoList &nodeInfoList) const;
0119 
0120 private:
0121     KisImageSP m_refImage;
0122     ReferenceNodeInfoListSP m_prevRefNodeInfoList;
0123     ReferenceNodeInfoListSP m_newRefNodeInfoList;
0124     KisPaintDeviceSP m_prevRefPaintDevice;
0125     KisPaintDeviceSP m_newRefPaintDevice;
0126     KisNodeSP m_currentRoot;
0127     QList<int> m_selectedLabels;
0128     GroupSelectionPolicy m_groupSelectionPolicy;
0129     bool m_forceRegeneration;
0130 };
0131 
0132 #endif /* __KIS_MERGE_LABELED_LAYERS_H */