diff --git a/src/core/region.cpp b/src/core/region.cpp index 5bd7da5..47f15d4 100644 --- a/src/core/region.cpp +++ b/src/core/region.cpp @@ -7,6 +7,7 @@ #include #include #include +#include PendingRegion::PendingRegion(QObject* parent): QObject(parent) { QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed); @@ -27,6 +28,7 @@ void PendingRegion::setItem(QQuickItem* item) { this->mItem = item; if (item != nullptr) { + QObject::connect(this->mItem, &QObject::destroyed, this, &PendingRegion::onItemDestroyed); QObject::connect(this->mItem, &QQuickItem::xChanged, this, &PendingRegion::itemChanged); QObject::connect(this->mItem, &QQuickItem::yChanged, this, &PendingRegion::itemChanged); QObject::connect(this->mItem, &QQuickItem::widthChanged, this, &PendingRegion::itemChanged); @@ -38,16 +40,18 @@ void PendingRegion::setItem(QQuickItem* item) { void PendingRegion::onItemDestroyed() { this->mItem = nullptr; } +void PendingRegion::onChildDestroyed() { this->mRegions.removeAll(this->sender()); } + QQmlListProperty PendingRegion::regions() { return QQmlListProperty( this, nullptr, - PendingRegion::regionsAppend, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr + &PendingRegion::regionsAppend, + &PendingRegion::regionsCount, + &PendingRegion::regionAt, + &PendingRegion::regionsClear, + &PendingRegion::regionsReplace, + &PendingRegion::regionsRemoveLast ); } @@ -103,9 +107,54 @@ QRegion PendingRegion::applyTo(QRegion& region) const { void PendingRegion::regionsAppend(QQmlListProperty* prop, PendingRegion* region) { auto* self = static_cast(prop->object); // NOLINT - region->setParent(self); + + QObject::connect(region, &QObject::destroyed, self, &PendingRegion::onChildDestroyed); + QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged); + self->mRegions.append(region); - QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged); + emit self->childrenChanged(); +} + +PendingRegion* PendingRegion::regionAt(QQmlListProperty* prop, qsizetype i) { + return static_cast(prop->object)->mRegions.at(i); // NOLINT +} + +void PendingRegion::regionsClear(QQmlListProperty* prop) { + auto* self = static_cast(prop->object); // NOLINT + + for (auto* region: self->mRegions) { + QObject::disconnect(region, nullptr, self, nullptr); + } + + self->mRegions.clear(); // NOLINT + emit self->childrenChanged(); +} + +qsizetype PendingRegion::regionsCount(QQmlListProperty* prop) { + return static_cast(prop->object)->mRegions.length(); // NOLINT +} + +void PendingRegion::regionsRemoveLast(QQmlListProperty* prop) { + auto* self = static_cast(prop->object); // NOLINT + + auto* last = self->mRegions.last(); + if (last != nullptr) QObject::disconnect(last, nullptr, self, nullptr); + + self->mRegions.removeLast(); + emit self->childrenChanged(); +} + +void PendingRegion::regionsReplace( + QQmlListProperty* prop, + qsizetype i, + PendingRegion* region +) { + auto* self = static_cast(prop->object); // NOLINT + + auto* old = self->mRegions.at(i); + if (old != nullptr) QObject::disconnect(old, nullptr, self, nullptr); + + self->mRegions.replace(i, region); emit self->childrenChanged(); } diff --git a/src/core/region.hpp b/src/core/region.hpp index 06654ca..35f2736 100644 --- a/src/core/region.hpp +++ b/src/core/region.hpp @@ -110,9 +110,16 @@ signals: private slots: void onItemDestroyed(); + void onChildDestroyed(); private: static void regionsAppend(QQmlListProperty* prop, PendingRegion* region); + static PendingRegion* regionAt(QQmlListProperty* prop, qsizetype i); + static void regionsClear(QQmlListProperty* prop); + static qsizetype regionsCount(QQmlListProperty* prop); + static void regionsRemoveLast(QQmlListProperty* prop); + static void + regionsReplace(QQmlListProperty* prop, qsizetype i, PendingRegion* region); QQuickItem* mItem = nullptr; diff --git a/src/core/variants.cpp b/src/core/variants.cpp index 8f251c1..aa3bdde 100644 --- a/src/core/variants.cpp +++ b/src/core/variants.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "reload.hpp" @@ -15,10 +16,10 @@ void Variants::onReload(QObject* oldInstance) { auto* old = qobject_cast(oldInstance); - for (auto& [variant, instanceObj]: this->instances.values) { + for (auto& [variant, instanceObj]: this->mInstances.values) { QObject* oldInstance = nullptr; if (old != nullptr) { - auto& values = old->instances.values; + auto& values = old->mInstances.values; if (variant.canConvert()) { auto variantMap = variant.value(); @@ -96,6 +97,19 @@ void Variants::setModel(const QVariant& model) { this->updateVariants(); emit this->modelChanged(); + emit this->instancesChanged(); +} + +QQmlListProperty Variants::instances() { + return QQmlListProperty(this, nullptr, &Variants::instanceCount, &Variants::instanceAt); +} + +qsizetype Variants::instanceCount(QQmlListProperty* prop) { + return static_cast(prop->object)->mInstances.values.length(); // NOLINT +} + +QObject* Variants::instanceAt(QQmlListProperty* prop, qsizetype i) { + return static_cast(prop->object)->mInstances.values.at(i).second; // NOLINT } void Variants::componentComplete() { @@ -110,12 +124,12 @@ void Variants::updateVariants() { } // clean up removed entries - for (auto iter = this->instances.values.begin(); iter < this->instances.values.end();) { + for (auto iter = this->mInstances.values.begin(); iter < this->mInstances.values.end();) { if (this->mModel.contains(iter->first)) { iter++; } else { iter->second->deleteLater(); - iter = this->instances.values.erase(iter); + iter = this->mInstances.values.erase(iter); } } @@ -130,7 +144,7 @@ void Variants::updateVariants() { } { - if (this->instances.contains(variant)) { + if (this->mInstances.contains(variant)) { continue; // we dont need to recreate this one } @@ -151,7 +165,7 @@ void Variants::updateVariants() { QQmlEngine::setObjectOwnership(instance, QQmlEngine::CppOwnership); instance->setParent(this); - this->instances.insert(variant, instance); + this->mInstances.insert(variant, instance); if (this->loaded) { if (auto* reloadable = qobject_cast(instance)) reloadable->onReload(nullptr); diff --git a/src/core/variants.hpp b/src/core/variants.hpp index cdfea7e..a9071cf 100644 --- a/src/core/variants.hpp +++ b/src/core/variants.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,8 @@ class Variants: public Reloadable { /// Each set creates an instance of the component, which are updated when the input sets update. QSDOC_PROPERTY_OVERRIDE(QList model READ model WRITE setModel NOTIFY modelChanged); QSDOC_HIDE Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged); + /// Current instances of the delegate. + Q_PROPERTY(QQmlListProperty instances READ instances NOTIFY instancesChanged); Q_CLASSINFO("DefaultProperty", "delegate"); QML_ELEMENT; @@ -64,14 +67,20 @@ public: [[nodiscard]] QVariant model() const; void setModel(const QVariant& model); + QQmlListProperty instances(); + signals: void modelChanged(); + void instancesChanged(); private: + static qsizetype instanceCount(QQmlListProperty* prop); + static QObject* instanceAt(QQmlListProperty* prop, qsizetype i); + void updateVariants(); QQmlComponent* mDelegate = nullptr; QVariantList mModel; - AwfulMap instances; + AwfulMap mInstances; bool loaded = false; };