File indexing completed on 2024-05-12 05:36:51

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