1 // SPDX-FileCopyrightText: 2021 Nheko Contributors
2 //
3 // SPDX-License-Identifier: GPL-3.0-or-later
4 
5 // A DelegateChooser like the one, that was added to Qt5.12 (in labs), but compatible with older Qt
6 // versions see KDE/kquickitemviews see qtdeclarative/qqmldelagatecomponent
7 
8 #pragma once
9 
10 #include <QQmlComponent>
11 #include <QQmlIncubator>
12 #include <QQmlListProperty>
13 #include <QQuickItem>
14 #include <QtCore/QObject>
15 #include <QtCore/QVariant>
16 
17 class QQmlAdaptorModel;
18 
19 class DelegateChoice : public QObject
20 {
21     Q_OBJECT
22     Q_CLASSINFO("DefaultProperty", "delegate")
23 
24 public:
25     Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
26     Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
27 
28     QQmlComponent *delegate() const;
29     void setDelegate(QQmlComponent *delegate);
30 
31     QVariant roleValue() const;
32     void setRoleValue(const QVariant &value);
33 
34 signals:
35     void delegateChanged();
36     void roleValueChanged();
37     void changed();
38 
39 private:
40     QVariant roleValue_;
41     QQmlComponent *delegate_ = nullptr;
42 };
43 
44 class DelegateChooser : public QQuickItem
45 {
46     Q_OBJECT
47     Q_CLASSINFO("DefaultProperty", "choices")
48 
49 public:
50     Q_PROPERTY(QQmlListProperty<DelegateChoice> choices READ choices CONSTANT)
51     Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
52     Q_PROPERTY(QQuickItem *child READ child NOTIFY childChanged)
53 
54     QQmlListProperty<DelegateChoice> choices();
55 
56     QVariant roleValue() const;
57     void setRoleValue(const QVariant &value);
58 
child()59     QQuickItem *child() const { return child_; }
60 
61     void recalcChild();
62     void componentComplete() override;
63 
64 signals:
65     void roleChanged();
66     void roleValueChanged();
67     void childChanged();
68 
69 private:
70     struct DelegateIncubator : public QQmlIncubator
71     {
DelegateIncubatorDelegateIncubator72         DelegateIncubator(DelegateChooser &parent)
73           : QQmlIncubator(QQmlIncubator::AsynchronousIfNested)
74           , chooser(parent)
75         {}
76         void statusChanged(QQmlIncubator::Status status) override;
77 
78         DelegateChooser &chooser;
79     };
80 
81     QVariant roleValue_;
82     QList<DelegateChoice *> choices_;
83     QQuickItem *child_ = nullptr;
84     DelegateIncubator incubator{*this};
85 
86     static void appendChoice(QQmlListProperty<DelegateChoice> *, DelegateChoice *);
87     static int choiceCount(QQmlListProperty<DelegateChoice> *);
88     static DelegateChoice *choice(QQmlListProperty<DelegateChoice> *, int index);
89     static void clearChoices(QQmlListProperty<DelegateChoice> *);
90 };
91