File indexing completed on 2024-05-12 17:08:30

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 #pragma once
0008 
0009 #include <QIdentityProxyModel>
0010 #include <QQmlComponent>
0011 
0012 /**
0013  * Attached property object for ComponentCacheProxyModel
0014  */
0015 class ComponentCacheAttached : public QObject
0016 {
0017     Q_OBJECT
0018     Q_PROPERTY(QAbstractItemModel *model MEMBER m_model CONSTANT)
0019     Q_PROPERTY(int row MEMBER m_row CONSTANT)
0020     Q_PROPERTY(int column MEMBER m_column CONSTANT)
0021 
0022 public:
0023     explicit ComponentCacheAttached(QObject *parent = nullptr);
0024 
0025     QAbstractItemModel *m_model = nullptr;
0026     int m_row = -1;
0027     int m_column = -1;
0028 };
0029 
0030 /**
0031  * A proxy model that adds a cached component as an extra role.
0032  *
0033  * This proxy model will return an instance of \property component when data is
0034  * requested for the CachedComponentRole. If the instance does not yet exist,
0035  * it will be created.
0036  *
0037  * The referenced component can make use of the ComponentCacheAttached
0038  * attached property.
0039  *
0040  * This is mostly a helper for dealing with TableView and QSortFilterProxyModel,
0041  * which will cause some annoying reordering of cell delegates when sorting is
0042  * applied.
0043  */
0044 class ComponentCacheProxyModel : public QIdentityProxyModel
0045 {
0046     Q_OBJECT
0047     Q_PROPERTY(QQmlComponent *component READ component WRITE setComponent NOTIFY componentChanged)
0048 
0049 public:
0050     enum Roles {
0051         CachedComponentRole = Qt::UserRole + 88,
0052     };
0053     Q_ENUM(Roles)
0054 
0055     explicit ComponentCacheProxyModel(QObject *parent = nullptr);
0056     ~ComponentCacheProxyModel() override;
0057 
0058     QHash<int, QByteArray> roleNames() const override;
0059     QVariant data(const QModelIndex &proxyIndex, int role) const override;
0060     void setSourceModel(QAbstractItemModel *sourceModel) override;
0061 
0062     QQmlComponent *component() const;
0063     void setComponent(QQmlComponent *newComponent);
0064     Q_SIGNAL void componentChanged();
0065 
0066     Q_INVOKABLE void clear();
0067 
0068     static ComponentCacheAttached *qmlAttachedProperties(QObject *object)
0069     {
0070         return new ComponentCacheAttached(object);
0071     }
0072 
0073 private:
0074     void onRowsRemoved(const QModelIndex &parent, int start, int end);
0075     void onColumnsRemoved(const QModelIndex &parent, int start, int end);
0076     void createPendingInstance();
0077 
0078     QQmlComponent *m_component = nullptr;
0079     QHash<QPersistentModelIndex, QObject *> m_instances;
0080 
0081     mutable QVector<QPersistentModelIndex> m_pendingInstances;
0082 };
0083 
0084 QML_DECLARE_TYPEINFO(ComponentCacheProxyModel, QML_HAS_ATTACHED_PROPERTIES)