From 8e6500ae47ff74539cd2c0a9c4eebe96e69ca81d Mon Sep 17 00:00:00 2001
From: James Turner <zakalawe@mac.com>
Date: Tue, 28 Nov 2017 22:54:12 +0000
Subject: [PATCH] Orderly destruction of canvas elements

Driven from the object destroyed signal, ensure children and
corresponding QQ items are also destroyed when the property is removed.
---
 utils/fgqcanvas/fgcanvaselement.cpp | 11 +++++++++++
 utils/fgqcanvas/fgcanvaselement.h   |  6 ++++++
 utils/fgqcanvas/fgcanvasgroup.cpp   | 21 +++++++++++++++++++++
 utils/fgqcanvas/fgcanvasgroup.h     |  3 +++
 utils/fgqcanvas/fgcanvaspath.cpp    |  5 +++++
 utils/fgqcanvas/fgcanvaspath.h      |  2 ++
 utils/fgqcanvas/fgcanvastext.cpp    |  6 ++++++
 utils/fgqcanvas/fgcanvastext.h      |  3 +++
 utils/fgqcanvas/fgqcanvasimage.cpp  |  4 ++++
 utils/fgqcanvas/fgqcanvasimage.h    |  1 +
 10 files changed, 62 insertions(+)

diff --git a/utils/fgqcanvas/fgcanvaselement.cpp b/utils/fgqcanvas/fgcanvaselement.cpp
index 748e6bda9..4a489a6fc 100644
--- a/utils/fgqcanvas/fgcanvaselement.cpp
+++ b/utils/fgqcanvas/fgcanvaselement.cpp
@@ -89,6 +89,7 @@ FGCanvasElement::FGCanvasElement(FGCanvasGroup* pr, LocalProp* prop) :
             this, &FGCanvasElement::onVisibleChanged);
     connect(prop, &LocalProp::childAdded, this, &FGCanvasElement::onChildAdded);
     connect(prop, &LocalProp::childRemoved, this, &FGCanvasElement::onChildRemoved);
+    connect(prop, &LocalProp::destroyed, this, &FGCanvasElement::onPropDestroyed);
 
     if (pr) {
         pr->markChildZIndicesDirty();
@@ -97,6 +98,12 @@ FGCanvasElement::FGCanvasElement(FGCanvasGroup* pr, LocalProp* prop) :
     requestPolish();
 }
 
+void FGCanvasElement::onPropDestroyed()
+{
+    doDestroy();
+    const_cast<FGCanvasGroup*>(_parent)->removeChild(this);
+    deleteLater();
+}
 
 void FGCanvasElement::requestPolish()
 {
@@ -304,6 +311,10 @@ bool FGCanvasElement::onChildRemoved(LocalProp *prop)
     return false;
 }
 
+void FGCanvasElement::doDestroy()
+{
+}
+
 QColor FGCanvasElement::fillColor() const
 {
     return _fillColor;
diff --git a/utils/fgqcanvas/fgcanvaselement.h b/utils/fgqcanvas/fgcanvaselement.h
index 01e05b468..8d59f1e24 100644
--- a/utils/fgqcanvas/fgcanvaselement.h
+++ b/utils/fgqcanvas/fgcanvaselement.h
@@ -73,6 +73,8 @@ protected:
     virtual bool onChildAdded(LocalProp* prop);
     virtual bool onChildRemoved(LocalProp* prop);
 
+    virtual void doDestroy();
+
     const LocalProp* _propertyRoot;
     const FGCanvasGroup* _parent;
 
@@ -83,6 +85,10 @@ protected:
     virtual void markStyleDirty();
 
     QVariant getCascadedStyle(const char* name, QVariant defaultValue = QVariant()) const;
+
+private slots:
+    void onPropDestroyed();
+
 private:
 
     void onCenterChanged(QVariant value);
diff --git a/utils/fgqcanvas/fgcanvasgroup.cpp b/utils/fgqcanvas/fgcanvasgroup.cpp
index c4158264a..4ceac22bd 100644
--- a/utils/fgqcanvas/fgcanvasgroup.cpp
+++ b/utils/fgqcanvas/fgcanvasgroup.cpp
@@ -190,6 +190,16 @@ bool FGCanvasGroup::onChildRemoved(LocalProp *prop)
     return false;
 }
 
+void FGCanvasGroup::removeChild(FGCanvasElement *child)
+{
+    auto it = std::find(_children.begin(), _children.end(), child);
+    if (it != _children.end()) {
+        int index = std::distance(_children.begin(), it);
+        _children.erase(it);
+        emit childRemoved(index);
+    }
+}
+
 int FGCanvasGroup::indexOfChildWithProp(LocalProp* prop) const
 {
     auto it = std::find_if(_children.begin(), _children.end(), [prop](FGCanvasElement* child)
@@ -211,6 +221,17 @@ void FGCanvasGroup::markStyleDirty()
     }
 }
 
+void FGCanvasGroup::doDestroy()
+{
+    delete _quick;
+
+    FGCanvasElementVec children = std::move(_children);
+    _children.clear();
+    for (auto c : children) {
+        delete c;
+    }
+}
+
 void FGCanvasGroup::markCachedSymbolDirty()
 {
     _cachedSymbolDirty = true;
diff --git a/utils/fgqcanvas/fgcanvasgroup.h b/utils/fgqcanvas/fgcanvasgroup.h
index 8b7b39492..985eacba9 100644
--- a/utils/fgqcanvas/fgcanvasgroup.h
+++ b/utils/fgqcanvas/fgcanvasgroup.h
@@ -25,6 +25,7 @@ public:
     CanvasItem* quickItem() const override
     { return _quick; }
 
+    void removeChild(FGCanvasElement* child);
 signals:
     void childAdded();
     void childRemoved(int index);
@@ -39,6 +40,8 @@ protected:
     bool onChildRemoved(LocalProp *prop) override;
 
     virtual void markStyleDirty() override;
+
+    void doDestroy() override;
 private:
     void markCachedSymbolDirty();
     int indexOfChildWithProp(LocalProp *prop) const;
diff --git a/utils/fgqcanvas/fgcanvaspath.cpp b/utils/fgqcanvas/fgcanvaspath.cpp
index b66869fe4..11758ff89 100644
--- a/utils/fgqcanvas/fgcanvaspath.cpp
+++ b/utils/fgqcanvas/fgcanvaspath.cpp
@@ -466,6 +466,11 @@ CanvasItem *FGCanvasPath::quickItem() const
     return _quickPath;
 }
 
+void FGCanvasPath::doDestroy()
+{
+    delete _quickPath;
+}
+
 void FGCanvasPath::markPathDirty()
 {
     _pathDirty = true;
diff --git a/utils/fgqcanvas/fgcanvaspath.h b/utils/fgqcanvas/fgcanvaspath.h
index ea8d0ac30..973697278 100644
--- a/utils/fgqcanvas/fgcanvaspath.h
+++ b/utils/fgqcanvas/fgcanvaspath.h
@@ -40,6 +40,8 @@ protected:
     CanvasItem* createQuickItem(QQuickItem *parent) override;
     CanvasItem* quickItem() const override;
 
+    void doDestroy() override;
+
 private:
     void markPathDirty();
     void markStrokeDirty();
diff --git a/utils/fgqcanvas/fgcanvastext.cpp b/utils/fgqcanvas/fgcanvastext.cpp
index 2e342337a..002e1e2ad 100644
--- a/utils/fgqcanvas/fgcanvastext.cpp
+++ b/utils/fgqcanvas/fgcanvastext.cpp
@@ -252,6 +252,12 @@ void FGCanvasText::markStyleDirty()
     markFontDirty();
 }
 
+void FGCanvasText::doDestroy()
+{
+    qDebug() << Q_FUNC_INFO;
+    delete _quickItem;
+}
+
 bool FGCanvasText::onChildAdded(LocalProp *prop)
 {
     if (FGCanvasElement::onChildAdded(prop)) {
diff --git a/utils/fgqcanvas/fgcanvastext.h b/utils/fgqcanvas/fgcanvastext.h
index ceb22ee5a..51c1f5833 100644
--- a/utils/fgqcanvas/fgcanvastext.h
+++ b/utils/fgqcanvas/fgcanvastext.h
@@ -38,6 +38,9 @@ protected:
     void doPolish() override;
 
     virtual void markStyleDirty() override;
+
+    void doDestroy() override;
+
 private:
     bool onChildAdded(LocalProp *prop) override;
 
diff --git a/utils/fgqcanvas/fgqcanvasimage.cpp b/utils/fgqcanvas/fgqcanvasimage.cpp
index 46127f955..64d51c43e 100644
--- a/utils/fgqcanvas/fgqcanvasimage.cpp
+++ b/utils/fgqcanvas/fgqcanvasimage.cpp
@@ -242,6 +242,10 @@ void FGQCanvasImage::markStyleDirty()
 {
 }
 
+void FGQCanvasImage::doDestroy()
+{
+    delete _quickItem;
+}
 
 CanvasItem *FGQCanvasImage::createQuickItem(QQuickItem *parent)
 {
diff --git a/utils/fgqcanvas/fgqcanvasimage.h b/utils/fgqcanvas/fgqcanvasimage.h
index 6ad3ededb..ae7f3cffd 100644
--- a/utils/fgqcanvas/fgqcanvasimage.h
+++ b/utils/fgqcanvas/fgqcanvasimage.h
@@ -38,6 +38,7 @@ protected:
 
     virtual void markStyleDirty() override;
 
+    void doDestroy() override;
 
     void doPolish() override;
 private slots: