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

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KDESCENDANTSPROXYMODEL_P_H
0008 #define KDESCENDANTSPROXYMODEL_P_H
0009 
0010 #include <QAbstractProxyModel>
0011 
0012 #include "kitemmodels_export.h"
0013 
0014 #include <memory>
0015 
0016 class KDescendantsProxyModelPrivate;
0017 
0018 /**
0019 @class KDescendantsProxyModel kdescendantsproxymodel.h KDescendantsProxyModel
0020 
0021 @brief Proxy Model for restructuring a Tree into a list.
0022 
0023 A KDescendantsProxyModel may be used to alter how the items in the tree are presented.
0024 
0025 Given a model which is represented as a tree:
0026 
0027 \image html entitytreemodel.png "A plain EntityTreeModel in a view"
0028 
0029 The KDescendantsProxyModel restructures the sourceModel to represent it as a flat list.
0030 
0031 @code
0032 // ... Create an entityTreeModel
0033 KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
0034 descProxy->setSourceModel(entityTree);
0035 view->setModel(descProxy);
0036 @endcode
0037 
0038 \image html descendantentitiesproxymodel.png "A KDescendantsProxyModel."
0039 
0040 KDescendantEntitiesProxyModel can also display the ancestors of the index in the source model as part of its display.
0041 
0042 @code
0043 // ... Create an entityTreeModel
0044 KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
0045 descProxy->setSourceModel(entityTree);
0046 
0047 // #### This is new
0048 descProxy->setDisplayAncestorData(true);
0049 descProxy->setAncestorSeparator(QString(" / "));
0050 
0051 view->setModel(descProxy);
0052 
0053 @endcode
0054 
0055 \image html descendantentitiesproxymodel-withansecnames.png "A KDescendantsProxyModel with ancestor names."
0056 
0057 @since 4.6
0058 @author Stephen Kelly <steveire@gmail.com>
0059 */
0060 class KITEMMODELS_EXPORT KDescendantsProxyModel : public QAbstractProxyModel
0061 {
0062     Q_OBJECT
0063 
0064     /**
0065      * @since 5.62
0066      */
0067     Q_PROPERTY(QAbstractItemModel *model READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged)
0068     /**
0069      * @since 5.62
0070      */
0071     Q_PROPERTY(bool displayAncestorData READ displayAncestorData WRITE setDisplayAncestorData NOTIFY displayAncestorDataChanged)
0072     /**
0073      * @since 5.62
0074      */
0075     Q_PROPERTY(QString ancestorSeparator READ ancestorSeparator WRITE setAncestorSeparator NOTIFY ancestorSeparatorChanged)
0076 
0077     /**
0078      * If true, all the nodes in the whole tree will be expanded upon loading and all items
0079      * of the source model will be shown in the proxy.
0080      * The default value is true.
0081      * @since 5.74
0082      */
0083     Q_PROPERTY(bool expandsByDefault READ expandsByDefault WRITE setExpandsByDefault NOTIFY expandsByDefaultChanged)
0084 
0085 public:
0086     enum AdditionalRoles {
0087         // Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
0088         // to define additional roles.
0089         LevelRole = 0x14823F9A,
0090         ExpandableRole = 0x1CA894AD,
0091         ExpandedRole = 0x1E413DA4,
0092         HasSiblingsRole = 0x1633CE0C,
0093     };
0094 
0095     /**
0096      * Creates a new descendant entities proxy model.
0097      *
0098      * @param parent The parent object.
0099      */
0100     explicit KDescendantsProxyModel(QObject *parent = nullptr);
0101 
0102     /**
0103      * Destroys the descendant entities proxy model.
0104      */
0105     ~KDescendantsProxyModel() override;
0106 
0107     /**
0108      * Sets the source @p model of the proxy.
0109      */
0110     void setSourceModel(QAbstractItemModel *model) override;
0111 
0112 #if KITEMMODELS_ENABLE_DEPRECATED_SINCE(4, 8)
0113     /**
0114      * @deprecated Since 4.8
0115      *
0116      * This method does nothing.
0117      */
0118     KITEMMODELS_DEPRECATED_VERSION(4, 8, "Method is a no-op.")
0119     void setRootIndex(const QModelIndex &index);
0120 #endif
0121 
0122     /**
0123      * Set whether to show ancestor data in the model. If @p display is true, then
0124      * a source model which is displayed as
0125      *
0126      * @code
0127      *  -> "Item 0-0" (this is row-depth)
0128      *  -> -> "Item 0-1"
0129      *  -> -> "Item 1-1"
0130      *  -> -> -> "Item 0-2"
0131      *  -> -> -> "Item 1-2"
0132      *  -> "Item 1-0"
0133      * @endcode
0134      *
0135      * will be displayed as
0136      *
0137      * @code
0138      *  -> *Item 0-0"
0139      *  -> "Item 0-0 / Item 0-1"
0140      *  -> "Item 0-0 / Item 1-1"
0141      *  -> "Item 0-0 / Item 1-1 / Item 0-2"
0142      *  -> "Item 0-0 / Item 1-1 / Item 1-2"
0143      *  -> "Item 1-0"
0144      * @endcode
0145      *
0146      * If @p display is false, the proxy will show
0147      *
0148      * @code
0149      *  -> *Item 0-0"
0150      *  -> "Item 0-1"
0151      *  -> "Item 1-1"
0152      *  -> "Item 0-2"
0153      *  -> "Item 1-2"
0154      *  -> "Item 1-0"
0155      * @endcode
0156      *
0157      * Default is false.
0158      */
0159     void setDisplayAncestorData(bool display);
0160 
0161     /**
0162      * Whether ancestor data will be displayed.
0163      */
0164     bool displayAncestorData() const;
0165 
0166     /**
0167      * Sets the ancestor @p separator used between data of ancestors.
0168      */
0169     void setAncestorSeparator(const QString &separator);
0170 
0171     /**
0172      * Separator used between data of ancestors.
0173      */
0174     QString ancestorSeparator() const;
0175 
0176     QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
0177     QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
0178 
0179     Qt::ItemFlags flags(const QModelIndex &index) const override;
0180     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0181     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0182     QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
0183 
0184     QMimeData *mimeData(const QModelIndexList &indexes) const override;
0185     QStringList mimeTypes() const override;
0186 
0187     bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
0188     QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const override;
0189     QModelIndex parent(const QModelIndex &) const override;
0190     int columnCount(const QModelIndex &index = QModelIndex()) const override;
0191     QHash<int, QByteArray> roleNames() const override;
0192 
0193     /**
0194      * If true, all the nodes in the whole tree will be expanded upon loading (default)
0195      * @param expand whether we want everything expanded upon load
0196      * @since 5.74
0197      */
0198     void setExpandsByDefault(bool expand);
0199 
0200     /**
0201      * @returns true if all the tree nodes are expanded by default upon loading
0202      * @since 5.74
0203      */
0204     bool expandsByDefault() const;
0205 
0206     /**
0207      * @returns true if the source index is mapped in the proxy as expanded, therefore it will show its children
0208      * @since 5.74
0209      */
0210     bool isSourceIndexExpanded(const QModelIndex &sourceIndex) const;
0211 
0212     /**
0213      * @returns true if the source index is visible in the proxy, meaning all its parent hierarchy is expanded.
0214      * @since 5.74
0215      */
0216     bool isSourceIndexVisible(const QModelIndex &sourceIndex) const;
0217 
0218     /**
0219      * Maps a source index as expanded in the proxy, all its children will become visible.
0220      * @param sourceIndex an idex of the source model.
0221      * @since 5.74
0222      */
0223     void expandSourceIndex(const QModelIndex &sourceIndex);
0224 
0225     /**
0226      * Maps a source index as collapsed in the proxy, all its children will be hidden.
0227      * @param sourceIndex an idex of the source model.
0228      * @since 5.74
0229      */
0230     void collapseSourceIndex(const QModelIndex &sourceIndex);
0231 
0232     Qt::DropActions supportedDropActions() const override;
0233 
0234     /**
0235     Reimplemented to match all descendants.
0236     */
0237     virtual QModelIndexList match(const QModelIndex &start,
0238                                   int role,
0239                                   const QVariant &value,
0240                                   int hits = 1,
0241                                   Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const override;
0242 
0243 Q_SIGNALS:
0244     void sourceModelChanged();
0245     void displayAncestorDataChanged();
0246     void ancestorSeparatorChanged();
0247     void expandsByDefaultChanged(bool expands);
0248     void sourceIndexExpanded(const QModelIndex &sourceIndex);
0249     void sourceIndexCollapsed(const QModelIndex &sourceIndex);
0250 
0251 private:
0252     Q_DECLARE_PRIVATE(KDescendantsProxyModel)
0253     //@cond PRIVATE
0254     std::unique_ptr<KDescendantsProxyModelPrivate> const d_ptr;
0255 
0256     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeInserted(const QModelIndex &, int, int))
0257     Q_PRIVATE_SLOT(d_func(), void sourceRowsInserted(const QModelIndex &, int, int))
0258     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))
0259     Q_PRIVATE_SLOT(d_func(), void sourceRowsRemoved(const QModelIndex &, int, int))
0260     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))
0261     Q_PRIVATE_SLOT(d_func(), void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))
0262     Q_PRIVATE_SLOT(d_func(), void sourceModelAboutToBeReset())
0263     Q_PRIVATE_SLOT(d_func(), void sourceModelReset())
0264     Q_PRIVATE_SLOT(d_func(), void sourceLayoutAboutToBeChanged())
0265     Q_PRIVATE_SLOT(d_func(), void sourceLayoutChanged())
0266     Q_PRIVATE_SLOT(d_func(), void sourceDataChanged(const QModelIndex &, const QModelIndex &))
0267     Q_PRIVATE_SLOT(d_func(), void sourceModelDestroyed())
0268 
0269     Q_PRIVATE_SLOT(d_func(), void processPendingParents())
0270 
0271     // Make these private, they shouldn't be called by applications
0272     //   virtual bool insertRows(int , int, const QModelIndex & = QModelIndex());
0273     //   virtual bool insertColumns(int, int, const QModelIndex & = QModelIndex());
0274     //   virtual bool removeRows(int, int, const QModelIndex & = QModelIndex());
0275     //   virtual bool removeColumns(int, int, const QModelIndex & = QModelIndex());
0276 
0277     //@endcond
0278 };
0279 
0280 #endif