File indexing completed on 2024-05-05 03:56:42

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     /**
0113      * Set whether to show ancestor data in the model. If @p display is true, then
0114      * a source model which is displayed as
0115      *
0116      * @code
0117      *  -> "Item 0-0" (this is row-depth)
0118      *  -> -> "Item 0-1"
0119      *  -> -> "Item 1-1"
0120      *  -> -> -> "Item 0-2"
0121      *  -> -> -> "Item 1-2"
0122      *  -> "Item 1-0"
0123      * @endcode
0124      *
0125      * will be displayed as
0126      *
0127      * @code
0128      *  -> *Item 0-0"
0129      *  -> "Item 0-0 / Item 0-1"
0130      *  -> "Item 0-0 / Item 1-1"
0131      *  -> "Item 0-0 / Item 1-1 / Item 0-2"
0132      *  -> "Item 0-0 / Item 1-1 / Item 1-2"
0133      *  -> "Item 1-0"
0134      * @endcode
0135      *
0136      * If @p display is false, the proxy will show
0137      *
0138      * @code
0139      *  -> *Item 0-0"
0140      *  -> "Item 0-1"
0141      *  -> "Item 1-1"
0142      *  -> "Item 0-2"
0143      *  -> "Item 1-2"
0144      *  -> "Item 1-0"
0145      * @endcode
0146      *
0147      * Default is false.
0148      */
0149     void setDisplayAncestorData(bool display);
0150 
0151     /**
0152      * Whether ancestor data will be displayed.
0153      */
0154     bool displayAncestorData() const;
0155 
0156     /**
0157      * Sets the ancestor @p separator used between data of ancestors.
0158      */
0159     void setAncestorSeparator(const QString &separator);
0160 
0161     /**
0162      * Separator used between data of ancestors.
0163      */
0164     QString ancestorSeparator() const;
0165 
0166     QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
0167     QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
0168 
0169     Qt::ItemFlags flags(const QModelIndex &index) const override;
0170     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0171     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0172     QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
0173 
0174     QMimeData *mimeData(const QModelIndexList &indexes) const override;
0175     QStringList mimeTypes() const override;
0176 
0177     bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
0178     QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const override;
0179     QModelIndex parent(const QModelIndex &) const override;
0180     int columnCount(const QModelIndex &index = QModelIndex()) const override;
0181     QHash<int, QByteArray> roleNames() const override;
0182 
0183     /**
0184      * If true, all the nodes in the whole tree will be expanded upon loading (default)
0185      * @param expand whether we want everything expanded upon load
0186      * @since 5.74
0187      */
0188     void setExpandsByDefault(bool expand);
0189 
0190     /**
0191      * @returns true if all the tree nodes are expanded by default upon loading
0192      * @since 5.74
0193      */
0194     bool expandsByDefault() const;
0195 
0196     /**
0197      * @returns true if the source index is mapped in the proxy as expanded, therefore it will show its children
0198      * @since 5.74
0199      */
0200     bool isSourceIndexExpanded(const QModelIndex &sourceIndex) const;
0201 
0202     /**
0203      * @returns true if the source index is visible in the proxy, meaning all its parent hierarchy is expanded.
0204      * @since 5.74
0205      */
0206     bool isSourceIndexVisible(const QModelIndex &sourceIndex) const;
0207 
0208     /**
0209      * Maps a source index as expanded in the proxy, all its children will become visible.
0210      * @param sourceIndex an idex of the source model.
0211      * @since 5.74
0212      */
0213     void expandSourceIndex(const QModelIndex &sourceIndex);
0214 
0215     /**
0216      * Maps a source index as collapsed in the proxy, all its children will be hidden.
0217      * @param sourceIndex an idex of the source model.
0218      * @since 5.74
0219      */
0220     void collapseSourceIndex(const QModelIndex &sourceIndex);
0221 
0222     Qt::DropActions supportedDropActions() const override;
0223 
0224     /**
0225     Reimplemented to match all descendants.
0226     */
0227     virtual QModelIndexList match(const QModelIndex &start,
0228                                   int role,
0229                                   const QVariant &value,
0230                                   int hits = 1,
0231                                   Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const override;
0232 
0233 Q_SIGNALS:
0234     void sourceModelChanged();
0235     void displayAncestorDataChanged();
0236     void ancestorSeparatorChanged();
0237     void expandsByDefaultChanged(bool expands);
0238     void sourceIndexExpanded(const QModelIndex &sourceIndex);
0239     void sourceIndexCollapsed(const QModelIndex &sourceIndex);
0240 
0241 private:
0242     Q_DECLARE_PRIVATE(KDescendantsProxyModel)
0243     //@cond PRIVATE
0244     std::unique_ptr<KDescendantsProxyModelPrivate> const d_ptr;
0245 
0246     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeInserted(const QModelIndex &, int, int))
0247     Q_PRIVATE_SLOT(d_func(), void sourceRowsInserted(const QModelIndex &, int, int))
0248     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeRemoved(const QModelIndex &, int, int))
0249     Q_PRIVATE_SLOT(d_func(), void sourceRowsRemoved(const QModelIndex &, int, int))
0250     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))
0251     Q_PRIVATE_SLOT(d_func(), void sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))
0252     Q_PRIVATE_SLOT(d_func(), void sourceModelAboutToBeReset())
0253     Q_PRIVATE_SLOT(d_func(), void sourceModelReset())
0254     Q_PRIVATE_SLOT(d_func(), void sourceLayoutAboutToBeChanged())
0255     Q_PRIVATE_SLOT(d_func(), void sourceLayoutChanged())
0256     Q_PRIVATE_SLOT(d_func(), void sourceDataChanged(const QModelIndex &, const QModelIndex &))
0257     Q_PRIVATE_SLOT(d_func(), void sourceModelDestroyed())
0258 
0259     Q_PRIVATE_SLOT(d_func(), void processPendingParents())
0260 
0261     // Make these private, they shouldn't be called by applications
0262     //   virtual bool insertRows(int , int, const QModelIndex & = QModelIndex());
0263     //   virtual bool insertColumns(int, int, const QModelIndex & = QModelIndex());
0264     //   virtual bool removeRows(int, int, const QModelIndex & = QModelIndex());
0265     //   virtual bool removeColumns(int, int, const QModelIndex & = QModelIndex());
0266 
0267     //@endcond
0268 };
0269 
0270 #endif