File indexing completed on 2025-02-09 04:25:59
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 #include "ItemBuilder.h" 0008 0009 class ItemIncubator : public QQmlIncubator 0010 { 0011 public: 0012 ItemIncubator(QQmlComponent *component, QQmlContext *context) 0013 { 0014 m_component = component; 0015 m_context = context; 0016 } 0017 0018 void setStateCallback(std::function<void(QQuickItem*)> callback) 0019 { 0020 m_stateCallback = callback; 0021 } 0022 0023 void setCompletedCallback(std::function<void(ItemIncubator*)> callback) 0024 { 0025 m_completedCallback = callback; 0026 } 0027 0028 void create() 0029 { 0030 m_component->create(*this, m_context); 0031 } 0032 0033 bool isFinished() 0034 { 0035 return m_finished; 0036 } 0037 0038 private: 0039 void setInitialState(QObject *object) override 0040 { 0041 auto item = qobject_cast<QQuickItem*>(object); 0042 if (item) { 0043 m_stateCallback(item); 0044 } 0045 } 0046 0047 void statusChanged(QQmlIncubator::Status status) override 0048 { 0049 if (status == QQmlIncubator::Error) { 0050 qWarning() << "Could not create delegate in ItemBuilder"; 0051 const auto e = errors(); 0052 for (const auto &error : e) { 0053 qWarning() << error; 0054 } 0055 m_finished = true; 0056 } 0057 0058 if (status == QQmlIncubator::Ready) { 0059 m_completedCallback(this); 0060 m_finished = true; 0061 } 0062 } 0063 0064 QQmlComponent *m_component; 0065 QQmlContext *m_context; 0066 std::function<void(QQuickItem*)> m_stateCallback; 0067 std::function<void(ItemIncubator*)> m_completedCallback; 0068 bool m_finished = false; 0069 }; 0070 0071 ItemBuilder::ItemBuilder(QObject *parent) 0072 : QObject(parent) 0073 { 0074 } 0075 0076 ItemBuilder::~ItemBuilder() 0077 { 0078 clear(); 0079 } 0080 0081 QQmlComponent *ItemBuilder::component() const 0082 { 0083 return m_component; 0084 } 0085 0086 void ItemBuilder::setComponent(QQmlComponent *newComponent) 0087 { 0088 if (newComponent == m_component) { 0089 return; 0090 } 0091 0092 m_component = newComponent; 0093 clear(); 0094 } 0095 0096 QQmlContext *ItemBuilder::context() const 0097 { 0098 return m_context; 0099 } 0100 0101 void ItemBuilder::setContext(QQmlContext *newContext) 0102 { 0103 if (newContext == m_context) { 0104 return; 0105 } 0106 0107 m_context = newContext; 0108 clear(); 0109 } 0110 0111 0112 int ItemBuilder::count() const 0113 { 0114 return m_count; 0115 } 0116 0117 void ItemBuilder::setCount(int newCount) 0118 { 0119 if (newCount == m_count) { 0120 return; 0121 } 0122 0123 m_count = newCount; 0124 clear(); 0125 } 0126 0127 QQmlIncubator::IncubationMode ItemBuilder::incubationMode() const 0128 { 0129 return m_incubationMode; 0130 } 0131 0132 void ItemBuilder::setIncubationMode(QQmlIncubator::IncubationMode newIncubationMode) 0133 { 0134 if (newIncubationMode == m_incubationMode) { 0135 return; 0136 } 0137 0138 m_incubationMode = newIncubationMode; 0139 } 0140 0141 QVariantMap ItemBuilder::initialProperties() const 0142 { 0143 return m_initialProperties; 0144 } 0145 0146 void ItemBuilder::setInitialProperties(const QVariantMap & newInitialProperties) 0147 { 0148 if (newInitialProperties == m_initialProperties) { 0149 return; 0150 } 0151 0152 m_initialProperties = newInitialProperties; 0153 } 0154 0155 void ItemBuilder::build(QQuickItem *parent) 0156 { 0157 if ((int(m_items.size()) == m_count && m_incubators.empty()) || !m_incubators.empty() || !m_component) { 0158 return; 0159 } 0160 0161 m_incubators.reserve(m_count); 0162 std::fill_n(std::back_inserter(m_items), m_count, std::shared_ptr<QQuickItem>()); 0163 0164 for (int i = 0; i < m_count; ++i) { 0165 auto context = m_context ? m_context : qmlContext(m_component); 0166 auto incubator = std::make_unique<ItemIncubator>(m_component, context); 0167 0168 incubator->setStateCallback([this, parent, i](QQuickItem *item) { 0169 item->setParentItem(parent); 0170 0171 for (auto itr = m_initialProperties.keyValueBegin(); itr != m_initialProperties.keyValueEnd(); ++itr) { 0172 item->setProperty((*itr).first.toUtf8().data(), (*itr).second); 0173 } 0174 0175 Q_EMIT beginCreate(i, item); 0176 }); 0177 0178 incubator->setCompletedCallback([this, i](ItemIncubator *incubator) { 0179 auto item = std::shared_ptr<QQuickItem>(qobject_cast<QQuickItem*>(incubator->object())); 0180 m_items[i] = item; 0181 0182 Q_EMIT endCreate(i, item.get()); 0183 0184 m_completed++; 0185 if (m_completed == m_count) { 0186 QMetaObject::invokeMethod(this, [this]() { 0187 m_incubators.clear(); 0188 }, Qt::QueuedConnection); 0189 Q_EMIT finished(); 0190 } 0191 }); 0192 0193 incubator->create(); 0194 0195 m_incubators.push_back(std::move(incubator)); 0196 } 0197 } 0198 0199 bool ItemBuilder::isFinished() const 0200 { 0201 return m_completed == m_count; 0202 } 0203 0204 std::vector<std::shared_ptr<QQuickItem>> ItemBuilder::items() const 0205 { 0206 return m_items; 0207 } 0208 0209 void ItemBuilder::clear() 0210 { 0211 m_items.clear(); 0212 0213 if (m_incubators.size() > 0) { 0214 for (auto &incubator : m_incubators) { 0215 incubator->clear(); 0216 } 0217 } 0218 m_incubators.clear(); 0219 0220 m_completed = 0; 0221 } 0222 0223 #include "moc_ItemBuilder.cpp"