From 4055e25636acbb5a78c09d583c941a5fb26b0d53 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Mon, 12 Dec 2022 14:05:15 +0100
Subject: [PATCH] SampleItem: m_layers --> QwningVector

---
 Base/Types/OwningVector.h            |  5 +-
 GUI/Model/FromCore/ItemizeSample.cpp |  2 -
 GUI/Model/Sample/SampleItem.cpp      | 76 ++++++++++------------------
 GUI/Model/Sample/SampleItem.h        |  5 +-
 4 files changed, 36 insertions(+), 52 deletions(-)

diff --git a/Base/Types/OwningVector.h b/Base/Types/OwningVector.h
index 51f7bc4f4cd..01e6234e573 100644
--- a/Base/Types/OwningVector.h
+++ b/Base/Types/OwningVector.h
@@ -45,7 +45,9 @@ public:
     OwningVector& operator=(OwningVector&& other) = default;
 
     void reserve(size_t n) { m_v.reserve(n); }
-    void emplace_back(T* e) { m_v.emplace_back(e); }
+    void emplace_back(T* e) { m_v.emplace_back(e); }    
+    void insert_at(size_t index, T* e) { m_v.insert(m_v.begin() + index, e); }
+
     void clear()
     {
         for (T* e : *this)
@@ -57,6 +59,7 @@ public:
     bool empty() const { return m_v.empty(); }
     T* const& operator[](int i) const { return m_v.operator[](i); }
     T* const& at(int i) const { return m_v.at(i); }
+    T* const& front() const { return m_v.front(); }
     T* const& back() const { return m_v.back(); }
 
     void delete_element(T* e)
diff --git a/GUI/Model/FromCore/ItemizeSample.cpp b/GUI/Model/FromCore/ItemizeSample.cpp
index f51dd2d6569..97be828d201 100644
--- a/GUI/Model/FromCore/ItemizeSample.cpp
+++ b/GUI/Model/FromCore/ItemizeSample.cpp
@@ -647,8 +647,6 @@ SampleItem* itemizeSample(const MultiLayer& sample, const QString& nodeName)
 
         auto* layerItem = result->addLayer();
         layerItem->setMaterial(findMaterialItem(matItems, layer));
-        layerItem->setIsTopLayer(layerIndex == 0);
-        layerItem->setIsBottomLayer(layerIndex == sample.numberOfLayers() - 1);
 
         setLayerItem(layerItem, layer, top_interface);
 
diff --git a/GUI/Model/Sample/SampleItem.cpp b/GUI/Model/Sample/SampleItem.cpp
index 9acf92d0049..e93846871c2 100644
--- a/GUI/Model/Sample/SampleItem.cpp
+++ b/GUI/Model/Sample/SampleItem.cpp
@@ -41,6 +41,8 @@ SampleItem::SampleItem()
     m_externalField.init("External field", "External field (A/m)", "A/m", "extField");
 }
 
+SampleItem::~SampleItem() {}
+
 void SampleItem::initFrom(const SampleItem* other)
 {
     GUI::Util::copyContents(other, this);
@@ -64,7 +66,7 @@ void SampleItem::addStandardMaterials()
 
 QVector<LayerItem*> SampleItem::layers() const
 {
-    return m_layers;
+    return QVector<LayerItem*>(m_layers.begin(), m_layers.end());
 }
 
 LayerItem* SampleItem::addLayer(int index)
@@ -73,41 +75,40 @@ LayerItem* SampleItem::addLayer(int index)
         index = m_layers.size();
 
     auto* layer = new LayerItem(&m_materials);
-    m_layers.insert(index, layer);
-    layer->setIsTopLayer(m_layers.first() == layer);
-    layer->setIsBottomLayer(m_layers.last() == layer);
+    m_layers.insert_at(index, layer);
+    updateTopBottom();
     return layer;
 }
 
-void SampleItem::removeLayer(LayerItem* layer)
+void SampleItem::updateTopBottom()
 {
-    m_layers.removeAll(layer);
-    delete layer;
-
-    if (!m_layers.isEmpty()) {
-        m_layers.first()->setIsTopLayer(true);
-        m_layers.last()->setIsBottomLayer(true);
+    for (LayerItem* l : m_layers) {
+        l->setIsTopLayer(m_layers.front() == l);
+        l->setIsBottomLayer(m_layers.back() == l);
     }
 }
 
+void SampleItem::removeLayer(LayerItem* layer)
+{
+    m_layers.delete_element(layer);
+    updateTopBottom();
+}
+
 void SampleItem::moveLayer(LayerItem* layer, LayerItem* beforeThisLayer)
 {
-    m_layers.removeAll(layer);
-    int index = m_layers.size(); // move to end
+    int destIndex = m_layers.size();
     if (beforeThisLayer != nullptr)
-        index = m_layers.indexOf(beforeThisLayer);
-    m_layers.insert(index, layer);
-    for (auto* l : m_layers) {
-        l->setIsTopLayer(m_layers.first() == l);
-        l->setIsBottomLayer(m_layers.last() == l);
-    }
+        destIndex = layers().indexOf(beforeThisLayer);
+    m_layers.insert_at(destIndex, layer);
+
+    int currentIndex = layers().indexOf(layer);
+    std::rotate(m_layers.begin() + currentIndex, m_layers.begin() + destIndex, m_layers.end());
+
+    updateTopBottom();
 }
 
 void SampleItem::writeTo(QXmlStreamWriter* w) const
 {
-//    Streamer s(w);
-//    const_cast<SampleItem*>(this)->serialize(s);
-
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
     // name
@@ -145,14 +146,10 @@ void SampleItem::writeTo(QXmlStreamWriter* w) const
 
 void SampleItem::readFrom(QXmlStreamReader* r)
 {
-//    Streamer s(r);
-//    serialize(s);
-
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
 
-    // TODO owning vector
-    qDeleteAll(m_layers);
+    m_layers.clear();
 
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
@@ -190,29 +187,12 @@ void SampleItem::readFrom(QXmlStreamReader* r)
         } else
             r->skipCurrentElement();
     }
-
-    // post-read assignment
-    for (auto* l : m_layers) {
-        l->setIsTopLayer(m_layers.first() == l);
-        l->setIsBottomLayer(m_layers.last() == l);
-    }
 }
 
 void SampleItem::serialize(Streamer& s)
 {
-    s.assertVersion(0);
-    Serialize::rwValue(s, Tag::Name, m_name);
-    Serialize::rwValue(s, Tag::Description, m_description);
-    Serialize::rwProperty(s, Tag::CrossCorrelationLength, m_crossCorrelationLength);
-    m_externalField.rwProperty(s, Tag::ExternalField);
-    Serialize::rwClass(s, Tag::Materials, m_materials);
-    Serialize::rwVector(s, "Layers", m_layers, &m_materials);
-
-    if (s.xmlReader()) {
-        // set non-stored infos
-        for (auto* l : m_layers) {
-            l->setIsTopLayer(m_layers.first() == l);
-            l->setIsBottomLayer(m_layers.last() == l);
-        }
-    }
+    if (s.xmlReader())
+        readFrom(s.xmlReader());
+    else if (s.xmlWriter())
+        writeTo(s.xmlWriter());
 }
diff --git a/GUI/Model/Sample/SampleItem.h b/GUI/Model/Sample/SampleItem.h
index ff2d2a16678..6bc4a1e4031 100644
--- a/GUI/Model/Sample/SampleItem.h
+++ b/GUI/Model/Sample/SampleItem.h
@@ -15,6 +15,7 @@
 #ifndef BORNAGAIN_GUI_MODEL_SAMPLE_SAMPLEITEM_H
 #define BORNAGAIN_GUI_MODEL_SAMPLE_SAMPLEITEM_H
 
+#include "Base/Types/OwningVector.h"
 #include "GUI/Model/Descriptor/VectorProperty.h"
 #include "GUI/Model/Sample/Item3D.h"
 #include "GUI/Model/Sample/MaterialModel.h"
@@ -30,6 +31,7 @@ class Streamer;
 class SampleItem : public virtual Item3D {
 public:
     SampleItem();
+    ~SampleItem();
 
     void initFrom(const SampleItem* other);
 
@@ -59,6 +61,7 @@ public:
     //! If index = -1, create a layer at the end of the list.
     LayerItem* addLayer(int index = -1);
 
+    void updateTopBottom();
     void removeLayer(LayerItem* item);
     void moveLayer(LayerItem* item, LayerItem* beforeThisLayer);
 
@@ -74,7 +77,7 @@ private:
     QString m_description;
     DoubleProperty m_crossCorrelationLength;
     VectorProperty m_externalField;
-    QVector<LayerItem*> m_layers;
+    OwningVector<LayerItem> m_layers;
     MaterialModel m_materials;
 };
 
-- 
GitLab