File indexing completed on 2024-04-28 15:27:41

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Marco Martin <mart@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #ifndef DELEGATERECYCLER_H
0008 #define DELEGATERECYCLER_H
0009 
0010 #include <QPointer>
0011 #include <QQuickItem>
0012 #include <QVariant>
0013 
0014 class DelegateRecyclerAttached : public QObject
0015 {
0016     Q_OBJECT
0017 
0018 public:
0019     DelegateRecyclerAttached(QObject *parent = nullptr);
0020     ~DelegateRecyclerAttached() override;
0021 
0022 Q_SIGNALS:
0023     void pooled();
0024     void reused();
0025 };
0026 
0027 /**
0028  * This class may be used as a delegate of a QtQuick.ListView or a QtQuick.GridView
0029  * in the case the intended delegate is a bit heavy, with many objects inside.
0030  * This will ensure the delegate instances will be put back in a common pool after
0031  * destruction, so when scrolling a big list, the delegates from old delete items will
0032  * be taken from the pool and reused, minimizing the need of instantiating new objects
0033  * and deleting old ones. It ensures scrolling of lists with heavy delegates is
0034  * smoother and helps with memory fragmentations as well.
0035  *
0036  * @note org::kde::kirigami::CardsListView and org::kde::kirigami::CardsGridView
0037  * are already using this recycler, so do NOT use it as a delegate for those 2 views.
0038  * Also, do NOT use this with a QtQuick.Repeater.
0039  *
0040  * @since org.kde.kirigami 2.4
0041  */
0042 class DelegateRecycler : public QQuickItem
0043 {
0044     Q_OBJECT
0045 
0046     /**
0047      * The Component the actual delegates will be built from.
0048      *
0049      * @note the component may not be a child of this object, therefore it can't be
0050      * declared inside the DelegateRecycler declaration.
0051      *
0052      * The DelegateRecycler will not take ownership of the delegate Component, so it's up
0053      * to the caller to delete it (usually with the normal child/parent relationship)
0054      */
0055     Q_PROPERTY(QQmlComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceComponentChanged)
0056 
0057 public:
0058     DelegateRecycler(QQuickItem *parent = nullptr);
0059     ~DelegateRecycler() override;
0060 
0061     QQmlComponent *sourceComponent() const;
0062     void setSourceComponent(QQmlComponent *component);
0063     void resetSourceComponent();
0064 
0065     static DelegateRecyclerAttached *qmlAttachedProperties(QObject *object);
0066 
0067 protected:
0068 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0069     void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0070 #else
0071     void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0072 #endif
0073     void focusInEvent(QFocusEvent *event) override;
0074 
0075     void updateHints();
0076     void updateSize(bool parentResized);
0077 
0078 Q_SIGNALS:
0079     void sourceComponentChanged();
0080 
0081 private Q_SLOTS:
0082     void syncIndex();
0083     void syncModel();
0084     void syncModelProperties();
0085     void syncModelData();
0086 
0087 private:
0088     QPointer<QQmlComponent> m_sourceComponent;
0089     QPointer<QQuickItem> m_item;
0090     QObject *m_propertiesTracker = nullptr;
0091     bool m_updatingSize = false;
0092     bool m_widthFromItem = false;
0093     bool m_heightFromItem = false;
0094 };
0095 
0096 QML_DECLARE_TYPEINFO(DelegateRecycler, QML_HAS_ATTACHED_PROPERTIES)
0097 
0098 #endif