diff --git a/src/core/region.cpp b/src/core/region.cpp index e36ed7d7..11892d6d 100644 --- a/src/core/region.cpp +++ b/src/core/region.cpp @@ -1,13 +1,13 @@ #include "region.hpp" #include -#include #include #include #include #include #include #include +#include #include PendingRegion::PendingRegion(QObject* parent): QObject(parent) { @@ -19,7 +19,6 @@ PendingRegion::PendingRegion(QObject* parent): QObject(parent) { QObject::connect(this, &PendingRegion::widthChanged, this, &PendingRegion::changed); QObject::connect(this, &PendingRegion::heightChanged, this, &PendingRegion::changed); QObject::connect(this, &PendingRegion::childrenChanged, this, &PendingRegion::changed); - QObject::connect(this, &PendingRegion::regionsChanged, this, &PendingRegion::childrenChanged); } void PendingRegion::setItem(QQuickItem* item) { @@ -42,33 +41,21 @@ void PendingRegion::setItem(QQuickItem* item) { emit this->itemChanged(); } -void PendingRegion::onItemDestroyed() { - this->mItem = nullptr; - emit this->itemChanged(); -} +void PendingRegion::onItemDestroyed() { this->mItem = nullptr; } -void PendingRegion::onChildDestroyed() { - this->mRegions.removeAll(this->sender()); - emit this->regionsChanged(); -} +void PendingRegion::onChildDestroyed() { this->mRegions.removeAll(this->sender()); } -const QList& PendingRegion::regions() const { return this->mRegions; } - -void PendingRegion::setRegions(const QList& regions) { - if (regions == this->mRegions) return; - - for (auto* region: this->mRegions) { - QObject::disconnect(region, nullptr, this, nullptr); - } - - this->mRegions = regions; - - for (auto* region: regions) { - QObject::connect(region, &QObject::destroyed, this, &PendingRegion::onChildDestroyed); - QObject::connect(region, &PendingRegion::changed, this, &PendingRegion::childrenChanged); - } - - emit this->regionsChanged(); +QQmlListProperty PendingRegion::regions() { + return QQmlListProperty( + this, + nullptr, + &PendingRegion::regionsAppend, + &PendingRegion::regionsCount, + &PendingRegion::regionAt, + &PendingRegion::regionsClear, + &PendingRegion::regionsReplace, + &PendingRegion::regionsRemoveLast + ); } bool PendingRegion::empty() const { @@ -130,3 +117,58 @@ QRegion PendingRegion::applyTo(const QRect& rect) const { return this->applyTo(baseRegion); } } + +void PendingRegion::regionsAppend(QQmlListProperty* prop, PendingRegion* region) { + auto* self = static_cast(prop->object); // NOLINT + if (!region) return; + + QObject::connect(region, &QObject::destroyed, self, &PendingRegion::onChildDestroyed); + QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged); + + self->mRegions.append(region); + + 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 0335abbf..6637d7bd 100644 --- a/src/core/region.hpp +++ b/src/core/region.hpp @@ -82,7 +82,7 @@ class PendingRegion: public QObject { /// } /// } /// ``` - Q_PROPERTY(QList regions READ regions WRITE setRegions NOTIFY regionsChanged); + Q_PROPERTY(QQmlListProperty regions READ regions); Q_CLASSINFO("DefaultProperty", "regions"); QML_NAMED_ELEMENT(Region); @@ -91,8 +91,7 @@ public: void setItem(QQuickItem* item); - [[nodiscard]] const QList& regions() const; - void setRegions(const QList& regions); + QQmlListProperty regions(); [[nodiscard]] bool empty() const; [[nodiscard]] QRegion build() const; @@ -110,7 +109,6 @@ signals: void yChanged(); void widthChanged(); void heightChanged(); - void regionsChanged(); void childrenChanged(); /// Triggered when the region's geometry changes. @@ -124,6 +122,14 @@ private slots: 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; qint32 mX = 0;