From f09f591e6adaa8bed6ed3698611c5b4546f8ebb8 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Thu, 21 Mar 2024 05:26:04 -0700 Subject: [PATCH] core/region: improve child handling - Children are no longer reparented - `regions` is now a full list property --- src/core/region.cpp | 65 +++++++++++++++++++++++++++++++++++++++------ src/core/region.hpp | 7 +++++ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/core/region.cpp b/src/core/region.cpp index 5bd7da59..47f15d4a 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 06654ca9..35f2736c 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;