File indexing completed on 2024-05-12 16:01:36

0001 /*
0002  *  SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef KIS_NODE_MODEL
0007 #define KIS_NODE_MODEL
0008 
0009 #include "kritaui_export.h"
0010 #include <kis_types.h>
0011 #include <QAbstractItemModel>
0012 #include <QIcon>
0013 #include <QList>
0014 #include <QString>
0015 #include <QVariant>
0016 
0017 #include <KisSelectionTags.h>
0018 
0019 class KisDummiesFacadeBase;
0020 class KisNodeDummy;
0021 class KisShapeController;
0022 class KisModelIndexConverterBase;
0023 class KisNodeSelectionAdapter;
0024 class KisNodeInsertionAdapter;
0025 class KisSelectionActionsAdapter;
0026 class KisNodeDisplayModeAdapter;
0027 class KisNodeManager;
0028 
0029 /**
0030  * KisNodeModel offers a Qt model-view compatible view of the node
0031  * hierarchy. The KisNodeView displays a thumbnail and a row of
0032  * icon properties for every document section.
0033  *
0034  * Note that there's a discrepancy between the krita node tree model
0035  * and the model Qt wants to see: we hide the root node from Qt.
0036  *
0037  * The node model also shows an inverse view of the layer tree: we want
0038  * the first layer to show up at the bottom.
0039  * 
0040  * See also the Qt documentation for QAbstractItemModel. 
0041  * This class extends that interface to provide a name and set of toggle
0042  * properties (like visible, locked, selected.)
0043  * 
0044  */
0045 class KRITAUI_EXPORT KisNodeModel : public QAbstractItemModel
0046 {
0047 
0048     Q_OBJECT
0049 
0050 public:
0051     /// Extensions to Qt::ItemDataRole.
0052     enum ItemDataRole
0053     {
0054         /// Whether the section is the active one
0055         ActiveRole = Qt::UserRole + 1,
0056 
0057         /// A list of properties the part has.
0058         PropertiesRole,
0059 
0060         /// The aspect ratio of the section as a floating point value: width divided by height.
0061         AspectRatioRole,
0062 
0063         /// Use to communicate a progress report to the section delegate on an action (a value of -1 or a QVariant() disable the progress bar
0064         ProgressRole,
0065 
0066         /// Special activation role which is emitted when the user Atl-clicks on a section
0067         /// The item is first activated with ActiveRole, then a separate AlternateActiveRole comes
0068         AlternateActiveRole,
0069 
0070         // When a layer is not (recursively) visible, then it should be gayed out
0071         ShouldGrayOutRole,
0072 
0073         // An index of a color label associated with the node
0074         ColorLabelIndexRole,
0075 
0076         // Instruct this model to update all its items' Qt::ItemIsDropEnabled flags in order to
0077         // reflect if the item allows an "onto" drop of the given QMimeData*.
0078         DropEnabled,
0079 
0080         // Instructs the model to activate "select opaque" action,
0081         // the selection action (of type SelectionAction) value
0082         // is passed via QVariant as integer
0083         SelectOpaqueRole,
0084 
0085         // Returns a text explaining why the node has been excluded from
0086         // projection rendering. If the node is not excluded, then empty
0087         // string is returned
0088         DropReasonRole,
0089 
0090         // Let's the model quickly determine whether a layer has any
0091         // animated content attached to it.
0092         IsAnimatedRole,
0093 
0094         /// This is to ensure that we can extend the data role in the future, since it's not possible to add a role after BeginThumbnailRole (due to "Hack")
0095         ReservedRole = Qt::UserRole + 99,
0096 
0097         /**
0098          * For values of BeginThumbnailRole or higher, a thumbnail of the layer of which neither dimension
0099          * is larger than (int) value - (int) BeginThumbnailRole.
0100          * This is a hack to work around the fact that Interview doesn't have a nice way to
0101          * request thumbnails of arbitrary size.
0102          */
0103         BeginThumbnailRole
0104     };
0105 
0106 public: // from QAbstractItemModel
0107 
0108     explicit KisNodeModel(QObject * parent, int clonedColumns = 0);
0109     ~KisNodeModel() override;
0110 
0111     void setDummiesFacade(KisDummiesFacadeBase *dummiesFacade,
0112                           KisImageWSP image,
0113                           KisShapeController *shapeController,
0114                           KisSelectionActionsAdapter *selectionActionsAdapter,
0115                           KisNodeManager *nodeManager);
0116     KisNodeSP nodeFromIndex(const QModelIndex &index) const;
0117     QModelIndex indexFromNode(KisNodeSP node) const;
0118 
0119     bool showGlobalSelection() const;
0120 
0121 public Q_SLOTS:
0122     void setShowGlobalSelection(bool value);
0123 
0124 public:
0125 
0126     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0127     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
0128     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
0129     QModelIndex parent(const QModelIndex &index) const override;
0130     QModelIndex sibling(int row, int column, const QModelIndex &idx) const override;
0131     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0132     Qt::ItemFlags flags(const QModelIndex &index) const override;
0133     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
0134     QStringList mimeTypes() const override;
0135     QMimeData* mimeData(const QModelIndexList & indexes) const override;
0136     bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
0137     bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
0138     Qt::DropActions supportedDragActions() const override;
0139     Qt::DropActions supportedDropActions() const override;
0140     bool hasDummiesFacade();
0141 
0142     static bool belongsToIsolatedGroup(KisImageSP image, KisNodeSP node, KisDummiesFacadeBase *dummiesFacade);
0143 
0144 Q_SIGNALS:
0145 
0146     void toggleIsolateActiveNode();
0147     void sigBeforeBeginRemoveRows(const QModelIndex &parent, int start, int end);
0148 
0149 protected Q_SLOTS:
0150     void slotBeginInsertDummy(KisNodeDummy *parent, int index, const QString &metaObjectType);
0151     void slotEndInsertDummy(KisNodeDummy *dummy);
0152     void slotBeginRemoveDummy(KisNodeDummy *dummy);
0153     void slotEndRemoveDummy();
0154     void slotDummyChanged(KisNodeDummy *dummy);
0155 
0156     void slotIsolatedModeChanged();
0157 
0158     void slotNodeDisplayModeChanged(bool showRootNode, bool showGlobalSelectionMask);
0159 
0160     void processUpdateQueue();
0161     void progressPercentageChanged(int, const KisNodeSP);
0162 
0163 protected:
0164     virtual KisModelIndexConverterBase *createIndexConverter();
0165     KisModelIndexConverterBase *indexConverter() const;
0166     KisDummiesFacadeBase *dummiesFacade() const;
0167 
0168 private:
0169     friend class KisModelIndexConverter;
0170     friend class KisModelIndexConverterShowAll;
0171 
0172     void connectDummy(KisNodeDummy *dummy, bool needConnect);
0173     void connectDummies(KisNodeDummy *dummy, bool needConnect);
0174 
0175     void resetIndexConverter();
0176 
0177     void regenerateItems(KisNodeDummy *dummy);
0178     bool belongsToIsolatedGroup(KisNodeSP node) const;
0179 
0180     void setDropEnabled(const QMimeData *data);
0181     void updateDropEnabled(const QList<KisNodeSP> &nodes, QModelIndex parent = QModelIndex());
0182     
0183 private:
0184 
0185     struct Private;
0186     Private * const m_d;
0187 };
0188 
0189 #endif