File indexing completed on 2024-05-12 15:58:10

0001 /*
0002  *  SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef _KIS_BASE_NODE_H
0007 #define _KIS_BASE_NODE_H
0008 
0009 #include <QObject>
0010 #include <QIcon>
0011 #include <QUuid>
0012 #include <QString>
0013 
0014 #include <KoID.h>
0015 
0016 #include "kis_shared.h"
0017 #include "kis_paint_device.h"
0018 #include "kis_processing_visitor.h" // included, not forward declared for msvc
0019 
0020 class KoProperties;
0021 class KoColorSpace;
0022 class KoCompositeOp;
0023 class KisNodeVisitor;
0024 class KisUndoAdapter;
0025 class KisKeyframeChannel;
0026 
0027 #include "kritaimage_export.h"
0028 
0029 /**
0030  * A KisBaseNode is the base class for all components of an image:
0031  * nodes, layers masks, selections. A node has a number of properties,
0032  * can be represented as a thumbnail and knows what to do when it gets
0033  * a certain paint device to process. A KisBaseNode does not know
0034  * anything about its peers. You should not directly inherit from a
0035  * KisBaseNode; inherit from KisNode instead.
0036  */
0037 class KRITAIMAGE_EXPORT KisBaseNode : public QObject, public KisShared
0038 {
0039 
0040     Q_OBJECT
0041 
0042 public:
0043     /**
0044      *  Describes a property of a document section.
0045      *
0046      * FIXME: using a QList instead of QMap and not having an untranslated identifier,
0047      * either enum or string, forces applications to rely on the order of properties
0048      * or to compare the translated strings. This makes it hard to robustly extend the
0049      * properties of document section items.
0050      */
0051     struct Property
0052     {
0053         QString id;
0054 
0055         /** i18n-ed name, suitable for displaying */
0056         QString name;
0057 
0058         /** Whether the property is a boolean (e.g. locked, visible) which can be toggled directly from the widget itself. */
0059         bool isMutable {false};
0060 
0061         /** Provide these if the property isMutable. */
0062         QIcon onIcon;
0063         QIcon offIcon;
0064 
0065         /** If the property isMutable, provide a boolean. Otherwise, a string suitable for displaying. */
0066         QVariant state;
0067 
0068         /** If the property is mutable, specifies whether it can be put into stasis. When a property
0069         is in stasis, a new state is created, and the old one is stored in stateInStasis. When
0070         stasis ends, the old value is restored and the new one discarded */
0071         bool canHaveStasis {false};
0072 
0073         /** If the property isMutable and canHaveStasis, indicate whether it is in stasis or not */
0074         bool isInStasis {false};
0075 
0076         /** If the property isMutable and canHaveStasis, provide this value to store the property's
0077         state while in stasis */
0078         bool stateInStasis {false};
0079 
0080         bool operator==(const Property &rhs) const {
0081             return rhs.name == name && rhs.state == state && isInStasis == rhs.isInStasis;
0082         }
0083 
0084         Property(): isMutable( false ), isInStasis(false) { }
0085 
0086         /// Constructor for a mutable property.
0087         Property( const KoID &n, const QIcon &on, const QIcon &off, bool isOn )
0088                 : id(n.id()), name( n.name() ), isMutable( true ), onIcon( on ), offIcon( off ), state( isOn ),
0089                   canHaveStasis( false ), isInStasis(false) { }
0090 
0091         /** Constructor for a mutable property accepting stasis */
0092         Property( const KoID &n, const QIcon &on, const QIcon &off, bool isOn,
0093                   bool _isInStasis, bool _stateInStasis = false )
0094                 : id(n.id()), name(n.name()), isMutable( true ), onIcon( on ), offIcon( off ), state( isOn ),
0095                   canHaveStasis( true ), isInStasis( _isInStasis ), stateInStasis( _stateInStasis ) { }
0096 
0097         /// Constructor for a nonmutable property.
0098         Property( const KoID &n, const QString &s )
0099                 : id(n.id()), name(n.name()), isMutable( false ), state( s ), isInStasis(false) { }
0100     };
0101 
0102     /** Return this type for PropertiesRole. */
0103     typedef QList<Property> PropertyList;
0104 
0105 public:
0106 
0107     /**
0108      * Create a new, empty base node. The node is unnamed, unlocked
0109      * visible and unlinked.
0110      */
0111     KisBaseNode(KisImageWSP image);
0112 
0113     /**
0114      * Create a copy of this node.
0115      */
0116     KisBaseNode(const KisBaseNode & rhs);
0117 
0118     /**
0119      * Delete this node
0120      */
0121     ~KisBaseNode() override;
0122 
0123 
0124     /**
0125      * Return the paintdevice you can use to change pixels on. For a
0126      * paint layer these will be paint pixels, for an adjustment layer or a mask
0127      * the selection paint device.
0128      *
0129      * @return the paint device to paint on. Can be 0 if the actual
0130      *         node type does not support painting.
0131      */
0132     virtual KisPaintDeviceSP paintDevice() const = 0;
0133 
0134     /**
0135      * @return the rendered representation of a node
0136      * before the effect masks have had their go at it. Can be 0.
0137      */
0138     virtual KisPaintDeviceSP original() const = 0;
0139 
0140     /**
0141      * @return the fully rendered representation of this layer: its
0142      * rendered original and its effect masks. Can be 0.
0143      */
0144     virtual KisPaintDeviceSP projection() const = 0;
0145 
0146     /**
0147      * @return a special device from where the color sampler tool should sample
0148      * color when in layer-only mode. For most of the nodes just shortcuts
0149      * to projection() device. TODO: can it be null?
0150      */
0151     virtual KisPaintDeviceSP colorSampleSourceDevice() const;
0152 
0153     virtual const KoColorSpace *colorSpace() const = 0;
0154 
0155     /**
0156      * Return the opacity of this layer, scaled to a range between 0
0157      * and 255.
0158      * XXX: Allow true float opacity
0159      */
0160     quint8 opacity() const; //0-255
0161 
0162     /**
0163      * Set the opacity for this layer. The range is between 0 and 255.
0164      * The layer will be marked dirty.
0165      *
0166      * XXX: Allow true float opacity
0167      */
0168     void setOpacity(quint8 val); //0-255
0169 
0170     /**
0171      * return the 8-bit opacity of this layer scaled to the range
0172      * 0-100
0173      *
0174      * XXX: Allow true float opacity
0175      */
0176     quint8 percentOpacity() const; //0-100
0177 
0178     /**
0179      * Set the opacity of this layer with a number between 0 and 100;
0180      * the number will be scaled to between 0 and 255.
0181      * XXX: Allow true float opacity
0182      */
0183     void setPercentOpacity(quint8 val); //0-100
0184 
0185     /**
0186      * Return the composite op associated with this layer.
0187      */
0188     virtual const KoCompositeOp *compositeOp() const = 0;
0189     const QString& compositeOpId() const;
0190 
0191     /**
0192      * Set a new composite op for this layer. The layer will be marked
0193      * dirty.
0194      */
0195     void setCompositeOpId(const QString& compositeOpId);
0196 
0197     /**
0198      * @return unique id, which is now used by clone layers.
0199      */
0200     QUuid uuid() const;
0201 
0202     /**
0203      * Set the uuid of node. This should only be used when loading
0204      * existing node and in constructor.
0205      */
0206     void setUuid(const QUuid& id);
0207 
0208     /**
0209      * return the name of this node. This is the same as the
0210      * QObject::objectName.
0211      */
0212     QString name() const {
0213         return objectName();
0214     }
0215 
0216     /**
0217      * set the QObject::objectName. This is also the user-visible name
0218      * of the layer. The reason for this is that we want to see the
0219      * layer name also when debugging.
0220      */
0221     void setName(const QString& name) {
0222         setObjectName(name);
0223         baseNodeChangedCallback();
0224     }
0225 
0226     /**
0227      * @return the icon used to represent the node type, for instance
0228      * in the layerbox and in the menu.
0229      */
0230     virtual QIcon icon() const {
0231         return QIcon();
0232     }
0233 
0234     /**
0235      * Return a the properties of this base node (locked, visible etc,
0236      * with the right icons for their representation and their state.
0237      *
0238      * Subclasses can extend this list with new properties, like
0239      * opacity for layers or visualized for masks.
0240      *
0241      * The order of properties is, unfortunately, for now, important,
0242      * so take care which properties superclasses of your class
0243      * define.
0244      *
0245      * KisBaseNode defines visible = 0, locked = 1
0246      * KisLayer defines  opacity = 2, compositeOp = 3
0247      * KisMask defines active = 2 (KisMask does not inherit kislayer)
0248      */
0249     virtual PropertyList sectionModelProperties() const;
0250 
0251     /**
0252      * Change the section model properties.
0253      */
0254     virtual void setSectionModelProperties(const PropertyList &properties);
0255 
0256     /**
0257      * Return all the properties of this layer as a KoProperties-based
0258      * serializable key-value list.
0259      */
0260     const KoProperties & nodeProperties() const;
0261 
0262     /**
0263      * Set a node property.
0264      * @param name name of the property to be set.
0265      * @param value value to set the property to.
0266      */
0267     void setNodeProperty(const QString & name, const QVariant & value);
0268 
0269     /**
0270      * Merge the specified properties with the properties of this
0271      * layer. Wherever these properties overlap, the value of the
0272      * node properties is changed. No properties on the node are
0273      * deleted. If there are new properties in this list, they will be
0274      * added on the node.
0275      */
0276     void mergeNodeProperties(const KoProperties & properties);
0277 
0278     /**
0279      * Compare the given properties list with the properties of this
0280      * node.
0281      *
0282      * @return false only if the same property exists in both lists
0283      * but with a different value. Properties that are not in both
0284      * lists are disregarded.
0285      */
0286     bool check(const KoProperties & properties) const;
0287 
0288     /**
0289      * Accept the KisNodeVisitor (for the Visitor design pattern),
0290      * should call the correct function on the KisNodeVisitor for this
0291      * node type, so you need to override it for all leaf classes in
0292      * the node inheritance hierarchy.
0293      *
0294      * return false if the visitor could not successfully act on this
0295      * node instance.
0296      */
0297     virtual bool accept(KisNodeVisitor &) {
0298         return false;
0299     }
0300 
0301     /**
0302      * Accept the KisNodeVisitor (for the Visitor design pattern),
0303      * should call the correct function on the KisProcessingVisitor
0304      * for this node type, so you need to override it for all leaf
0305      * classes in the node inheritance hierarchy.
0306      *
0307      * The processing visitor differs from node visitor in the way
0308      * that it accepts undo adapter, that allows the processing to
0309      * be multithreaded
0310      */
0311     virtual void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) {
0312         Q_UNUSED(visitor);
0313         Q_UNUSED(undoAdapter);
0314     }
0315 
0316     /**
0317      * @return a thumbnail in requested size. The thumbnail is a rgba
0318      * QImage and may have transparent parts. Returns a fully
0319      * transparent QImage of the requested size if the current node
0320      * type cannot generate a thumbnail. If the requested size is too
0321      * big, return a null QImage.
0322      */
0323     virtual QImage createThumbnail(qint32 w, qint32 h, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio);
0324 
0325     /**
0326      * @return a thumbnail in requested size for the defined timestamp.
0327      * The thumbnail is a rgba Image and may have transparent parts.
0328      * Returns a fully transparent QImage of the requested size if the
0329      * current node type cannot generate a thumbnail. If the requested
0330      * size is too big, return a null QImage.
0331      */
0332     virtual QImage createThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio);
0333 
0334     /**
0335      * Ask this node to re-read the pertinent settings from the krita
0336      * configuration.
0337      */
0338     virtual void updateSettings() {
0339     }
0340 
0341     /**
0342      * @return true if this node is visible (i.e, active (except for
0343      * selection masks where visible and active properties are
0344      * different)) in the graph
0345      *
0346      * @param bool recursive if true, check whether all parents of
0347      * this node are visible as well.
0348      */
0349     virtual bool visible(bool recursive = false) const;
0350 
0351     /**
0352      * Set the visible status of this node. Visible nodes are active
0353      * in the graph (except for selections masks which can be active
0354      * while hidden), that is to say, they are taken into account
0355      * when merging. Invisible nodes play no role in the final image
0356      *, but will be modified when modifying all layers, for instance
0357      * when cropping.
0358      *
0359      * Toggling the visibility of a node will not automatically lead
0360      * to recomposition.
0361      *
0362      * @param visible the new visibility state
0363      * @param isLoading if true, the property is set during loading.
0364      */
0365     virtual void setVisible(bool visible, bool loading = false);
0366 
0367     /**
0368      * Return the locked status of this node. Locked nodes cannot be
0369      * edited.
0370      */
0371     bool userLocked() const;
0372 
0373     /**
0374      * Return whether or not the given node is isolated.
0375      */
0376     bool belongsToIsolatedGroup() const;
0377 
0378     /**
0379      * Return whether or not the given node is the root of
0380      * isolation.
0381      */
0382     bool isIsolatedRoot() const;
0383 
0384     /**
0385      * Set the locked status of this node. Locked nodes cannot be
0386      * edited.
0387      */
0388     virtual void setUserLocked(bool l);
0389 
0390     /**
0391      * @return true if the node can be edited:
0392      *
0393      * if checkVisibility is true, then the node is only editable if it is visible and not locked.
0394      * if checkVisibility is false, then the node is editable if it's not locked.
0395      */
0396     bool isEditable(bool checkVisibility = true) const;
0397 
0398     /**
0399      * @return true if the node is editable and has a paintDevice()
0400      *         which which can be used for accessing pixels. It is an
0401      *         equivalent to (isEditable() && paintDevice())
0402      */
0403     bool hasEditablePaintDevice() const;
0404 
0405     /**
0406      * @return the x-offset of this layer in the image plane.
0407      */
0408     virtual qint32 x() const {
0409         return 0;
0410     }
0411 
0412     /**
0413      * Set the x offset of this layer in the image place.
0414      * Re-implement this where it makes sense, by default it does
0415      * nothing. It should not move child nodes.
0416      */
0417     virtual void setX(qint32) {
0418     }
0419 
0420     /**
0421      * @return the y-offset of this layer in the image plane.
0422      */
0423     virtual qint32 y() const {
0424         return 0;
0425     }
0426 
0427     /**
0428      * Set the y offset of this layer in the image place.
0429      * Re-implement this where it makes sense, by default it does
0430      * nothing. It should not move child nodes.
0431      */
0432     virtual void setY(qint32) {
0433     }
0434 
0435     /**
0436     * Returns an approximation of where the bounds on actual data are
0437     * in this node.
0438     */
0439     virtual QRect extent() const {
0440         return QRect();
0441     }
0442 
0443     /**
0444      * Returns the exact bounds of where the actual data resides in
0445      * this node.
0446      */
0447     virtual QRect exactBounds() const {
0448         return QRect();
0449     }
0450 
0451     /**
0452      * Sets the state of the node to the value of @param collapsed
0453      */
0454     void setCollapsed(bool collapsed);
0455 
0456     /**
0457      * returns the collapsed state of this node
0458      */
0459     bool collapsed() const;
0460 
0461     /**
0462      * Sets a color label index associated to the layer.  The actual
0463      * color of the label and the number of available colors is
0464      * defined by Krita GUI configuration.
0465      */
0466     void setColorLabelIndex(int index);
0467 
0468     /**
0469      * \see setColorLabelIndex
0470      */
0471     int colorLabelIndex() const;
0472 
0473     /**
0474      * Returns true if the offset of the node can be changed in a LodN
0475      * stroke. Currently, all the nodes except shape layers support that.
0476      */
0477     bool supportsLodMoves() const;
0478 
0479     /**
0480      * Returns true if the node can be painted via KisPaintDevice. Notable
0481      * exceptions are selection-based layers and masks.
0482      */
0483     virtual bool supportsLodPainting() const;
0484 
0485     /**
0486      * Return the keyframe channels associated with this node
0487      * @return list of keyframe channels
0488      */
0489     QMap<QString, KisKeyframeChannel*> keyframeChannels() const;
0490 
0491     /**
0492      * Get the keyframe channel with given id.
0493      * If the channel does not yet exist and the node supports the requested
0494      * channel, it will be created if create is true.
0495      * @param id internal name for channel
0496      * @param create attempt to create the channel if it does not exist yet
0497      * @return keyframe channel with the id, or null if not found
0498      */
0499     KisKeyframeChannel *getKeyframeChannel(const QString &id, bool create);
0500     KisKeyframeChannel *getKeyframeChannel(const QString &id) const;
0501 
0502     /**
0503      * @return If true, node will be visible on animation timeline even when inactive.
0504      */
0505     bool isPinnedToTimeline() const;
0506 
0507     /**
0508      * Set whether node should be visible on animation timeline even when inactive.
0509      */
0510     void setPinnedToTimeline(bool pinned);
0511 
0512     bool isAnimated() const;
0513     void enableAnimation();
0514 
0515     virtual void setImage(KisImageWSP image);
0516     KisImageWSP image() const;
0517 
0518 
0519     /**
0520      * Fake node is not present in the layer stack and is not used
0521      * for normal projection rendering algorithms.
0522      */
0523     virtual bool isFakeNode() const;
0524 
0525 protected:
0526 
0527     void setSupportsLodMoves(bool value);
0528 
0529     /**
0530      * FIXME: This method is a workaround for getting parent node
0531      * on a level of KisBaseNode. In fact, KisBaseNode should inherit
0532      * KisNode (in terms of current Krita) to be able to traverse
0533      * the node stack
0534      */
0535     virtual KisBaseNodeSP parentCallback() const {
0536         return KisBaseNodeSP();
0537     }
0538 
0539     virtual void notifyParentVisibilityChanged(bool value) {
0540         Q_UNUSED(value);
0541     }
0542 
0543     /**
0544      * This callback is called when some meta state of the base node
0545      * that can be interesting to the UI has changed. E.g. visibility,
0546      * lockness, opacity, compositeOp and etc. This signal is
0547      * forwarded by the KisNode and KisNodeGraphListener to the model
0548      * in KisLayerBox, so it can update its controls when information
0549      * changes.
0550      */
0551     virtual void baseNodeChangedCallback() {
0552     }
0553 
0554     /**
0555      * This callback is called when collapsed state of the base node
0556      * has changed. This signal is forwarded by the KisNode and
0557      * KisNodeGraphListener to the model in KisLayerBox, so it can
0558      * update its controls when information changes.
0559      */
0560     virtual void baseNodeCollapsedChangedCallback() {
0561     }
0562 
0563 
0564     virtual void baseNodeInvalidateAllFramesCallback() {
0565     }
0566 
0567     /**
0568      * Add a keyframe channel for this node. The channel will be added
0569      * to the common hash table which will be available to the UI.
0570      *
0571      * WARNING: the \p channel object *NOT* become owned by the node!
0572      *          The caller must ensure manually that the lifetime of
0573      *          the object coincide with the lifetime of the node.
0574      */
0575     virtual void addKeyframeChannel(KisKeyframeChannel* channel);
0576 
0577     /**
0578      * Attempt to create the requested channel. Used internally by getKeyframeChannel.
0579      * Subclasses should implement this method to catch any new channel types they support.
0580      * @param id channel to create
0581      * @return newly created channel or null
0582      */
0583     virtual KisKeyframeChannel * requestKeyframeChannel(const QString &id);
0584 
0585 public:
0586     /**
0587      * Ideally, this function would be used to query for keyframe support
0588      * before trying to create channels. The ability to query would help
0589      * in cases such as animation curves where you might want to ask
0590      * which channels it supports before allowing the user to add.
0591      *
0592      * @param id querried channel
0593      * @return bool whether it supports said channel or not.
0594      */
0595     virtual bool supportsKeyframeChannel(const QString &id);
0596 
0597 Q_SIGNALS:
0598     void keyframeChannelAdded(KisKeyframeChannel *channel);
0599     void opacityChanged(quint8 value);
0600 
0601 private:
0602 
0603     struct Private;
0604     Private * const m_d;
0605 
0606 };
0607 
0608 KRITAIMAGE_EXPORT QDebug operator<<(QDebug dbg, const KisBaseNode::Property &prop);
0609 
0610 Q_DECLARE_METATYPE( KisBaseNode::PropertyList )
0611 
0612 
0613 #endif