core/region: improve child handling

- Children are no longer reparented
- `regions` is now a full list property
This commit is contained in:
outfoxxed 2024-03-21 05:26:04 -07:00
parent 8e25c1cee0
commit f09f591e6a
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
2 changed files with 64 additions and 8 deletions

View file

@ -7,6 +7,7 @@
#include <qquickitem.h> #include <qquickitem.h>
#include <qregion.h> #include <qregion.h>
#include <qtmetamacros.h> #include <qtmetamacros.h>
#include <qtypes.h>
PendingRegion::PendingRegion(QObject* parent): QObject(parent) { PendingRegion::PendingRegion(QObject* parent): QObject(parent) {
QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed); QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed);
@ -27,6 +28,7 @@ void PendingRegion::setItem(QQuickItem* item) {
this->mItem = item; this->mItem = item;
if (item != nullptr) { 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::xChanged, this, &PendingRegion::itemChanged);
QObject::connect(this->mItem, &QQuickItem::yChanged, this, &PendingRegion::itemChanged); QObject::connect(this->mItem, &QQuickItem::yChanged, this, &PendingRegion::itemChanged);
QObject::connect(this->mItem, &QQuickItem::widthChanged, 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::onItemDestroyed() { this->mItem = nullptr; }
void PendingRegion::onChildDestroyed() { this->mRegions.removeAll(this->sender()); }
QQmlListProperty<PendingRegion> PendingRegion::regions() { QQmlListProperty<PendingRegion> PendingRegion::regions() {
return QQmlListProperty<PendingRegion>( return QQmlListProperty<PendingRegion>(
this, this,
nullptr, nullptr,
PendingRegion::regionsAppend, &PendingRegion::regionsAppend,
nullptr, &PendingRegion::regionsCount,
nullptr, &PendingRegion::regionAt,
nullptr, &PendingRegion::regionsClear,
nullptr, &PendingRegion::regionsReplace,
nullptr &PendingRegion::regionsRemoveLast
); );
} }
@ -103,9 +107,54 @@ QRegion PendingRegion::applyTo(QRegion& region) const {
void PendingRegion::regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region) { void PendingRegion::regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region) {
auto* self = static_cast<PendingRegion*>(prop->object); // NOLINT auto* self = static_cast<PendingRegion*>(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); self->mRegions.append(region);
QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged); emit self->childrenChanged();
}
PendingRegion* PendingRegion::regionAt(QQmlListProperty<PendingRegion>* prop, qsizetype i) {
return static_cast<PendingRegion*>(prop->object)->mRegions.at(i); // NOLINT
}
void PendingRegion::regionsClear(QQmlListProperty<PendingRegion>* prop) {
auto* self = static_cast<PendingRegion*>(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<PendingRegion>* prop) {
return static_cast<PendingRegion*>(prop->object)->mRegions.length(); // NOLINT
}
void PendingRegion::regionsRemoveLast(QQmlListProperty<PendingRegion>* prop) {
auto* self = static_cast<PendingRegion*>(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<PendingRegion>* prop,
qsizetype i,
PendingRegion* region
) {
auto* self = static_cast<PendingRegion*>(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(); emit self->childrenChanged();
} }

View file

@ -110,9 +110,16 @@ signals:
private slots: private slots:
void onItemDestroyed(); void onItemDestroyed();
void onChildDestroyed();
private: private:
static void regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region); static void regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region);
static PendingRegion* regionAt(QQmlListProperty<PendingRegion>* prop, qsizetype i);
static void regionsClear(QQmlListProperty<PendingRegion>* prop);
static qsizetype regionsCount(QQmlListProperty<PendingRegion>* prop);
static void regionsRemoveLast(QQmlListProperty<PendingRegion>* prop);
static void
regionsReplace(QQmlListProperty<PendingRegion>* prop, qsizetype i, PendingRegion* region);
QQuickItem* mItem = nullptr; QQuickItem* mItem = nullptr;