File indexing completed on 2024-05-19 04:29:02

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