1 // SPDX-FileCopyrightText: 2021 Nheko Contributors
2 //
3 // SPDX-License-Identifier: GPL-3.0-or-later
4
5 #include "DelegateChooser.h"
6
7 #include "Logging.h"
8
9 // uses private API, which moved between versions
10 #include <QQmlEngine>
11 #include <QtGlobal>
12
13 QQmlComponent *
delegate() const14 DelegateChoice::delegate() const
15 {
16 return delegate_;
17 }
18
19 void
setDelegate(QQmlComponent * delegate)20 DelegateChoice::setDelegate(QQmlComponent *delegate)
21 {
22 if (delegate != delegate_) {
23 delegate_ = delegate;
24 emit delegateChanged();
25 emit changed();
26 }
27 }
28
29 QVariant
roleValue() const30 DelegateChoice::roleValue() const
31 {
32 return roleValue_;
33 }
34
35 void
setRoleValue(const QVariant & value)36 DelegateChoice::setRoleValue(const QVariant &value)
37 {
38 if (value != roleValue_) {
39 roleValue_ = value;
40 emit roleValueChanged();
41 emit changed();
42 }
43 }
44
45 QVariant
roleValue() const46 DelegateChooser::roleValue() const
47 {
48 return roleValue_;
49 }
50
51 void
setRoleValue(const QVariant & value)52 DelegateChooser::setRoleValue(const QVariant &value)
53 {
54 if (value != roleValue_) {
55 roleValue_ = value;
56 recalcChild();
57 emit roleValueChanged();
58 }
59 }
60
61 QQmlListProperty<DelegateChoice>
choices()62 DelegateChooser::choices()
63 {
64 return QQmlListProperty<DelegateChoice>(this,
65 this,
66 &DelegateChooser::appendChoice,
67 &DelegateChooser::choiceCount,
68 &DelegateChooser::choice,
69 &DelegateChooser::clearChoices);
70 }
71
72 void
appendChoice(QQmlListProperty<DelegateChoice> * p,DelegateChoice * c)73 DelegateChooser::appendChoice(QQmlListProperty<DelegateChoice> *p, DelegateChoice *c)
74 {
75 DelegateChooser *dc = static_cast<DelegateChooser *>(p->object);
76 dc->choices_.append(c);
77 }
78
79 int
choiceCount(QQmlListProperty<DelegateChoice> * p)80 DelegateChooser::choiceCount(QQmlListProperty<DelegateChoice> *p)
81 {
82 return static_cast<DelegateChooser *>(p->object)->choices_.count();
83 }
84 DelegateChoice *
choice(QQmlListProperty<DelegateChoice> * p,int index)85 DelegateChooser::choice(QQmlListProperty<DelegateChoice> *p, int index)
86 {
87 return static_cast<DelegateChooser *>(p->object)->choices_.at(index);
88 }
89 void
clearChoices(QQmlListProperty<DelegateChoice> * p)90 DelegateChooser::clearChoices(QQmlListProperty<DelegateChoice> *p)
91 {
92 static_cast<DelegateChooser *>(p->object)->choices_.clear();
93 }
94
95 void
recalcChild()96 DelegateChooser::recalcChild()
97 {
98 for (const auto choice : qAsConst(choices_)) {
99 auto choiceValue = choice->roleValue();
100 if (!roleValue_.isValid() || !choiceValue.isValid() || choiceValue == roleValue_) {
101 if (child_) {
102 child_->setParentItem(nullptr);
103 child_ = nullptr;
104 }
105
106 choice->delegate()->create(incubator, QQmlEngine::contextForObject(this));
107 return;
108 }
109 }
110 }
111
112 void
componentComplete()113 DelegateChooser::componentComplete()
114 {
115 QQuickItem::componentComplete();
116 recalcChild();
117 }
118
119 void
statusChanged(QQmlIncubator::Status status)120 DelegateChooser::DelegateIncubator::statusChanged(QQmlIncubator::Status status)
121 {
122 if (status == QQmlIncubator::Ready) {
123 chooser.child_ = dynamic_cast<QQuickItem *>(object());
124 if (chooser.child_ == nullptr) {
125 nhlog::ui()->error("Delegate has to be derived of Item!");
126 return;
127 }
128
129 chooser.child_->setParentItem(&chooser);
130 QQmlEngine::setObjectOwnership(chooser.child_,
131 QQmlEngine::ObjectOwnership::JavaScriptOwnership);
132 emit chooser.childChanged();
133
134 } else if (status == QQmlIncubator::Error) {
135 for (const auto &e : errors())
136 nhlog::ui()->error("Error instantiating delegate: {}", e.toString().toStdString());
137 }
138 }
139