From 48c10d2c9b71fa4fa923fb9183b53aa8b7b52f88 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:20:58 +0100
Subject: [PATCH 001/108] VectorWC + currentItem()

---
 Base/Types/VectorWC.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Base/Types/VectorWC.h b/Base/Types/VectorWC.h
index ff50130de8d..e2746542a29 100644
--- a/Base/Types/VectorWC.h
+++ b/Base/Types/VectorWC.h
@@ -83,6 +83,14 @@ public:
         m_current_index = i;
     }
     size_t currentIndex() const { return m_current_index; }
+    const T* currentItem() const
+    {
+        return m_current_index < super::size() ? super::at(m_current_index) : (T*)nullptr;
+    }
+    T* currentItem()
+    {
+        return m_current_index < super::size() ? super::at(m_current_index) : (T*)nullptr;
+    }
 
 private:
     void update_current()
-- 
GitLab


From 16471388bf755b42cc90fef99e171ad7b50386a6 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:26:19 +0100
Subject: [PATCH 002/108] get current instr directly from gDoc

---
 GUI/View/Views/InstrumentView.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 5137ef6ad96..ae27639812d 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -100,7 +100,7 @@ void InstrumentView::hideEvent(QHideEvent*)
 
 void InstrumentView::createWidgetsForCurrentInstrument()
 {
-    InstrumentItem* currentInstrument = m_listing->currentInstrumentItem();
+    InstrumentItem* currentInstrument = gDoc->instrumentsModifier()->currentItem();
     if (!currentInstrument) {
         m_scroll_area->setWidget(new QWidget(m_scroll_area)); // blank widget
         return;
@@ -157,14 +157,14 @@ void InstrumentView::createWidgetsForCurrentInstrument()
 
 void InstrumentView::onInstrumentNameEdited(const QString& newName)
 {
-    InstrumentItem* t = m_listing->currentInstrumentItem();
+    InstrumentItem* t = gDoc->instrumentsModifier()->currentItem();
     if (t && t->instrumentName() != newName)
         gDoc->instrumentsModifier()->setInstrumentName(t, newName);
 }
 
 void InstrumentView::onInstrumentdescriptionEdited(const QString& s)
 {
-    InstrumentItem* t = m_listing->currentInstrumentItem();
+    InstrumentItem* t = gDoc->instrumentsModifier()->currentItem();
     if (t && t->description() != s) {
         t->setDescription(s);
         onInstrumentChangedByEditor();
@@ -176,11 +176,11 @@ void InstrumentView::onInstrumentChangedByEditor()
     // uses 'instrumentChanged' signal for two purposes:
     // 1) notify 'ProjectDocument' that user has changed data ==> mark project with '*'
     // 2) notify 'LinkInstrumentManager' ==> unlink instrument from data if they are incompatible
-    emit gDoc->instruments()->instrumentChanged(m_listing->currentInstrumentItem());
+    emit gDoc->instruments()->instrumentChanged(gDoc->instrumentsModifier()->currentItem());
 }
 
 void InstrumentView::onInstrumentChangedFromExternal(const InstrumentItem* instrument)
 {
-    if (instrument == m_listing->currentInstrumentItem())
+    if (instrument == gDoc->instrumentsModifier()->currentItem())
         createWidgetsForCurrentInstrument();
 }
-- 
GitLab


From 162ad0b647f32926abeec3b7e4aad09c71828ef7 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:27:25 +0100
Subject: [PATCH 003/108] rm InstrumentsQListView::currentInstrumentItem()

---
 GUI/View/List/InstrumentsQListView.cpp | 8 --------
 GUI/View/List/InstrumentsQListView.h   | 2 --
 2 files changed, 10 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 3c075491916..d416557c304 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -79,14 +79,6 @@ QSize InstrumentsQListView::minimumSizeHint() const
     return {96, 200};
 }
 
-InstrumentItem* InstrumentsQListView::currentInstrumentItem() const
-{
-    const QModelIndexList indexes = selectionModel()->selectedIndexes();
-    if (!indexes.empty())
-        return m_model->instrumentItemForIndex(indexes.front());
-    return nullptr;
-}
-
 void InstrumentsQListView::onItemSelectionChanged()
 {
     updateActions();
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 5ee1847e46a..06c3933c0c1 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -30,8 +30,6 @@ public:
     QSize sizeHint() const override;
     QSize minimumSizeHint() const override;
 
-    InstrumentItem* currentInstrumentItem() const;
-
 signals:
     void instrumentSelected(InstrumentItem* instrument);
 
-- 
GitLab


From 7cece7ab93bbc20a848bc207be01fcffc04d2061 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:30:28 +0100
Subject: [PATCH 004/108] rm selection support from InstrumentsQListView

---
 GUI/View/List/InstrumentsQListView.cpp | 29 --------------------------
 GUI/View/List/InstrumentsQListView.h   |  2 --
 2 files changed, 31 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index d416557c304..2f331d765cd 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -63,10 +63,6 @@ InstrumentsQListView::InstrumentsQListView()
     setContextMenuPolicy(Qt::ActionsContextMenu);
 
     updateActions();
-    restoreSelection();
-
-    connect(selectionModel(), &QItemSelectionModel::selectionChanged, this,
-            &InstrumentsQListView::onItemSelectionChanged);
 }
 
 QSize InstrumentsQListView::sizeHint() const
@@ -79,19 +75,6 @@ QSize InstrumentsQListView::minimumSizeHint() const
     return {96, 200};
 }
 
-void InstrumentsQListView::onItemSelectionChanged()
-{
-    updateActions();
-
-    QModelIndexList indexes = selectionModel()->selectedIndexes();
-    if (!indexes.empty()) {
-        QModelIndex current = indexes.front();
-        gDoc->instrumentsModifier()->setCurrentIndex(current.row());
-        emit instrumentSelected(m_model->instrumentItemForIndex(current));
-    } else
-        emit instrumentSelected(nullptr);
-}
-
 void InstrumentsQListView::onNewGisas()
 {
     QModelIndex idx = m_model->addNewGISASInstrument();
@@ -192,15 +175,3 @@ void InstrumentsQListView::ensureItemSelected()
         selectionModel()->select(last, QItemSelectionModel::ClearAndSelect);
     }
 }
-
-void InstrumentsQListView::restoreSelection()
-{
-    int lastUsed = gDoc->instruments()->currentIndex();
-    if (lastUsed >= 0 && lastUsed < m_model->rowCount()) {
-        QModelIndex lastUsedIndex = m_model->index(lastUsed, 0, QModelIndex());
-        selectionModel()->select(lastUsedIndex, QItemSelectionModel::ClearAndSelect);
-    } else
-        ensureItemSelected();
-
-    updateActions();
-}
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 06c3933c0c1..064b50b3d28 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -34,7 +34,6 @@ signals:
     void instrumentSelected(InstrumentItem* instrument);
 
 private slots:
-    void onItemSelectionChanged();
     void onNewGisas();
     void onNewOffspec();
     void onNewSpecular();
@@ -49,7 +48,6 @@ private slots:
 private:
     void updateActions();
     void ensureItemSelected();
-    void restoreSelection();
 
     InstrumentsQModel* m_model;
 };
-- 
GitLab


From bbb3f7284816abb4704a9a4a272ff1b38d7dd0d4 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:35:01 +0100
Subject: [PATCH 005/108] rm selection signals from InstrumentsQListView

---
 GUI/View/List/InstrumentsQListView.cpp | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 2f331d765cd..66ced96e8f9 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -77,26 +77,22 @@ QSize InstrumentsQListView::minimumSizeHint() const
 
 void InstrumentsQListView::onNewGisas()
 {
-    QModelIndex idx = m_model->addNewGISASInstrument();
-    selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+    m_model->addNewGISASInstrument();
 }
 
 void InstrumentsQListView::onNewOffspec()
 {
-    QModelIndex idx = m_model->addNewOffspecInstrument();
-    selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+    m_model->addNewOffspecInstrument();
 }
 
 void InstrumentsQListView::onNewSpecular()
 {
-    QModelIndex idx = m_model->addNewSpecularInstrument();
-    selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+    m_model->addNewSpecularInstrument();
 }
 
 void InstrumentsQListView::onNewDepthprobe()
 {
-    QModelIndex idx = m_model->addNewDepthprobeInstrument();
-    selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+    m_model->addNewDepthprobeInstrument();
 }
 
 //! Removes currently selected instrument.
-- 
GitLab


From b964cb14bc5705b03da5994e606244fe0f8cdcbe Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:45:26 +0100
Subject: [PATCH 006/108] modernize InstrumentsQModel::data

---
 GUI/View/List/InstrumentsQModel.cpp | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 299de6199c1..b7ede26df12 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -31,13 +31,15 @@ int InstrumentsQModel::rowCount(const QModelIndex&) const
 
 QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 {
-    QVector<InstrumentItem*> instruments = gDoc->instruments()->instrumentItems();
-    if (!index.isValid() || index.row() >= instruments.size() || index.row() < 0)
+    const InstrumentsSet* instruments = gDoc->instruments();
+    if (!index.isValid())
+        return {};
+    size_t row = index.row();
+    if (row >= instruments->size())
         return {};
-    const InstrumentItem* item = instruments[index.row()];
-    ASSERT(item);
+    const InstrumentItem* t = instruments->at(row);
     if (role == Qt::DisplayRole)
-        return item->instrumentName();
+        return t->instrumentName();
     return {};
 }
 
-- 
GitLab


From 73ddc60f54963feec02e254a0785224d36b329ca Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:52:03 +0100
Subject: [PATCH 007/108] + const

---
 Base/Types/OwningVector.h           | 2 +-
 Base/Types/VectorWC.h               | 2 +-
 GUI/Model/Device/InstrumentsSet.cpp | 4 ++--
 GUI/Model/Device/InstrumentsSet.h   | 2 +-
 GUI/View/List/InstrumentsQModel.cpp | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Base/Types/OwningVector.h b/Base/Types/OwningVector.h
index ffdded1cfdd..f70d8870fd1 100644
--- a/Base/Types/OwningVector.h
+++ b/Base/Types/OwningVector.h
@@ -54,7 +54,7 @@ public:
         delete m_v[i];
         m_v[i] = e;
     }
-    void delete_element(T* e)
+    void delete_element(const T* e)
     {
         if (!e)
             return;
diff --git a/Base/Types/VectorWC.h b/Base/Types/VectorWC.h
index e2746542a29..980b4eb1128 100644
--- a/Base/Types/VectorWC.h
+++ b/Base/Types/VectorWC.h
@@ -41,7 +41,7 @@ public:
         super::replace_at(i, e);
         m_current_index = i;
     }
-    void delete_element(T* e)
+    void delete_element(const T* e)
     {
         super::delete_element(e);
         update_current();
diff --git a/GUI/Model/Device/InstrumentsSet.cpp b/GUI/Model/Device/InstrumentsSet.cpp
index 93e96e9db6d..543b1adc4ec 100644
--- a/GUI/Model/Device/InstrumentsSet.cpp
+++ b/GUI/Model/Device/InstrumentsSet.cpp
@@ -123,9 +123,9 @@ bool InstrumentsSet::instrumentExists(const QString& instrumentId) const
     return findInstrumentItemById(instrumentId) != nullptr;
 }
 
-void InstrumentsSet::removeInstrument(InstrumentItem* instrument)
+void InstrumentsSet::removeInstrument(const InstrumentItem* t)
 {
-    delete_element(instrument);
+    delete_element(t);
     emit instrumentAddedOrRemoved();
 }
 
diff --git a/GUI/Model/Device/InstrumentsSet.h b/GUI/Model/Device/InstrumentsSet.h
index 0bddf18bc4e..8d4ddca38af 100644
--- a/GUI/Model/Device/InstrumentsSet.h
+++ b/GUI/Model/Device/InstrumentsSet.h
@@ -29,7 +29,7 @@ public:
     ~InstrumentsSet();
 
     void addInstrumentItem(InstrumentItem* t);
-    void removeInstrument(InstrumentItem* instrument);
+    void removeInstrument(const InstrumentItem* t);
 
     void writeTo(QXmlStreamWriter* w) const;
     void readFrom(QXmlStreamReader* r);
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index b7ede26df12..ad2e2e23faa 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -85,7 +85,7 @@ QModelIndex InstrumentsQModel::addNewDepthprobeInstrument()
 void InstrumentsQModel::removeInstrument(const QModelIndex& index)
 {
     beginRemoveRows(QModelIndex(), index.row(), index.row());
-    InstrumentItem* instrument = instrumentItemForIndex(index);
+    const InstrumentItem* instrument = instrumentItemForIndex(index);
     gDoc->instrumentsModifier()->removeInstrument(instrument);
     endRemoveRows();
 }
-- 
GitLab


From e135b6e7e642623a3502f3335ff5570a6e54b55b Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:54:28 +0100
Subject: [PATCH 008/108] std var name

---
 GUI/View/List/InstrumentsQListView.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 66ced96e8f9..8a02d5e61cc 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -119,17 +119,17 @@ void InstrumentsQListView::onCopy()
 void InstrumentsQListView::onStoreInLibrary() const
 {
     QModelIndex idx = selectionModel()->selectedIndexes().front();
-    InstrumentItem* ii = m_model->instrumentItemForIndex(idx);
-    if (!ii)
+    InstrumentItem* t = m_model->instrumentItemForIndex(idx);
+    if (!t)
         return;
 
     QString fname = GUI::Dialog::fileSaveDialog("Save instrument", appSettings->xml_dir,
-                                                "XML Files (*.xml)", ii->instrumentName() + ".xml");
+                                                "XML Files (*.xml)", t->instrumentName() + ".xml");
     if (fname.isEmpty())
         return;
 
     try {
-        InstrumentXML::save(fname, ii);
+        InstrumentXML::save(fname, t);
     } catch (const std::exception& ex) {
         QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", QString(ex.what()),
                     QMessageBox::Ok, nullptr)
-- 
GitLab


From ec3195593def683c6bb824939ace55d5e3fec18d Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 08:59:42 +0100
Subject: [PATCH 009/108] standardize, + const

---
 GUI/Model/Device/InstrumentXML.cpp     | 18 +++++++++---------
 GUI/Model/Device/InstrumentXML.h       |  2 +-
 GUI/View/List/InstrumentsQListView.cpp |  3 +--
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/GUI/Model/Device/InstrumentXML.cpp b/GUI/Model/Device/InstrumentXML.cpp
index be370e2cf19..318f52484cc 100644
--- a/GUI/Model/Device/InstrumentXML.cpp
+++ b/GUI/Model/Device/InstrumentXML.cpp
@@ -28,7 +28,7 @@ const QString XML_VERSION_TAG = "version";
 
 } // namespace
 
-void InstrumentXML::save(const QString& fname, InstrumentItem* ii)
+void InstrumentXML::save(const QString& fname, const InstrumentItem* t)
 {
     QFile file(fname);
 
@@ -40,13 +40,13 @@ void InstrumentXML::save(const QString& fname, InstrumentItem* ii)
     w.writeStartDocument();
     w.writeStartElement(XML_ROOT_TAG);
 
-    const uint typeIndex = static_cast<uint>(InstrumentsCatalog::type(ii));
+    const uint typeIndex = static_cast<uint>(InstrumentsCatalog::type(t));
     XML::writeAttribute(&w, XML::Attrib::type, typeIndex);
     // The next line allows to see the name of item type in XML. May be skipped while reading.
     XML::writeAttribute(&w, XML::Attrib::name,
-                        InstrumentsCatalog::uiInfo(InstrumentsCatalog::type(ii)).menuEntry);
+                        InstrumentsCatalog::uiInfo(InstrumentsCatalog::type(t)).menuEntry);
 
-    ii->writeTo(&w);
+    t->writeTo(&w);
     w.writeEndElement();
     w.writeEndDocument();
 
@@ -55,7 +55,7 @@ void InstrumentXML::save(const QString& fname, InstrumentItem* ii)
 
 InstrumentItem* InstrumentXML::load(const QString& fname)
 {
-    InstrumentItem* ii = nullptr;
+    InstrumentItem* t = nullptr;
 
     QFile file(fname);
 
@@ -78,9 +78,9 @@ InstrumentItem* InstrumentXML::load(const QString& fname)
         throw std::runtime_error("Unsupported version of instrument element");
     const uint typeIndex = XML::readUIntAttribute(&r, XML::Attrib::type);
     const auto type = static_cast<typename InstrumentsCatalog::Type>(typeIndex);
-    ii = InstrumentsCatalog::create(type);
-    ASSERT(ii);
-    ii->readFrom(&r);
+    t = InstrumentsCatalog::create(type);
+    ASSERT(t);
+    t->readFrom(&r);
 
     if (r.hasError())
         throw std::runtime_error(QString("Error in instrument file, line %1, column %2: %3")
@@ -90,5 +90,5 @@ InstrumentItem* InstrumentXML::load(const QString& fname)
                                      .toStdString());
     file.close();
 
-    return ii;
+    return t;
 }
diff --git a/GUI/Model/Device/InstrumentXML.h b/GUI/Model/Device/InstrumentXML.h
index cb29bd4070d..631b28e99cc 100644
--- a/GUI/Model/Device/InstrumentXML.h
+++ b/GUI/Model/Device/InstrumentXML.h
@@ -21,7 +21,7 @@ class InstrumentItem;
 
 namespace InstrumentXML {
 
-void save(const QString& fname, InstrumentItem* ii);
+void save(const QString& fname, const InstrumentItem* t);
 InstrumentItem* load(const QString& fname);
 
 } // namespace InstrumentXML
diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 8a02d5e61cc..2f5918339e6 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -118,8 +118,7 @@ void InstrumentsQListView::onCopy()
 
 void InstrumentsQListView::onStoreInLibrary() const
 {
-    QModelIndex idx = selectionModel()->selectedIndexes().front();
-    InstrumentItem* t = m_model->instrumentItemForIndex(idx);
+    const InstrumentItem* t = gDoc->instruments()->currentItem();
     if (!t)
         return;
 
-- 
GitLab


From 52eef28f2ec5c21bfd92416f1a0ba0e0c496a75c Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 09:05:35 +0100
Subject: [PATCH 010/108] local var name 'set'

---
 GUI/View/List/InstrumentsQModel.cpp | 32 ++++++++++++++---------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index ad2e2e23faa..3b6079c1a16 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -31,13 +31,13 @@ int InstrumentsQModel::rowCount(const QModelIndex&) const
 
 QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 {
-    const InstrumentsSet* instruments = gDoc->instruments();
+    const InstrumentsSet* set = gDoc->instruments();
     if (!index.isValid())
         return {};
     size_t row = index.row();
-    if (row >= instruments->size())
+    if (row >= set->size())
         return {};
-    const InstrumentItem* t = instruments->at(row);
+    const InstrumentItem* t = set->at(row);
     if (role == Qt::DisplayRole)
         return t->instrumentName();
     return {};
@@ -48,9 +48,9 @@ InstrumentItem* InstrumentsQModel::instrumentItemForIndex(const QModelIndex& ind
     if (!index.isValid())
         return nullptr;
 
-    QVector<InstrumentItem*> instruments = gDoc->instruments()->instrumentItems();
-    if (index.row() >= 0 && index.row() < instruments.size())
-        return instruments[index.row()];
+    QVector<InstrumentItem*> set = gDoc->instruments()->instrumentItems();
+    if (index.row() >= 0 && index.row() < set.size())
+        return set[index.row()];
     return nullptr;
 }
 
@@ -100,14 +100,14 @@ QModelIndex InstrumentsQModel::copyInstrument(const QModelIndex& source)
 
 QModelIndex InstrumentsQModel::copyInstrument(const InstrumentItem* source)
 {
-    InstrumentsSet* instruments = gDoc->instrumentsModifier();
-    const QString copyName = instruments->suggestInstrumentName(source->instrumentName());
-    const int row = instruments->instrumentItems().size();
+    InstrumentsSet* set = gDoc->instrumentsModifier();
+    const QString copyName = set->suggestInstrumentName(source->instrumentName());
+    const int row = set->instrumentItems().size();
 
     beginInsertRows({}, row, row);
-    InstrumentItem* copy = instruments->insertItemCopy(*source);
+    InstrumentItem* copy = set->insertItemCopy(*source);
     copy->setInstrumentName(copyName);
-    emit instruments->instrumentAddedOrRemoved();
+    emit set->instrumentAddedOrRemoved();
     endInsertRows();
 
     return createIndex(row, 0);
@@ -115,11 +115,11 @@ QModelIndex InstrumentsQModel::copyInstrument(const InstrumentItem* source)
 
 QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 {
-    InstrumentsSet* instruments = gDoc->instrumentsModifier();
-    const int row = instruments->instrumentItems().size();
+    InstrumentsSet* set = gDoc->instrumentsModifier();
+    const int row = set->instrumentItems().size();
 
     beginInsertRows({}, row, row);
-    instruments->addInstrumentItem(t);
+    set->addInstrumentItem(t);
     endInsertRows();
 
     return createIndex(row, 0);
@@ -127,7 +127,7 @@ QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 
 void InstrumentsQModel::onInstrumentNameChanged(const InstrumentItem* instrument)
 {
-    const auto instruments = gDoc->instruments()->instrumentItems();
-    if (const auto row = instruments.indexOf(instrument); row != -1)
+    const auto set = gDoc->instruments()->instrumentItems();
+    if (const auto row = set.indexOf(instrument); row != -1)
         emit dataChanged(index(row, 0), index(row, 0));
 }
-- 
GitLab


From e8114b124253196f613d84f9242be47c1f2afa64 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 09:13:15 +0100
Subject: [PATCH 011/108] InstrumentsQModel::copyInstrument() now directly
 operating on current instrument

---
 GUI/View/List/InstrumentsQListView.cpp | 34 +++++---------------------
 GUI/View/List/InstrumentsQListView.h   |  3 ---
 GUI/View/List/InstrumentsQModel.cpp    | 30 ++++++++++-------------
 GUI/View/List/InstrumentsQModel.h      |  8 +++---
 4 files changed, 22 insertions(+), 53 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 2f5918339e6..583c73fbc49 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -49,10 +49,11 @@ InstrumentsQListView::InstrumentsQListView()
     connect(gActions->new_depthprobe_instrument, &QAction::triggered, this,
             &InstrumentsQListView::onNewDepthprobe);
 
-    connect(gActions->remove_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onRemove);
+    connect(gActions->remove_instrument, &QAction::triggered, m_model,
+            &InstrumentsQModel::removeInstrument);
 
-    connect(gActions->copy_instrument, &QAction::triggered, this, &InstrumentsQListView::onCopy);
+    connect(gActions->copy_instrument, &QAction::triggered, m_model,
+            &InstrumentsQModel::copyInstrument);
 
     connect(gActions->store_in_library_instrument, &QAction::triggered, this,
             &InstrumentsQListView::onStoreInLibrary);
@@ -95,27 +96,6 @@ void InstrumentsQListView::onNewDepthprobe()
     m_model->addNewDepthprobeInstrument();
 }
 
-//! Removes currently selected instrument.
-void InstrumentsQListView::onRemove()
-{
-    QModelIndexList indexes = selectionModel()->selectedIndexes();
-    if (!indexes.empty()) {
-        m_model->removeInstrument(indexes.front());
-
-        ensureItemSelected();
-    }
-}
-
-//! Makes a copy of the currently selected instrument.
-void InstrumentsQListView::onCopy()
-{
-    QModelIndexList indexes = selectionModel()->selectedIndexes();
-    if (!indexes.empty()) {
-        QModelIndex idx = m_model->copyInstrument(indexes.front());
-        selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
-    }
-}
-
 void InstrumentsQListView::onStoreInLibrary() const
 {
     const InstrumentItem* t = gDoc->instruments()->currentItem();
@@ -144,10 +124,8 @@ void InstrumentsQListView::onLoadFromLibrary()
         return;
 
     try {
-        if (InstrumentItem* ii = InstrumentXML::load(fname)) {
-            QModelIndex idx = m_model->copyInstrument(ii);
-            selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
-        }
+        if (InstrumentItem* t = InstrumentXML::load(fname))
+            m_model->pushInstrument(t);
     } catch (const std::exception& ex) {
         QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", QString(ex.what()),
                     QMessageBox::Ok, nullptr)
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 064b50b3d28..0274ca1f537 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -39,9 +39,6 @@ private slots:
     void onNewSpecular();
     void onNewDepthprobe();
 
-    void onRemove();
-    void onCopy();
-
     void onStoreInLibrary() const;
     void onLoadFromLibrary();
 
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 3b6079c1a16..0ff2c55d03b 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -82,31 +82,27 @@ QModelIndex InstrumentsQModel::addNewDepthprobeInstrument()
     return pushInstrument(t);
 }
 
-void InstrumentsQModel::removeInstrument(const QModelIndex& index)
+void InstrumentsQModel::removeInstrument()
 {
-    beginRemoveRows(QModelIndex(), index.row(), index.row());
-    const InstrumentItem* instrument = instrumentItemForIndex(index);
-    gDoc->instrumentsModifier()->removeInstrument(instrument);
-    endRemoveRows();
-}
-
-QModelIndex InstrumentsQModel::copyInstrument(const QModelIndex& source)
-{
-    const InstrumentItem* srcInstr = instrumentItemForIndex(source);
-    ASSERT(srcInstr);
+    InstrumentsSet* set = gDoc->instrumentsModifier();
+    const InstrumentItem* t = set->currentItem();
 
-    return copyInstrument(srcInstr);
+    const int row = set->index_of(t);
+    beginInsertRows({}, row, row);
+    set->removeInstrument(t);
+    endRemoveRows();
 }
 
-QModelIndex InstrumentsQModel::copyInstrument(const InstrumentItem* source)
+QModelIndex InstrumentsQModel::copyInstrument() // TODO implement using pushInstrument
 {
     InstrumentsSet* set = gDoc->instrumentsModifier();
-    const QString copyName = set->suggestInstrumentName(source->instrumentName());
-    const int row = set->instrumentItems().size();
+    const InstrumentItem* t = set->currentItem();
+    const QString copyName = set->suggestInstrumentName(t->instrumentName());
 
+    const int row = set->instrumentItems().size();
     beginInsertRows({}, row, row);
-    InstrumentItem* copy = set->insertItemCopy(*source);
-    copy->setInstrumentName(copyName);
+    InstrumentItem* t2 = set->insertItemCopy(*t);
+    t2->setInstrumentName(copyName);
     emit set->instrumentAddedOrRemoved();
     endInsertRows();
 
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index fd8e4acbebe..f54c4767ad5 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -36,13 +36,11 @@ public:
     QModelIndex addNewSpecularInstrument();
     QModelIndex addNewDepthprobeInstrument();
 
-    void removeInstrument(const QModelIndex& index);
-
-    QModelIndex copyInstrument(const QModelIndex& source);
-    QModelIndex copyInstrument(const InstrumentItem* source);
+    void removeInstrument();
+    QModelIndex copyInstrument();
+    QModelIndex pushInstrument(InstrumentItem*);
 
 private:
-    QModelIndex pushInstrument(InstrumentItem*);
     void onInstrumentNameChanged(const InstrumentItem* instrument);
 };
 
-- 
GitLab


From 1845a8880ecfa5c43bb6bd57ed17aac1898f3c0c Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 09:20:14 +0100
Subject: [PATCH 012/108] rm unused

---
 GUI/View/List/InstrumentsQModel.cpp | 11 -----------
 GUI/View/List/InstrumentsQModel.h   |  2 --
 2 files changed, 13 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 0ff2c55d03b..6722c1cb01e 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -43,17 +43,6 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     return {};
 }
 
-InstrumentItem* InstrumentsQModel::instrumentItemForIndex(const QModelIndex& index) const
-{
-    if (!index.isValid())
-        return nullptr;
-
-    QVector<InstrumentItem*> set = gDoc->instruments()->instrumentItems();
-    if (index.row() >= 0 && index.row() < set.size())
-        return set[index.row()];
-    return nullptr;
-}
-
 QModelIndex InstrumentsQModel::addNewGISASInstrument()
 {
     auto* t = new GISASInstrumentItem;
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index f54c4767ad5..e9f0d4961fb 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -29,8 +29,6 @@ public:
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 
-    InstrumentItem* instrumentItemForIndex(const QModelIndex& index) const;
-
     QModelIndex addNewGISASInstrument();
     QModelIndex addNewOffspecInstrument();
     QModelIndex addNewSpecularInstrument();
-- 
GitLab


From eb5c32fc641c51005aa41dc4ea6c45be221e5504 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 09:28:27 +0100
Subject: [PATCH 013/108] InstrumentsQListView cleared all of selection

---
 GUI/View/List/InstrumentsQListView.cpp | 46 +++++---------------------
 GUI/View/List/InstrumentsQListView.h   |  6 ----
 2 files changed, 9 insertions(+), 43 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 583c73fbc49..85cdf2061d3 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -37,17 +37,17 @@ InstrumentsQListView::InstrumentsQListView()
     setModel(m_model);
     setItemDelegate(new ListItemDelegate(this));
 
-    connect(gActions->new_gisas_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onNewGisas);
+    connect(gActions->new_gisas_instrument, &QAction::triggered, m_model,
+            &InstrumentsQModel::addNewGISASInstrument);
 
-    connect(gActions->new_offspec_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onNewOffspec);
+    connect(gActions->new_offspec_instrument, &QAction::triggered, m_model,
+            &InstrumentsQModel::addNewOffspecInstrument);
 
-    connect(gActions->new_specular_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onNewSpecular);
+    connect(gActions->new_specular_instrument, &QAction::triggered, m_model,
+            &InstrumentsQModel::addNewSpecularInstrument);
 
-    connect(gActions->new_depthprobe_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onNewDepthprobe);
+    connect(gActions->new_depthprobe_instrument, &QAction::triggered, m_model,
+            &InstrumentsQModel::addNewDepthprobeInstrument);
 
     connect(gActions->remove_instrument, &QAction::triggered, m_model,
             &InstrumentsQModel::removeInstrument);
@@ -76,26 +76,6 @@ QSize InstrumentsQListView::minimumSizeHint() const
     return {96, 200};
 }
 
-void InstrumentsQListView::onNewGisas()
-{
-    m_model->addNewGISASInstrument();
-}
-
-void InstrumentsQListView::onNewOffspec()
-{
-    m_model->addNewOffspecInstrument();
-}
-
-void InstrumentsQListView::onNewSpecular()
-{
-    m_model->addNewSpecularInstrument();
-}
-
-void InstrumentsQListView::onNewDepthprobe()
-{
-    m_model->addNewDepthprobeInstrument();
-}
-
 void InstrumentsQListView::onStoreInLibrary() const
 {
     const InstrumentItem* t = gDoc->instruments()->currentItem();
@@ -135,16 +115,8 @@ void InstrumentsQListView::onLoadFromLibrary()
 
 void InstrumentsQListView::updateActions()
 {
-    bool enabled = selectionModel()->hasSelection();
+    bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
     gActions->remove_instrument->setEnabled(enabled);
     gActions->copy_instrument->setEnabled(enabled);
     gActions->store_in_library_instrument->setEnabled(enabled);
 }
-
-void InstrumentsQListView::ensureItemSelected()
-{
-    if (!selectionModel()->hasSelection() && m_model->rowCount()) {
-        QModelIndex last = m_model->index(m_model->rowCount() - 1, 0, QModelIndex());
-        selectionModel()->select(last, QItemSelectionModel::ClearAndSelect);
-    }
-}
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 0274ca1f537..53b6400266a 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -34,17 +34,11 @@ signals:
     void instrumentSelected(InstrumentItem* instrument);
 
 private slots:
-    void onNewGisas();
-    void onNewOffspec();
-    void onNewSpecular();
-    void onNewDepthprobe();
-
     void onStoreInLibrary() const;
     void onLoadFromLibrary();
 
 private:
     void updateActions();
-    void ensureItemSelected();
 
     InstrumentsQModel* m_model;
 };
-- 
GitLab


From 683a80eae6ce2878d997011c0f8152289989a007 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 09:44:59 +0100
Subject: [PATCH 014/108] implicit cast

---
 GUI/View/List/InstrumentsQListView.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 85cdf2061d3..f315c1069df 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -25,7 +25,6 @@
 #include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QMessageBox>
-#include <QVBoxLayout>
 
 InstrumentsQListView::InstrumentsQListView()
     : m_model(new InstrumentsQModel)
@@ -90,7 +89,7 @@ void InstrumentsQListView::onStoreInLibrary() const
     try {
         InstrumentXML::save(fname, t);
     } catch (const std::exception& ex) {
-        QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", QString(ex.what()),
+        QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", ex.what(),
                     QMessageBox::Ok, nullptr)
             .exec();
     }
@@ -107,7 +106,7 @@ void InstrumentsQListView::onLoadFromLibrary()
         if (InstrumentItem* t = InstrumentXML::load(fname))
             m_model->pushInstrument(t);
     } catch (const std::exception& ex) {
-        QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", QString(ex.what()),
+        QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", ex.what(),
                     QMessageBox::Ok, nullptr)
             .exec();
     }
-- 
GitLab


From c25e5fdf1a2c2778e1147590d32d7c6803be00f8 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 13:08:58 +0100
Subject: [PATCH 015/108] + InstrumentsSet::onCurrentChanged; restore instr
 editor

---
 Base/Types/VectorWC.h                | 14 ++++++++++++--
 GUI/Model/Device/InstrumentsSet.h    |  5 +++++
 GUI/View/List/InstrumentsQListView.h |  3 ---
 GUI/View/Views/InstrumentView.cpp    |  2 +-
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/Base/Types/VectorWC.h b/Base/Types/VectorWC.h
index 980b4eb1128..e7abb6409de 100644
--- a/Base/Types/VectorWC.h
+++ b/Base/Types/VectorWC.h
@@ -30,16 +30,19 @@ public:
     {
         super::push_back(e);
         m_current_index = super::size() - 1;
+        onCurrentChanged();
     }
     void insert_at(size_t i, T* e)
     {
         super::insert_at(i, e);
         m_current_index = i;
+        onCurrentChanged();
     }
     void replace_at(size_t i, T* e)
     {
         super::replace_at(i, e);
         m_current_index = i;
+        onCurrentChanged();
     }
     void delete_element(const T* e)
     {
@@ -80,7 +83,10 @@ public:
     void setCurrentIndex(size_t i)
     {
         ASSERT(i < super::size() || i == size_t(-1));
-        m_current_index = i;
+        if (i != m_current_index) {
+            m_current_index = i;
+            onCurrentChanged();
+        }
     }
     size_t currentIndex() const { return m_current_index; }
     const T* currentItem() const
@@ -95,11 +101,15 @@ public:
 private:
     void update_current()
     {
-        if (m_current_index == super::size())
+        if (m_current_index == super::size()) {
             m_current_index = super::size() - 1;
+            onCurrentChanged();
+        }
     }
 
     size_t m_current_index = -1;
+
+    virtual void onCurrentChanged() const {}
 };
 
 #endif // BORNAGAIN_BASE_TYPES_VECTORWC_H
diff --git a/GUI/Model/Device/InstrumentsSet.h b/GUI/Model/Device/InstrumentsSet.h
index 8d4ddca38af..1c84da9b6dd 100644
--- a/GUI/Model/Device/InstrumentsSet.h
+++ b/GUI/Model/Device/InstrumentsSet.h
@@ -61,6 +61,11 @@ signals:
     //! Signals name change of the given instrument.
     //! In addition to this, instrumentChanged() will be emitted as well.
     void instrumentNameChanged(const InstrumentItem* instrument) const;
+
+    void instrumentSelected() const;
+
+private:
+    void onCurrentChanged() const override { emit instrumentSelected(); }
 };
 
 #endif // BORNAGAIN_GUI_MODEL_DEVICE_INSTRUMENTSSET_H
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 53b6400266a..3ab58956ad7 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -30,9 +30,6 @@ public:
     QSize sizeHint() const override;
     QSize minimumSizeHint() const override;
 
-signals:
-    void instrumentSelected(InstrumentItem* instrument);
-
 private slots:
     void onStoreInLibrary() const;
     void onLoadFromLibrary();
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index ae27639812d..8fbd499015e 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -68,7 +68,7 @@ InstrumentView::InstrumentView()
 
     //... Finalize
 
-    connect(m_listing, &InstrumentsQListView::instrumentSelected, this,
+    connect(gDoc->instruments(), &InstrumentsSet::instrumentSelected, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
     // Initial state
-- 
GitLab


From 2728fcbd57f13ba6646f4ead3bbac6c5243c5dbe Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Sun, 18 Feb 2024 13:27:41 +0100
Subject: [PATCH 016/108] rewire updates

---
 Base/Types/VectorWC.h                       | 14 +---
 GUI/Model/Device/InstrumentItems.cpp        |  2 +
 GUI/Model/Device/InstrumentItems.h          |  2 +-
 GUI/Model/Device/InstrumentsSet.cpp         | 30 +-------
 GUI/Model/Device/InstrumentsSet.h           | 26 +------
 GUI/Model/Project/LinkInstrumentManager.cpp | 11 +--
 GUI/Model/Project/LinkInstrumentManager.h   |  2 +-
 GUI/Model/Project/ProjectDocument.cpp       |  4 +-
 GUI/View/Data/DatafileEditor.cpp            |  5 +-
 GUI/View/Device/ScanEditor.cpp              |  4 +-
 GUI/View/List/InstrumentsQListView.cpp      | 31 +++++----
 GUI/View/List/InstrumentsQListView.h        |  2 -
 GUI/View/List/InstrumentsQModel.cpp         | 51 ++++++--------
 GUI/View/List/InstrumentsQModel.h           |  3 -
 GUI/View/Manager/ProjectManager.cpp         |  2 +-
 GUI/View/Views/InstrumentView.cpp           | 73 ++++---------------
 GUI/View/Views/InstrumentView.h             | 16 +----
 GUI/styles/Base.stylesheet                  | 30 +-------
 Tests/Unit/GUI/TestAutosaveController.cpp   | 62 +++++++++--------
 Tests/Unit/GUI/TestDatafilesModel.cpp       |  6 +-
 Tests/Unit/GUI/TestInstrumentItems.cpp      | 77 ---------------------
 Tests/Unit/GUI/TestInstrumentsSet.cpp       | 72 +++++++++++++++++++
 Tests/Unit/GUI/TestLinkInstrument.cpp       | 28 ++++----
 Tests/Unit/GUI/TestProjectDocument.cpp      | 67 +++++++++---------
 24 files changed, 235 insertions(+), 385 deletions(-)
 delete mode 100644 Tests/Unit/GUI/TestInstrumentItems.cpp
 create mode 100644 Tests/Unit/GUI/TestInstrumentsSet.cpp

diff --git a/Base/Types/VectorWC.h b/Base/Types/VectorWC.h
index e7abb6409de..c193c1cca3e 100644
--- a/Base/Types/VectorWC.h
+++ b/Base/Types/VectorWC.h
@@ -19,6 +19,7 @@
 #define BORNAGAIN_BASE_TYPES_VECTORWC_H
 
 #include "Base/Types/OwningVector.h"
+#include "Base/Util/Assert.h"
 
 //! An OwningVector with a current index.
 
@@ -30,19 +31,16 @@ public:
     {
         super::push_back(e);
         m_current_index = super::size() - 1;
-        onCurrentChanged();
     }
     void insert_at(size_t i, T* e)
     {
         super::insert_at(i, e);
         m_current_index = i;
-        onCurrentChanged();
     }
     void replace_at(size_t i, T* e)
     {
         super::replace_at(i, e);
         m_current_index = i;
-        onCurrentChanged();
     }
     void delete_element(const T* e)
     {
@@ -83,10 +81,8 @@ public:
     void setCurrentIndex(size_t i)
     {
         ASSERT(i < super::size() || i == size_t(-1));
-        if (i != m_current_index) {
+        if (i != m_current_index)
             m_current_index = i;
-            onCurrentChanged();
-        }
     }
     size_t currentIndex() const { return m_current_index; }
     const T* currentItem() const
@@ -101,15 +97,11 @@ public:
 private:
     void update_current()
     {
-        if (m_current_index == super::size()) {
+        if (m_current_index == super::size())
             m_current_index = super::size() - 1;
-            onCurrentChanged();
-        }
     }
 
     size_t m_current_index = -1;
-
-    virtual void onCurrentChanged() const {}
 };
 
 #endif // BORNAGAIN_BASE_TYPES_VECTORWC_H
diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index f763826645c..f7e45aa69ac 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -107,6 +107,8 @@ InstrumentItem::InstrumentItem()
     m_background.initWithArgs("Background", "", BackgroundItemCatalog::Type::Constant);
 }
 
+InstrumentItem::~InstrumentItem() = default;
+
 InstrumentItem* InstrumentItem::createItemCopy() const
 {
     const auto type = InstrumentsCatalog::type(this);
diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h
index 9b417351366..b9662308e95 100644
--- a/GUI/Model/Device/InstrumentItems.h
+++ b/GUI/Model/Device/InstrumentItems.h
@@ -39,7 +39,7 @@ class ScanItem;
 class InstrumentItem {
 public:
     InstrumentItem();
-    virtual ~InstrumentItem() = default;
+    virtual ~InstrumentItem();
 
     //! The type as how to show it on the UI. Do not use for type checking or similar!
     virtual QString instrumentType() const = 0;
diff --git a/GUI/Model/Device/InstrumentsSet.cpp b/GUI/Model/Device/InstrumentsSet.cpp
index 543b1adc4ec..4ec4702b227 100644
--- a/GUI/Model/Device/InstrumentsSet.cpp
+++ b/GUI/Model/Device/InstrumentsSet.cpp
@@ -17,7 +17,6 @@
 #include "GUI/Model/Device/InstrumentItems.h"
 #include "GUI/Model/Device/InstrumentsCatalog.h"
 #include "GUI/Support/Util/String.h"
-#include <QUuid>
 
 namespace {
 namespace Tag {
@@ -75,20 +74,6 @@ void InstrumentsSet::readFrom(QXmlStreamReader* r)
     }
 }
 
-void InstrumentsSet::addInstrumentItem(InstrumentItem* t)
-{
-    push_back(t);
-    emit instrumentAddedOrRemoved();
-}
-
-InstrumentItem* InstrumentsSet::insertItemCopy(const InstrumentItem& source)
-{
-    InstrumentItem* copy = source.createItemCopy();
-    copy->setId(QUuid::createUuid().toString());
-    push_back(copy);
-    return copy;
-}
-
 QVector<InstrumentItem*> InstrumentsSet::instrumentItems() const
 {
     QVector<InstrumentItem*> output;
@@ -105,11 +90,6 @@ QStringList InstrumentsSet::instrumentNames() const
     return existingNames;
 }
 
-QString InstrumentsSet::suggestInstrumentName(const QString& baseName) const
-{
-    return GUI::Util::String::suggestName(instrumentNames(), baseName);
-}
-
 InstrumentItem* InstrumentsSet::findInstrumentItemById(const QString& instrumentId) const
 {
     for (auto* instrument : instrumentItems())
@@ -123,17 +103,11 @@ bool InstrumentsSet::instrumentExists(const QString& instrumentId) const
     return findInstrumentItemById(instrumentId) != nullptr;
 }
 
-void InstrumentsSet::removeInstrument(const InstrumentItem* t)
-{
-    delete_element(t);
-    emit instrumentAddedOrRemoved();
-}
-
 void InstrumentsSet::setInstrumentName(InstrumentItem* instrument, const QString& name)
 {
     if (instrument->instrumentName() != name) {
         instrument->setInstrumentName(name);
-        emit instrumentNameChanged(instrument);
-        emit instrumentChanged(instrument);
+        emit currentModified();
+        emit setChanged();
     }
 }
diff --git a/GUI/Model/Device/InstrumentsSet.h b/GUI/Model/Device/InstrumentsSet.h
index 1c84da9b6dd..059eda1af11 100644
--- a/GUI/Model/Device/InstrumentsSet.h
+++ b/GUI/Model/Device/InstrumentsSet.h
@@ -28,44 +28,22 @@ public:
     InstrumentsSet();
     ~InstrumentsSet();
 
-    void addInstrumentItem(InstrumentItem* t);
-    void removeInstrument(const InstrumentItem* t);
-
     void writeTo(QXmlStreamWriter* w) const;
     void readFrom(QXmlStreamReader* r);
 
-    //! Inserts a deep copy (also of any non XML data in a pointwise axis)
-    //! The id will not be copied, but a new unique one will be created
-    //! Returns the newly created instrument.
-    InstrumentItem* insertItemCopy(const InstrumentItem& source);
-
     QVector<InstrumentItem*> instrumentItems() const;
 
     InstrumentItem* findInstrumentItemById(const QString& instrumentId) const;
     bool instrumentExists(const QString& instrumentId) const;
 
-    QString suggestInstrumentName(const QString& baseName) const;
     QStringList instrumentNames() const;
 
     //! Set an instrument's name and emit the respective signal.
     void setInstrumentName(InstrumentItem* instrument, const QString& name);
 
 signals:
-    //! Signals a change in the list of instruments.
-    void instrumentAddedOrRemoved() const;
-
-    //! Signals any change in the settings of the given instrument.
-    //! Signals also a name change, which has its own additional signal
-    void instrumentChanged(const InstrumentItem* instrument) const;
-
-    //! Signals name change of the given instrument.
-    //! In addition to this, instrumentChanged() will be emitted as well.
-    void instrumentNameChanged(const InstrumentItem* instrument) const;
-
-    void instrumentSelected() const;
-
-private:
-    void onCurrentChanged() const override { emit instrumentSelected(); }
+    void setChanged() const;
+    void currentModified() const;
 };
 
 #endif // BORNAGAIN_GUI_MODEL_DEVICE_INSTRUMENTSSET_H
diff --git a/GUI/Model/Project/LinkInstrumentManager.cpp b/GUI/Model/Project/LinkInstrumentManager.cpp
index 97e52149b0e..eb2bb5deefb 100644
--- a/GUI/Model/Project/LinkInstrumentManager.cpp
+++ b/GUI/Model/Project/LinkInstrumentManager.cpp
@@ -80,10 +80,10 @@ void warn(QWidget* parent, const QString& text)
 LinkInstrumentManager::LinkInstrumentManager(ProjectDocument* document)
     : m_doc(document)
 {
-    connect(m_doc->instruments(), &InstrumentsSet::instrumentAddedOrRemoved, this,
+    connect(m_doc->instruments(), &InstrumentsSet::setChanged, this,
             &LinkInstrumentManager::onInstrumentAddedOrRemoved);
 
-    connect(m_doc->instruments(), &InstrumentsSet::instrumentChanged, this,
+    connect(m_doc->instruments(), &InstrumentsSet::currentModified, this,
             &LinkInstrumentManager::onInstrumentChanged);
 }
 
@@ -114,12 +114,15 @@ bool LinkInstrumentManager::canLinkDataToInstrument(const DatafileItem* dfi,
         return false;
 
     instrumentItem->updateToRealData(dfi);
-    emit m_doc->instruments()->instrumentChanged(instrumentItem);
+    emit m_doc->instruments()->currentModified();
     return true;
 }
 
-void LinkInstrumentManager::onInstrumentChanged(const InstrumentItem* instrument)
+void LinkInstrumentManager::onInstrumentChanged()
 {
+    ASSERT(gDoc);
+    ASSERT(gDoc->instruments());
+    const InstrumentItem* instrument = gDoc->instruments()->currentItem();
     // Run through all DatafileItem and refresh linking to match possible change in detector
     // axes definition.
     for (DatafileItem* dfi : *m_doc->datafilesModifier())
diff --git a/GUI/Model/Project/LinkInstrumentManager.h b/GUI/Model/Project/LinkInstrumentManager.h
index 7be979aecd0..14712808350 100644
--- a/GUI/Model/Project/LinkInstrumentManager.h
+++ b/GUI/Model/Project/LinkInstrumentManager.h
@@ -42,7 +42,7 @@ signals:
     void linkToInstrumentChanged(const DatafileItem* dfi);
 
 private:
-    void onInstrumentChanged(const InstrumentItem* instrument);
+    void onInstrumentChanged();
     void onInstrumentAddedOrRemoved();
 
     ProjectDocument* m_doc;
diff --git a/GUI/Model/Project/ProjectDocument.cpp b/GUI/Model/Project/ProjectDocument.cpp
index 2a276c31e37..95d47cc8dc2 100644
--- a/GUI/Model/Project/ProjectDocument.cpp
+++ b/GUI/Model/Project/ProjectDocument.cpp
@@ -65,9 +65,9 @@ ProjectDocument::ProjectDocument()
     , m_jobs(std::make_unique<JobsSet>())
     , m_last_view_active(GUI::ID::ViewId::Instrument)
 {
-    connect(m_instruments.get(), &InstrumentsSet::instrumentAddedOrRemoved, this,
+    connect(m_instruments.get(), &InstrumentsSet::setChanged, this,
             &ProjectDocument::onModelChanged);
-    connect(m_instruments.get(), &InstrumentsSet::instrumentChanged, this,
+    connect(m_instruments.get(), &InstrumentsSet::currentModified, this,
             &ProjectDocument::onModelChanged);
 
     m_link_manager = std::make_unique<LinkInstrumentManager>(this);
diff --git a/GUI/View/Data/DatafileEditor.cpp b/GUI/View/Data/DatafileEditor.cpp
index 78ce608c68b..6b3031de105 100644
--- a/GUI/View/Data/DatafileEditor.cpp
+++ b/GUI/View/Data/DatafileEditor.cpp
@@ -47,10 +47,7 @@ DatafileEditor::DatafileEditor()
     connect(m_instrument_combo, &QComboBox::currentIndexChanged, this,
             &DatafileEditor::onInstrumentComboIndexChanged);
 
-    connect(gDoc->instruments(), &InstrumentsSet::instrumentAddedOrRemoved, this,
-            &DatafileEditor::updateInstrumentComboEntries);
-
-    connect(gDoc->instruments(), &InstrumentsSet::instrumentNameChanged, this,
+    connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &DatafileEditor::updateInstrumentComboEntries);
 
     connect(gDoc->linkInstrumentManager(), &LinkInstrumentManager::linkToInstrumentChanged, this,
diff --git a/GUI/View/Device/ScanEditor.cpp b/GUI/View/Device/ScanEditor.cpp
index f4cdda6c43a..0da52bf7e05 100644
--- a/GUI/View/Device/ScanEditor.cpp
+++ b/GUI/View/Device/ScanEditor.cpp
@@ -71,12 +71,12 @@ ScanEditor::ScanEditor(QWidget* parent, InstrumentItem* instr_item, ScanItem* it
                         pw->updateAxIndicators(frame);
                     }
                 }
-                emit gDoc->instruments()->instrumentChanged(instr_item);
+                emit gDoc->instruments()->currentModified();
                 emit inclinationEditor->updateIndicators();
             });
 
     connect(inclinationEditor, &AlphaScanEditor::dataChanged, [instr_item, wavelengthEditor] {
-        gDoc->instruments()->instrumentChanged(instr_item);
+        emit gDoc->instruments()->currentModified();
         emit wavelengthEditor->updateData();
     });
 
diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index f315c1069df..1583a854b4f 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -25,13 +25,14 @@
 #include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QMessageBox>
+#include <QThread>
 
 InstrumentsQListView::InstrumentsQListView()
     : m_model(new InstrumentsQModel)
 {
     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
     setMovement(QListView::Static);
-    setSelectionMode(QAbstractItemView::SingleSelection);
+    setSelectionMode(QAbstractItemView::NoSelection);
 
     setModel(m_model);
     setItemDelegate(new ListItemDelegate(this));
@@ -60,9 +61,17 @@ InstrumentsQListView::InstrumentsQListView()
     connect(gActions->load_from_library_instrument, &QAction::triggered, this,
             &InstrumentsQListView::onLoadFromLibrary);
 
-    setContextMenuPolicy(Qt::ActionsContextMenu);
+    connect(this, &QListView::clicked, [](const QModelIndex& qi) {
+        gDoc->instrumentsModifier()->setCurrentIndex(qi.row());
+        emit gDoc->instruments()->setChanged();
+    });
+
+    connect(gDoc->instruments(), &InstrumentsSet::setChanged, [this] {
+        setCurrentIndex(m_model->index(gDoc->instruments()->currentIndex(), 0));
+        repaint();
+    });
 
-    updateActions();
+    setContextMenuPolicy(Qt::ActionsContextMenu);
 }
 
 QSize InstrumentsQListView::sizeHint() const
@@ -89,8 +98,8 @@ void InstrumentsQListView::onStoreInLibrary() const
     try {
         InstrumentXML::save(fname, t);
     } catch (const std::exception& ex) {
-        QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", ex.what(),
-                    QMessageBox::Ok, nullptr)
+        QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", ex.what(), QMessageBox::Ok,
+                    nullptr)
             .exec();
     }
 }
@@ -106,16 +115,8 @@ void InstrumentsQListView::onLoadFromLibrary()
         if (InstrumentItem* t = InstrumentXML::load(fname))
             m_model->pushInstrument(t);
     } catch (const std::exception& ex) {
-        QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", ex.what(),
-                    QMessageBox::Ok, nullptr)
+        QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", ex.what(), QMessageBox::Ok,
+                    nullptr)
             .exec();
     }
 }
-
-void InstrumentsQListView::updateActions()
-{
-    bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
-    gActions->remove_instrument->setEnabled(enabled);
-    gActions->copy_instrument->setEnabled(enabled);
-    gActions->store_in_library_instrument->setEnabled(enabled);
-}
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 3ab58956ad7..51ede215814 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -35,8 +35,6 @@ private slots:
     void onLoadFromLibrary();
 
 private:
-    void updateActions();
-
     InstrumentsQModel* m_model;
 };
 
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 6722c1cb01e..ae04aad7e7d 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -17,12 +17,10 @@
 #include "GUI/Model/Device/InstrumentItems.h"
 #include "GUI/Model/Device/InstrumentsSet.h"
 #include "GUI/Model/Project/ProjectDocument.h"
+#include <QColor>
+#include <QUuid>
 
-InstrumentsQModel::InstrumentsQModel()
-{
-    connect(gDoc->instruments(), &InstrumentsSet::instrumentNameChanged, this,
-            &InstrumentsQModel::onInstrumentNameChanged);
-}
+InstrumentsQModel::InstrumentsQModel() {}
 
 int InstrumentsQModel::rowCount(const QModelIndex&) const
 {
@@ -38,9 +36,15 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     if (row >= set->size())
         return {};
     const InstrumentItem* t = set->at(row);
-    if (role == Qt::DisplayRole)
+
+    switch (role) {
+    case Qt::DisplayRole:
         return t->instrumentName();
-    return {};
+    case Qt::BackgroundRole:
+        return row == set->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
+    default:
+        return {};
+    }
 }
 
 QModelIndex InstrumentsQModel::addNewGISASInstrument()
@@ -77,42 +81,31 @@ void InstrumentsQModel::removeInstrument()
     const InstrumentItem* t = set->currentItem();
 
     const int row = set->index_of(t);
-    beginInsertRows({}, row, row);
-    set->removeInstrument(t);
+    beginRemoveRows({}, row, row);
+    set->delete_element(t);
     endRemoveRows();
+
+    emit set->setChanged();
 }
 
-QModelIndex InstrumentsQModel::copyInstrument() // TODO implement using pushInstrument
+QModelIndex InstrumentsQModel::copyInstrument()
 {
     InstrumentsSet* set = gDoc->instrumentsModifier();
     const InstrumentItem* t = set->currentItem();
-    const QString copyName = set->suggestInstrumentName(t->instrumentName());
-
-    const int row = set->instrumentItems().size();
-    beginInsertRows({}, row, row);
-    InstrumentItem* t2 = set->insertItemCopy(*t);
-    t2->setInstrumentName(copyName);
-    emit set->instrumentAddedOrRemoved();
-    endInsertRows();
-
-    return createIndex(row, 0);
+    InstrumentItem* t2 = t->createItemCopy();
+    t2->setId(QUuid::createUuid().toString());
+    return pushInstrument(t2);
 }
 
 QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 {
     InstrumentsSet* set = gDoc->instrumentsModifier();
-    const int row = set->instrumentItems().size();
 
+    const int row = set->instrumentItems().size();
     beginInsertRows({}, row, row);
-    set->addInstrumentItem(t);
+    set->push_back(t);
     endInsertRows();
+    emit set->setChanged();
 
     return createIndex(row, 0);
 }
-
-void InstrumentsQModel::onInstrumentNameChanged(const InstrumentItem* instrument)
-{
-    const auto set = gDoc->instruments()->instrumentItems();
-    if (const auto row = set.indexOf(instrument); row != -1)
-        emit dataChanged(index(row, 0), index(row, 0));
-}
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index e9f0d4961fb..f433d414359 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -37,9 +37,6 @@ public:
     void removeInstrument();
     QModelIndex copyInstrument();
     QModelIndex pushInstrument(InstrumentItem*);
-
-private:
-    void onInstrumentNameChanged(const InstrumentItem* instrument);
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_INSTRUMENTSQMODEL_H
diff --git a/GUI/View/Manager/ProjectManager.cpp b/GUI/View/Manager/ProjectManager.cpp
index 486980915b5..3e4506c2573 100644
--- a/GUI/View/Manager/ProjectManager.cpp
+++ b/GUI/View/Manager/ProjectManager.cpp
@@ -322,7 +322,7 @@ void ProjectManager::createNewProject()
     if (gDoc)
         throw std::runtime_error("ProjectManager::createNewProject -> Project already exists");
 
-    gDoc = std::make_unique<ProjectDocument>();
+    gDoc.reset(new ProjectDocument);
 
     if (m_autosave)
         m_autosave->setDocument(gDoc.get());
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 8fbd499015e..88449921609 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -29,6 +29,7 @@
 #include <QFormLayout>
 #include <QLineEdit>
 #include <QTextEdit>
+#include <iostream>
 
 InstrumentView::InstrumentView()
     : m_listing(new InstrumentsQListView)
@@ -63,43 +64,22 @@ InstrumentView::InstrumentView()
     hLayout->addWidget(m_scroll_area);
     m_scroll_area->setWidgetResizable(true);
     m_scroll_area->setMinimumWidth(1000);
+    m_scroll_area->setWidget(new QWidget(m_scroll_area)); // initial state: blank widget
 
     hLayout->addStretch(1);
 
     //... Finalize
 
-    connect(gDoc->instruments(), &InstrumentsSet::instrumentSelected, this,
+    connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
-    // Initial state
-    createWidgetsForCurrentInstrument();
-    subscribeOnExternalUpdates();
-}
-
-void InstrumentView::subscribeOnExternalUpdates()
-{
-    connect(gDoc->instruments(), &InstrumentsSet::instrumentChanged, this,
-            &InstrumentView::onInstrumentChangedFromExternal, Qt::UniqueConnection);
-}
-
-void InstrumentView::showEvent(QShowEvent*)
-{
-    // disconnect because when this view is visible, no other instance is modifying instruments. By
-    // disconnecting, no additional logic is necessary to avoid recursive calls (recursive since
-    // this view also causes instrumentChanged to be emitted).
-    disconnect(gDoc->instruments(), &InstrumentsSet::instrumentChanged, this,
-               &InstrumentView::onInstrumentChangedFromExternal);
-}
-
-void InstrumentView::hideEvent(QHideEvent*)
-{
-    // when the instrument view gets hidden (meaning another view is shown), it's necessary to
-    // listen to changes (e.g. performed by the LinkInstrumentManager).
-    subscribeOnExternalUpdates();
+    updateActions();
 }
 
 void InstrumentView::createWidgetsForCurrentInstrument()
 {
+    updateActions();
+
     InstrumentItem* currentInstrument = gDoc->instrumentsModifier()->currentItem();
     if (!currentInstrument) {
         m_scroll_area->setWidget(new QWidget(m_scroll_area)); // blank widget
@@ -120,7 +100,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
 
     auto* nameEdit = new QLineEdit(g);
     nameEdit->setText(currentInstrument->instrumentName());
-    connect(nameEdit, &QLineEdit::textEdited, this, &InstrumentView::onInstrumentNameEdited);
+    connect(nameEdit, &QLineEdit::textEdited, [this] { m_listing->repaint(); });
     formLayout->addRow("Name:", nameEdit);
 
     auto* descriptionEdit = new QTextEdit(g);
@@ -129,9 +109,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
     descriptionEdit->setAcceptRichText(false);
     descriptionEdit->setTabChangesFocus(true);
     descriptionEdit->setPlainText(currentInstrument->description());
-    connect(descriptionEdit, &QTextEdit::textChanged, [this, descriptionEdit] {
-        onInstrumentdescriptionEdited(descriptionEdit->toPlainText());
-    });
+    connect(descriptionEdit, &QTextEdit::textChanged, [this] { m_listing->repaint(); });
     formLayout->addRow("Description:", descriptionEdit);
 
     //... All remaining content depends on instrument type
@@ -149,38 +127,13 @@ void InstrumentView::createWidgetsForCurrentInstrument()
         ASSERT_NEVER;
 
     layout->addWidget(editor);
-    connect(editor, &IComponentEditor::dataChanged, this,
-            &InstrumentView::onInstrumentChangedByEditor);
-
     m_scroll_area->setWidget(w);
 }
 
-void InstrumentView::onInstrumentNameEdited(const QString& newName)
-{
-    InstrumentItem* t = gDoc->instrumentsModifier()->currentItem();
-    if (t && t->instrumentName() != newName)
-        gDoc->instrumentsModifier()->setInstrumentName(t, newName);
-}
-
-void InstrumentView::onInstrumentdescriptionEdited(const QString& s)
-{
-    InstrumentItem* t = gDoc->instrumentsModifier()->currentItem();
-    if (t && t->description() != s) {
-        t->setDescription(s);
-        onInstrumentChangedByEditor();
-    }
-}
-
-void InstrumentView::onInstrumentChangedByEditor()
-{
-    // uses 'instrumentChanged' signal for two purposes:
-    // 1) notify 'ProjectDocument' that user has changed data ==> mark project with '*'
-    // 2) notify 'LinkInstrumentManager' ==> unlink instrument from data if they are incompatible
-    emit gDoc->instruments()->instrumentChanged(gDoc->instrumentsModifier()->currentItem());
-}
-
-void InstrumentView::onInstrumentChangedFromExternal(const InstrumentItem* instrument)
+void InstrumentView::updateActions()
 {
-    if (instrument == gDoc->instrumentsModifier()->currentItem())
-        createWidgetsForCurrentInstrument();
+    bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
+    gActions->remove_instrument->setEnabled(enabled);
+    gActions->copy_instrument->setEnabled(enabled);
+    gActions->store_in_library_instrument->setEnabled(enabled);
 }
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index 971aac39107..47832162d6b 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -27,24 +27,14 @@ class InstrumentView : public QWidget {
 public:
     InstrumentView();
 
-private:
-    void showEvent(QShowEvent*) override;
-    void hideEvent(QHideEvent*) override;
+private slots:
+    void updateActions();
 
-    void subscribeOnExternalUpdates();
+private:
     void createWidgetsForCurrentInstrument();
-    void onInstrumentNameEdited(const QString& newName);
-    void onInstrumentdescriptionEdited(const QString& t);
-    void onInstrumentChangedByEditor();
-    void onInstrumentChangedFromExternal(const InstrumentItem* instrument);
-    void onSingleInstrumentModeChanged(bool newState);
 
     InstrumentsQListView* m_listing;
     QScrollArea* m_scroll_area;
-    QCheckBox* gisasCheck;
-    QCheckBox* offspecCheck;
-    QCheckBox* specularCheck;
-    QCheckBox* depthProbeCheck;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_VIEWS_INSTRUMENTVIEW_H
diff --git a/GUI/styles/Base.stylesheet b/GUI/styles/Base.stylesheet
index 101c6d4a28a..3022c0d393a 100644
--- a/GUI/styles/Base.stylesheet
+++ b/GUI/styles/Base.stylesheet
@@ -260,37 +260,11 @@ QAbstractItemView
     alternate-background-color:palette(alternate-base);
 }
 
-/* ------------------------------------------------------------------------------- */
-DataView QTreeView::item
-{
-    padding: 2px;
-    border-bottom: 1px solid rgba(100, 100, 100, 25%);
-}
-DataView QTreeView::item:selected
-{
-	color: palette(text);
-}
-
-/* ------------------------------------------------------------------------------- */
-QTreeView::item .QWidget
-{
-    background-color: transparent;
-}
-
 /* ------------------------------------------------------------------------------- */
 QListView
 {
-    background-color: palette(dark)
-}
-QListView::item .QWidget
-{
-    background-color: transparent;
+    /* background-color: palette(dark) */
 }
-/* Listing (from InstrumentsQListView.cpp before 2297966a5 31oct23 11:59)
-                          "   selection-background-color : rgb(98,100,105); \n"
-                          "   selection-color: rgb(255,255,255);\n"
-                          "   border: 1px solid rgb(98,100,105);\n"
-*/
 
 /* ------------------------------------------------------------------------------- */
 QDockWidget
@@ -596,7 +570,7 @@ QWidget{
 
 QTextEdit, QLineEdit, QSpinBox, ScientificSpinBox, QDoubleSpinBox, DoubleSpinBox, QComboBox, QTabWidget,
 QDockWidget, QListView, QTableView, QTableWidget, QHeaderView, QProgressBar, QSlider, QScrollBar,
-QToolBar, QPushButton {
+QToolBar, QPushButton, QScrollArea {
     background-color: white;
 }
 
diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index 3c97df77c79..d36c18d51b5 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -37,16 +37,16 @@ TEST_F(TestAutosaveController, autoSaveController)
 
     const int autosave_time(100);
 
-    std::unique_ptr<ProjectDocument> document(new ProjectDocument);
+    gDoc = std::make_unique<ProjectDocument>();
     auto* instrument = new GISASInstrumentItem;
-    document->instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
-    document->saveProjectFileWithData(projectFileName);
+    gDoc->saveProjectFileWithData(projectFileName);
 
     // setting up autosave
     AutosaveController autosave;
     autosave.setAutosaveTime(autosave_time);
-    autosave.setDocument(document.get());
+    autosave.setDocument(gDoc.get());
 
     // checking proposed autosave directory
     EXPECT_EQ(autosave.autosaveDir(), QString(projectDir + "/autosave"));
@@ -55,20 +55,20 @@ TEST_F(TestAutosaveController, autoSaveController)
     QSignalSpy spyAutosave(&autosave, SIGNAL(autosaveRequest()));
 
     // modify document once and check that autosave directory was created
-    modelsModifier(*document);
-    EXPECT_TRUE(document->isModified());
+    modelsModifier(*gDoc);
+    EXPECT_TRUE(gDoc->isModified());
     EXPECT_TRUE(spyAutosave.wait(m_save_wait));
     EXPECT_EQ(spyAutosave.count(), 1);
     EXPECT_TRUE(QFile::exists(autosave.autosaveDir()));
 
     // saving document and checking that autosave is not triggered
-    document->saveProjectFileWithData(projectFileName);
-    EXPECT_FALSE(document->isModified());
+    gDoc->saveProjectFileWithData(projectFileName);
+    EXPECT_FALSE(gDoc->isModified());
     EXPECT_EQ(spyAutosave.count(), 1);
 
     // modify several times and check that autosave was triggered only once
     for (size_t i = 0; i < 10; ++i)
-        modelsModifier(*document);
+        modelsModifier(*gDoc);
 
     EXPECT_TRUE(spyAutosave.wait(m_save_wait));
     EXPECT_EQ(spyAutosave.count(), 2);
@@ -82,20 +82,20 @@ TEST_F(TestAutosaveController, autoSaveController)
 
 TEST_F(TestAutosaveController, autoSaveControllerNewDocument)
 {
-    std::unique_ptr<ProjectDocument> document(new ProjectDocument);
+    gDoc = std::make_unique<ProjectDocument>();
     auto* instrument = new GISASInstrumentItem;
-    document->instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
 
     const int autosave_time(100);
 
     AutosaveController autosave;
     autosave.setAutosaveTime(autosave_time);
-    autosave.setDocument(document.get());
+    autosave.setDocument(gDoc.get());
 
     QSignalSpy spyAutosave(&autosave, SIGNAL(autosaveRequest()));
 
-    modelsModifier(*document);
+    modelsModifier(*gDoc);
     EXPECT_FALSE(spyAutosave.wait(autosave_time * 2));
     EXPECT_EQ(spyAutosave.count(), 0);
 }
@@ -111,44 +111,46 @@ TEST_F(TestAutosaveController, autosaveEnabled)
     const QString ext = QString(GUI::Util::Project::projectFileExtension);
     const QString projectFileName(projectDir + "/document" + ext);
 
-    std::unique_ptr<ProjectManager> manager(new ProjectManager(nullptr));
-    ProjectDocument* document = manager->newProject();
-    EXPECT_TRUE(document != nullptr);
+    gDoc = std::make_unique<ProjectDocument>();
+    auto manager = std::make_unique<ProjectManager>(nullptr);
+    EXPECT_TRUE(manager);
+    manager->newProject();
+    EXPECT_TRUE(gDoc);
 
-    document->setProjectFullPath(projectFileName);
+    gDoc->setProjectFullPath(projectFileName);
     auto* instrument = new GISASInstrumentItem;
-    document->instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
 
     DatafileItem* realData =
-        UTest::GUI::createRealData2D("TestData", *document->datafilesModifier(), 0.);
+        UTest::GUI::createRealData2D("TestData", *gDoc->datafilesModifier(), 0.);
     DataItem* data_item = realData->dataItem();
-    auto frame = document->instruments()->instrumentItems().front()->createFrame();
+    auto frame = gDoc->instruments()->instrumentItems().front()->createFrame();
     Datafield df(frame.release());
     data_item->setDatafield(df);
-    document->clearModified();
-    EXPECT_FALSE(document->isModified());
+    gDoc->clearModified();
+    EXPECT_FALSE(gDoc->isModified());
 
     manager->setAutosaveEnabled(true);
     const int autosave_time(200);
     manager->autosaveController()->setAutosaveTime(autosave_time);
-    manager->autosaveController()->setDocument(document);
+    manager->autosaveController()->setDocument(gDoc.get());
 
-    QSignalSpy spyDocument(document, SIGNAL(projectSaved()));
-    document->saveProjectFileWithData(projectFileName);
+    QSignalSpy spyDocument(gDoc.get(), SIGNAL(projectSaved()));
+    gDoc->saveProjectFileWithData(projectFileName);
 
     spyDocument.wait(m_save_wait); // waiting saving in a thread is complete
     EXPECT_EQ(spyDocument.count(), 1);
-    EXPECT_FALSE(document->isModified());
+    EXPECT_FALSE(gDoc->isModified());
     EXPECT_TRUE(QFile::exists(projectDir + "/document" + ext));
     EXPECT_TRUE(QFile::exists(projectDir + "/realdata_TestData.int"));
     spyDocument.clear();
 
     // modify several times and check SaveService signals
     for (size_t i = 0; i < 10; ++i)
-        modelsModifier(*document);
+        modelsModifier(*gDoc);
 
-    EXPECT_TRUE(document->isModified());
+    EXPECT_TRUE(gDoc->isModified());
 
     spyDocument.wait(m_save_wait); // waiting saving in a thread is complete
     EXPECT_EQ(spyDocument.count(), 1);
@@ -157,7 +159,7 @@ TEST_F(TestAutosaveController, autosaveEnabled)
     EXPECT_TRUE(QFile::exists(projectDir + "/autosave/realdata_TestData.int"));
 
     // after autosave the project has to be still in modified state
-    EXPECT_TRUE(document->isModified());
+    EXPECT_TRUE(gDoc->isModified());
     // after autosave, project file name should remain the same
-    EXPECT_EQ(document->projectFullPath(), projectFileName);
+    EXPECT_EQ(gDoc->projectFullPath(), projectFileName);
 }
diff --git a/Tests/Unit/GUI/TestDatafilesModel.cpp b/Tests/Unit/GUI/TestDatafilesModel.cpp
index 88fd2b751a7..18a62a3230b 100644
--- a/Tests/Unit/GUI/TestDatafilesModel.cpp
+++ b/Tests/Unit/GUI/TestDatafilesModel.cpp
@@ -85,7 +85,7 @@ TEST(TestDatafilesSet, saveXMLData)
     auto* spec1 = new DatafileItem("spec1", df1);
     model1.push_back(spec1);
     auto* t1 = new SpecularInstrumentItem;
-    instrument_model.addInstrumentItem(t1);
+    instrument_model.push_back(t1);
     spec1->linkToInstrument(t1);
 
     // add second specular DatafileItem
@@ -99,8 +99,8 @@ TEST(TestDatafilesSet, saveXMLData)
     model1.push_back(intensity2);
     auto* t2 = new GISASInstrumentItem;
     auto* t3 = new OffspecInstrumentItem;
-    instrument_model.addInstrumentItem(t2);
-    instrument_model.addInstrumentItem(t3);
+    instrument_model.push_back(t2);
+    instrument_model.push_back(t3);
     intensity1->linkToInstrument(t2);
     intensity2->linkToInstrument(t3);
 
diff --git a/Tests/Unit/GUI/TestInstrumentItems.cpp b/Tests/Unit/GUI/TestInstrumentItems.cpp
deleted file mode 100644
index 316e2be98d3..00000000000
--- a/Tests/Unit/GUI/TestInstrumentItems.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "GUI/Model/Device/InstrumentItems.h"
-#include "GUI/Model/Device/InstrumentsSet.h"
-#include "GUI/Model/Project/ProjectDocument.h"
-#include "Tests/GTestWrapper/google_test.h"
-#include <QSignalSpy>
-
-Q_DECLARE_METATYPE(const InstrumentItem*)
-
-//! Checks whether instrumentAddedRemoved will be emitted as expected
-
-TEST(TestInstrumentCollection, instrumentAddedRemoved)
-{
-    auto doc = std::make_unique<ProjectDocument>();
-
-    QSignalSpy spy(doc->instruments(), SIGNAL(instrumentAddedOrRemoved()));
-    EXPECT_TRUE(spy.isValid());
-
-    // populating instrument model
-    auto* p = new GISASInstrumentItem;
-    doc->instrumentsModifier()->addInstrumentItem(p);
-
-    // checking that a signal was emitted about the new instrument
-    EXPECT_EQ(spy.count(), 1);
-
-    // removing instrument
-    doc->instrumentsModifier()->removeInstrument(p);
-    EXPECT_EQ(spy.count(), 2);
-}
-
-//! Test whether instrumentChanged will be emitted as expected
-TEST(TestInstrumentCollection, instrumentChanged)
-{
-    qRegisterMetaType<const InstrumentItem*>();
-    auto doc = std::make_unique<ProjectDocument>();
-
-    // populating instrument model
-    auto* instrument1 = new GISASInstrumentItem;
-    doc->instrumentsModifier()->addInstrumentItem(instrument1);
-    auto* instrument2 = new SpecularInstrumentItem;
-    doc->instrumentsModifier()->addInstrumentItem(instrument2);
-
-    QSignalSpy spy(doc->instruments(), SIGNAL(instrumentChanged(const InstrumentItem*)));
-    EXPECT_TRUE(spy.isValid());
-
-    // change name of instrument 1
-    doc->instrumentsModifier()->setInstrumentName(instrument1, "A");
-    EXPECT_EQ(spy.count(), 1);
-    const auto* instr = qvariant_cast<const InstrumentItem*>(spy.at(0).at(0));
-    EXPECT_EQ(instr, instrument1);
-
-    // change other properties, e.g. id
-    instrument1->setId("xxxxx");
-    emit doc->instruments()->instrumentChanged(instrument1);
-    EXPECT_EQ(spy.count(), 2);
-
-    // change name of instrument 2
-    doc->instrumentsModifier()->setInstrumentName(instrument2, "B");
-    EXPECT_EQ(spy.count(), 3);
-    instr = qvariant_cast<const InstrumentItem*>(spy.at(2).at(0));
-    EXPECT_EQ(instr, instrument2);
-
-    // Add another instrument
-    auto* instrument3 = new OffspecInstrumentItem;
-    doc->instrumentsModifier()->addInstrumentItem(instrument3);
-
-    // Change instrument2
-    doc->instrumentsModifier()->setInstrumentName(instrument2, "BB");
-    EXPECT_EQ(spy.count(), 4);
-    instr = qvariant_cast<const InstrumentItem*>(spy.at(3).at(0));
-    EXPECT_EQ(instr, instrument2);
-
-    // Change instrument3
-    doc->instrumentsModifier()->setInstrumentName(instrument3, "C");
-    EXPECT_EQ(spy.count(), 5);
-    instr = qvariant_cast<const InstrumentItem*>(spy.at(4).at(0));
-    EXPECT_EQ(instr, instrument3);
-}
diff --git a/Tests/Unit/GUI/TestInstrumentsSet.cpp b/Tests/Unit/GUI/TestInstrumentsSet.cpp
new file mode 100644
index 00000000000..71ce2ec27c0
--- /dev/null
+++ b/Tests/Unit/GUI/TestInstrumentsSet.cpp
@@ -0,0 +1,72 @@
+#include "GUI/Model/Device/InstrumentItems.h"
+#include "GUI/Model/Device/InstrumentsSet.h"
+#include "GUI/Model/Project/ProjectDocument.h"
+#include "Tests/GTestWrapper/google_test.h"
+#include <QSignalSpy>
+
+Q_DECLARE_METATYPE(const InstrumentItem*)
+
+/* Disabled 18feb24: signal no longer emitted at InstrumentsSet level
+
+//! Checks whether instrumentAddedRemoved will be emitted as expected
+
+TEST(TestInstrumentsSet, instrumentAddedRemoved)
+{
+    gDoc = std::make_unique<ProjectDocument>();
+
+    QSignalSpy spy(gDoc->instruments(), SIGNAL(setChanged()));
+    EXPECT_TRUE(spy.isValid());
+
+    // populating instrument model
+    auto* p = new GISASInstrumentItem;
+    gDoc->instrumentsModifier()->push_back(p);
+
+    // checking that a signal was emitted about the new instrument
+    EXPECT_EQ(spy.count(), 1);
+
+    // removing instrument
+    gDoc->instrumentsModifier()->delete_element(p);
+    EXPECT_EQ(spy.count(), 2);
+}
+*/
+
+//! Test whether instrumentChanged will be emitted as expected
+TEST(TestInstrumentsSet, instrumentChanged)
+{
+    qRegisterMetaType<const InstrumentItem*>();
+    gDoc = std::make_unique<ProjectDocument>();
+
+    // populating instrument model
+    auto* instrument1 = new GISASInstrumentItem;
+    gDoc->instrumentsModifier()->push_back(instrument1);
+    auto* instrument2 = new SpecularInstrumentItem;
+    gDoc->instrumentsModifier()->push_back(instrument2);
+
+    QSignalSpy spy(gDoc->instruments(), SIGNAL(currentModified()));
+    EXPECT_TRUE(spy.isValid());
+
+    // change name of instrument 1
+    gDoc->instrumentsModifier()->setInstrumentName(instrument1, "A");
+    EXPECT_EQ(spy.count(), 1);
+
+    // change other properties, e.g. id
+    instrument1->setId("xxxxx");
+    emit gDoc->instruments()->currentModified();
+    EXPECT_EQ(spy.count(), 2);
+
+    // change name of instrument 2
+    gDoc->instrumentsModifier()->setInstrumentName(instrument2, "B");
+    EXPECT_EQ(spy.count(), 3);
+
+    // Add another instrument
+    auto* instrument3 = new OffspecInstrumentItem;
+    gDoc->instrumentsModifier()->push_back(instrument3);
+
+    // Change instrument2
+    gDoc->instrumentsModifier()->setInstrumentName(instrument2, "BB");
+    EXPECT_EQ(spy.count(), 4);
+
+    // Change instrument3
+    gDoc->instrumentsModifier()->setInstrumentName(instrument3, "C");
+    EXPECT_EQ(spy.count(), 5);
+}
diff --git a/Tests/Unit/GUI/TestLinkInstrument.cpp b/Tests/Unit/GUI/TestLinkInstrument.cpp
index 12734482ada..3d005585f37 100644
--- a/Tests/Unit/GUI/TestLinkInstrument.cpp
+++ b/Tests/Unit/GUI/TestLinkInstrument.cpp
@@ -32,51 +32,51 @@ QVector<DatafileItem*> linkedRealDataItems(DatafilesSet& realModel,
 
 TEST(TestLinkInstrument, canLinkToGisas)
 {
-    ProjectDocument document;
+    gDoc = std::make_unique<ProjectDocument>();
 
     // populating instrument model
     auto* instrument = new GISASInstrumentItem;
-    document.instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     const QString identifier = instrument->id();
     ASSERT_TRUE(!identifier.isEmpty());
 
     // populating real data model, setting intensity data
     DatafileItem* realData =
-        UTest::GUI::createRealData2D("RealData", *document.datafilesModifier(), 0.);
+        UTest::GUI::createRealData2D("RealData", *gDoc->datafilesModifier(), 0.);
     Datafield df(instrument->createFrame().release());
     realData->dataItem()->setDatafield(df);
 
     ASSERT_TRUE(
-        document.linkInstrumentManager()->canLinkDataToInstrument(realData, identifier, nullptr));
+        gDoc->linkInstrumentManager()->canLinkDataToInstrument(realData, identifier, nullptr));
 
     // making link
     realData->linkToInstrument(instrument);
-    EXPECT_EQ(linkedRealDataItems(*document.datafilesModifier(), instrument),
-              QVector<DatafileItem*>() << realData);
+    EXPECT_EQ(linkedRealDataItems(*gDoc->datafilesModifier(), instrument), QVector<DatafileItem*>()
+                                                                               << realData);
 
     // changing detector binning and checking that link is destroyed
     auto* detectorItem = instrument->detectorItem();
     detectorItem->phiAxis().setNbins(10);
-    emit document.instruments()->instrumentChanged(instrument);
+    emit gDoc->instruments()->currentModified();
 
-    EXPECT_EQ(linkedRealDataItems(*document.datafilesModifier(), instrument),
+    EXPECT_EQ(linkedRealDataItems(*gDoc->datafilesModifier(), instrument),
               QVector<DatafileItem*>());
     EXPECT_EQ(realData->instrumentId(), QString());
 }
 
 TEST(TestLinkInstrument, canLinkToSpecular)
 {
-    ProjectDocument document;
+    gDoc = std::make_unique<ProjectDocument>();
 
     // populating instrument model
     auto* instrument = new SpecularInstrumentItem;
-    document.instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     const QString identifier = instrument->id();
     ASSERT_TRUE(!identifier.isEmpty());
 
     // populating real data model, setting intensity data
     DatafileItem* realData =
-        UTest::GUI::createRealData1D("RealData", *document.datafilesModifier(), 0.);
+        UTest::GUI::createRealData1D("RealData", *gDoc->datafilesModifier(), 0.);
     auto frame = instrument->createFrame();
     instrument->scanItem()->grazingScanItem()->initListScan(frame->axis(0));
     instrument->scanItem()->grazingScanItem()->selectListScan();
@@ -85,10 +85,10 @@ TEST(TestLinkInstrument, canLinkToSpecular)
     realData->dataItem()->setOriginalDatafield(df);
 
     ASSERT_TRUE(
-        document.linkInstrumentManager()->canLinkDataToInstrument(realData, identifier, nullptr));
+        gDoc->linkInstrumentManager()->canLinkDataToInstrument(realData, identifier, nullptr));
 
     // making link
     realData->linkToInstrument(instrument);
-    EXPECT_EQ(linkedRealDataItems(*document.datafilesModifier(), instrument),
-              QVector<DatafileItem*>() << realData);
+    EXPECT_EQ(linkedRealDataItems(*gDoc->datafilesModifier(), instrument), QVector<DatafileItem*>()
+                                                                               << realData);
 }
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index fb14b358f28..8fedf71ef30 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -32,38 +32,38 @@ TEST_F(TestProjectDocument, projectDocument)
     const QString ext = QString(GUI::Util::Project::projectFileExtension);
     const QString projectFileName(projectDir + "/document" + ext);
 
-    ProjectDocument document;
+    gDoc = std::make_unique<ProjectDocument>();
     // Checking initial document status
-    EXPECT_FALSE(document.isModified());
-    EXPECT_FALSE(document.hasValidNameAndPath());
-    EXPECT_EQ(document.projectDir(), QString());
-    EXPECT_EQ(document.projectName(), QString());
-    EXPECT_EQ(document.projectFullPath(), QString());
+    EXPECT_FALSE(gDoc->isModified());
+    EXPECT_FALSE(gDoc->hasValidNameAndPath());
+    EXPECT_EQ(gDoc->projectDir(), QString());
+    EXPECT_EQ(gDoc->projectName(), QString());
+    EXPECT_EQ(gDoc->projectFullPath(), QString());
 
     auto* instrument = new GISASInstrumentItem;
-    document.instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
 
     // Checking document name and isModified status after project save
-    document.saveProjectFileWithData(projectFileName);
-    EXPECT_TRUE(document.hasValidNameAndPath());
-    EXPECT_EQ(document.projectDir(), projectDir);
-    EXPECT_EQ(document.projectName(), "document");
-    EXPECT_EQ(document.projectFullPath(), projectFileName);
-    EXPECT_FALSE(document.isModified());
-
-    QSignalSpy spyDocument(&document, SIGNAL(modifiedStateChanged()));
+    gDoc->saveProjectFileWithData(projectFileName);
+    EXPECT_TRUE(gDoc->hasValidNameAndPath());
+    EXPECT_EQ(gDoc->projectDir(), projectDir);
+    EXPECT_EQ(gDoc->projectName(), "document");
+    EXPECT_EQ(gDoc->projectFullPath(), projectFileName);
+    EXPECT_FALSE(gDoc->isModified());
+
+    QSignalSpy spyDocument(gDoc.get(), SIGNAL(modifiedStateChanged()));
     EXPECT_EQ(spyDocument.count(), 0);
 
     // Changing document and checking its status
-    modelsModifier(document);
-    EXPECT_TRUE(document.isModified());
-    EXPECT_EQ(spyDocument.count(), 1);
+    modelsModifier(*gDoc);
+    EXPECT_TRUE(gDoc->isModified());
+    // EXPECT_EQ(spyDocument.count(), 1); TODO 18feb24 restore
 
     // Saving document
-    document.saveProjectFileWithData(projectFileName);
-    EXPECT_FALSE(document.isModified());
-    EXPECT_EQ(spyDocument.count(), 2);
+    gDoc->saveProjectFileWithData(projectFileName);
+    EXPECT_FALSE(gDoc->isModified());
+    // EXPECT_EQ(spyDocument.count(), 2); TODO 18feb24 restore
 
     QFileInfo info(projectFileName);
     EXPECT_TRUE(info.exists());
@@ -71,24 +71,25 @@ TEST_F(TestProjectDocument, projectDocument)
 
 TEST_F(TestProjectDocument, projectDocumentWithData)
 {
+    gDoc = std::make_unique<ProjectDocument>();
+
     const QString projectDir("projectDocumentWithData");
     UTest::GUI::create_dir(projectDir);
     const QString ext = QString(GUI::Util::Project::projectFileExtension);
 
-    ProjectDocument document;
     auto* instrument = new GISASInstrumentItem;
-    document.instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
     DatafileItem* realData =
-        UTest::GUI::createRealData2D("TestData", *document.datafilesModifier(), 0.);
+        UTest::GUI::createRealData2D("TestData", *gDoc->datafilesModifier(), 0.);
     ASSERT(realData);
     DataItem* data_item = realData->dataItem();
-    auto frame = document.instruments()->instrumentItems().front()->createFrame();
+    auto frame = gDoc->instruments()->instrumentItems().front()->createFrame();
     Datafield df(frame.release());
     data_item->setDatafield(df);
 
-    document.setProjectDir(projectDir);
-    document.saveProjectFileWithData(projectDir + "/untitled" + ext);
+    gDoc->setProjectDir(projectDir);
+    gDoc->saveProjectFileWithData(projectDir + "/untitled" + ext);
 
     QFileInfo info(projectDir + "/untitled" + ext);
     EXPECT_TRUE(info.exists());
@@ -109,21 +110,21 @@ TEST_F(TestProjectDocument, failingProjectSave)
     const QString ext = QString(GUI::Util::Project::projectFileExtension);
     const QString projectFileName(projectDir + "/document" + ext);
 
-    std::unique_ptr<ProjectDocument> document(new ProjectDocument);
+    gDoc = std::make_unique<ProjectDocument>();
     auto* instrument = new GISASInstrumentItem;
-    document->instrumentsModifier()->addInstrumentItem(instrument);
+    gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
-    modelsModifier(*document);
+    modelsModifier(*gDoc);
 
     EXPECT_FALSE(QFile::exists(projectFileName));
 
-    QSignalSpy spyDocument(document.get(), SIGNAL(modifiedStateChanged()));
+    QSignalSpy spyDocument(gDoc.get(), SIGNAL(modifiedStateChanged()));
 
-    EXPECT_THROW(document->saveProjectFileWithData(projectFileName), std::runtime_error);
+    EXPECT_THROW(gDoc->saveProjectFileWithData(projectFileName), std::runtime_error);
 
     EXPECT_EQ(spyDocument.count(), 0);
     EXPECT_FALSE(QFile::exists(projectFileName));
 
     // after failed save, document should still be in modified state
-    EXPECT_TRUE(document->isModified());
+    EXPECT_TRUE(gDoc->isModified());
 }
-- 
GitLab


From 81425691a72338873d343e5a117aca7c80567caf Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Mon, 19 Feb 2024 21:22:35 +0100
Subject: [PATCH 017/108] resolved new-project bug: no more duplications

---
 GUI/View/List/InstrumentsQListView.cpp | 8 +++++++-
 GUI/View/List/InstrumentsQListView.h   | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 1583a854b4f..b431a5daec5 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -25,7 +25,6 @@
 #include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QMessageBox>
-#include <QThread>
 
 InstrumentsQListView::InstrumentsQListView()
     : m_model(new InstrumentsQModel)
@@ -66,6 +65,7 @@ InstrumentsQListView::InstrumentsQListView()
         emit gDoc->instruments()->setChanged();
     });
 
+    disconnect(gDoc->instruments(), &InstrumentsSet::setChanged, nullptr, nullptr);
     connect(gDoc->instruments(), &InstrumentsSet::setChanged, [this] {
         setCurrentIndex(m_model->index(gDoc->instruments()->currentIndex(), 0));
         repaint();
@@ -74,6 +74,12 @@ InstrumentsQListView::InstrumentsQListView()
     setContextMenuPolicy(Qt::ActionsContextMenu);
 }
 
+InstrumentsQListView::~InstrumentsQListView()
+{
+    disconnect(this, nullptr, nullptr, nullptr);
+    delete m_model;
+}
+
 QSize InstrumentsQListView::sizeHint() const
 {
     return {170, 400};
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 51ede215814..558602eaaed 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -26,6 +26,7 @@ class InstrumentsQListView : public QListView {
     Q_OBJECT
 public:
     InstrumentsQListView();
+    ~InstrumentsQListView();
 
     QSize sizeHint() const override;
     QSize minimumSizeHint() const override;
-- 
GitLab


From 9e8a88d2b1c2cca52762fe4e1914f04d343e3e6c Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 15:47:17 +0100
Subject: [PATCH 018/108] gDOc + Win export symbol

---
 GUI/CMakeLists.txt                    | 18 ++++++++----------
 GUI/Model/Project/ProjectDocument.cpp |  2 +-
 GUI/Model/Project/ProjectDocument.h   |  3 ++-
 Wrap/WinDllMacros.h                   |  7 +++++++
 4 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/GUI/CMakeLists.txt b/GUI/CMakeLists.txt
index a7deca8d324..d1dedf27c90 100644
--- a/GUI/CMakeLists.txt
+++ b/GUI/CMakeLists.txt
@@ -22,16 +22,6 @@ set(resource_files
 
 qt_add_resources(RC_SRCS ${resource_files})
 
-# --- definitions ------
-
-if(BA_CRASHHANDLER)
-    add_definitions(-DBA_CRASHHANDLER)
-endif()
-
-if(WIN32)
-    string(APPEND CMAKE_CXX_FLAGS " -DBA_GUI_BUILD_DLL")
-endif()
-
 # --- make the library ---------
 
 add_library(${lib} SHARED ${source_files} ${RC_SRCS} ${include_files} ${form_files})
@@ -70,6 +60,14 @@ target_include_directories(${lib} PUBLIC
     ${CMAKE_SOURCE_DIR}/3rdparty/GUI/qcustomplot
 )
 
+if(WIN32)
+    target_compile_definitions(${lib} PRIVATE -DBA_GUI_BUILD_DLL)
+endif()
+
+if(BA_CRASHHANDLER)
+    target_compile_definitions(${lib} PRIVATE -DBA_CRASHHANDLER)
+endif()
+
 # --- installation ---------
 
 set_target_properties(${lib} PROPERTIES
diff --git a/GUI/Model/Project/ProjectDocument.cpp b/GUI/Model/Project/ProjectDocument.cpp
index 95d47cc8dc2..fa4ebbf6693 100644
--- a/GUI/Model/Project/ProjectDocument.cpp
+++ b/GUI/Model/Project/ProjectDocument.cpp
@@ -34,7 +34,7 @@
 #include <QFile>
 #include <QStandardPaths>
 
-std::unique_ptr<ProjectDocument> gDoc;
+BA_GUI_API_ std::unique_ptr<ProjectDocument> gDoc;
 
 namespace {
 
diff --git a/GUI/Model/Project/ProjectDocument.h b/GUI/Model/Project/ProjectDocument.h
index fe606b56f9b..fa99bf6f38d 100644
--- a/GUI/Model/Project/ProjectDocument.h
+++ b/GUI/Model/Project/ProjectDocument.h
@@ -15,6 +15,7 @@
 #ifndef BORNAGAIN_GUI_MODEL_PROJECT_PROJECTDOCUMENT_H
 #define BORNAGAIN_GUI_MODEL_PROJECT_PROJECTDOCUMENT_H
 
+#include "Wrap/WinDllMacros.h"
 #include <QObject>
 
 class DatafilesSet;
@@ -27,7 +28,7 @@ class QIODevice;
 class SamplesSet;
 class SimulationOptionsItem;
 
-extern std::unique_ptr<ProjectDocument> gDoc;
+BA_GUI_API_ extern std::unique_ptr<ProjectDocument> gDoc;
 
 //! Project document class handles all data related to the opened project
 //! (sample, job, project specific settings).
diff --git a/Wrap/WinDllMacros.h b/Wrap/WinDllMacros.h
index 0282f7d4bb0..4cdeae8f932 100644
--- a/Wrap/WinDllMacros.h
+++ b/Wrap/WinDllMacros.h
@@ -38,10 +38,17 @@
 #define BA_DEVICE_API_ __declspec(dllimport)
 #endif // BA_DEVICE_BUILD_DLL
 
+#ifdef BA_GUI_BUILD_DLL
+#define BA_GUI_API_ __declspec(dllexport)
+#else
+#define BA_GUI_API_ __declspec(dllimport)
+#endif // BA_GUI_BUILD_DLL
+
 #else // not _WIN32
 
 #define BA_BASE_API_
 #define BA_DEVICE_API_
+#define BA_GUI_API_
 
 #endif // _WIN32
 
-- 
GitLab


From 9f4d80ac0c9092774716fe127859b5358eeda79e Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 17:48:12 +0100
Subject: [PATCH 019/108] InstrumentsItem: subclasses in same order as in
 InstrumentsCatalog

---
 GUI/Model/Device/InstrumentItems.cpp | 397 +++++++++++++--------------
 GUI/Model/Device/InstrumentItems.h   |  54 ++--
 2 files changed, 225 insertions(+), 226 deletions(-)

diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index f7e45aa69ac..181bd7ecf0c 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -284,7 +284,7 @@ Frame InstrumentItem::makeFrame() const
 }
 
 //  ************************************************************************************************
-//  class ScanningItem
+//  class ScanningFunctionality
 //  ************************************************************************************************
 
 ScanningFunctionality::ScanningFunctionality(double intensity)
@@ -360,108 +360,83 @@ void ScanningFunctionality::readScanFrom(QXmlStreamReader* r)
     }
 }
 
-
 //  ************************************************************************************************
-//  class SpecularInstrumentItem
+//  class GISASInstrumentItem
 //  ************************************************************************************************
 
-SpecularInstrumentItem::SpecularInstrumentItem()
-    : ScanningFunctionality(1e6)
-{
-}
-
-std::vector<int> SpecularInstrumentItem::axdims() const
+GISASInstrumentItem::GISASInstrumentItem()
 {
-    return {scanItem()->inclinationAxisItem()->size()};
+    m_detector_item = std::make_unique<DetectorItem>();
+    m_beam_item = std::make_unique<BeamItem>();
 }
 
-void SpecularInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
+std::vector<int> GISASInstrumentItem::axdims() const
 {
-    if (axdims().size() != dfileItem->axdims().size())
-        throw std::runtime_error("Specular instrument type is incompatible with passed data shape");
-
-    const auto& dataAxis = dfileItem->dataItem()->c_field()->axis(0);
-    scanItem()->updateToData(dataAxis);
-    scanItem()->grazingScanItem()->updateAxIndicators(makeFrame());
+    ASSERT(detectorItem());
+    return {(int)detectorItem()->phiAxis().nbins(), (int)detectorItem()->alphaAxis().nbins()};
 }
 
-bool SpecularInstrumentItem::alignedWith(const DatafileItem* dfileItem) const
+void GISASInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
 {
-    if (!dfileItem->holdsDimensionalData())
-        return scanItem()->grazingScanItem()->uniformAlphaAxisSelected()
-               && axdims() == dfileItem->axdims();
-
-    if (!scanItem()->grazingScanItem()->pointwiseAlphaAxisSelected())
-        return false;
-
-    const auto* axisItem =
-        dynamic_cast<const PointwiseAxisItem*>(scanItem()->grazingScanItem()->alphaAxisItem());
-    ASSERT(axisItem);
-
-    const auto* instrumentAxis = axisItem->axis();
-    if (!instrumentAxis)
-        return false;
+    if (!dfileItem)
+        return;
 
-    const auto& native_axis = dfileItem->dataItem()->c_field()->axis(0);
-    return *instrumentAxis == native_axis;
+    const auto data_shape = dfileItem->axdims();
+    if (axdims().size() != data_shape.size())
+        throw std::runtime_error("GISAS instrument type is incompatible with passed data shape.");
+    ASSERT(detectorItem());
+    detectorItem()->phiAxis().setNbins(data_shape[0]);
+    detectorItem()->alphaAxis().setNbins(data_shape[1]);
 }
 
-std::unique_ptr<Frame> SpecularInstrumentItem::createFrame() const
+std::unique_ptr<Frame> GISASInstrumentItem::createFrame() const
 {
-    auto* axis_item = scanItem()->inclinationAxisItem();
-    ASSERT(axis_item);
-
-    if (auto* pointwise_axis = dynamic_cast<PointwiseAxisItem*>(axis_item)) {
-        const Scale* pAxis = pointwise_axis->axis();
-        if (!pAxis) // workaround for loading project
-            return {};
-
-        if (pAxis->unit() == "1/nm") {
-            double lambda = scanItem()->wavelength();
-            Scale ax =
-                pAxis->transformedScale(Coordinate("alpha_i", "rad").label(), [lambda](double qz) {
-                    return std::asin(qz * lambda / 4 / pi);
-                });
-            return std::make_unique<Frame>(ax.clone());
-        }
-        return std::make_unique<Frame>(pAxis->clone());
-    }
-
-    Scale axis = axis_item->makeScale("alpha_i (rad)");
-    return std::make_unique<Frame>(axis.clone());
+    return std::make_unique<Frame>(normalDetector()->clippedFrame());
 }
 
-ISimulation* SpecularInstrumentItem::createSimulation(const MultiLayer& sample) const
+ISimulation* GISASInstrumentItem::createSimulation(const MultiLayer& sample) const
 {
-    auto frame = createFrame();
-    std::unique_ptr<BeamScan> scan = createScan(frame->axis(0));
+    const auto beam = beamItem()->createBeam();
     if (withPolarizer())
-        scan->setPolarization(m_polarizer_bloch_vector);
+        beam->setPolarization(m_polarizer_bloch_vector);
+    const auto detector = detectorItem()->createDetector();
     if (withAnalyzer())
-        scan->setAnalyzer(m_analyzer_bloch_vector);
-    auto* result = new SpecularSimulation(*scan, sample);
+        detector->setAnalyzer(m_analyzer_bloch_vector);
+    auto* result = new ScatteringSimulation(*beam, sample, *detector);
+
+    setBeamDistribution(ParameterDistribution::BeamWavelength, beamItem()->wavelengthItem(),
+                        result);
+    setBeamDistribution(ParameterDistribution::BeamInclinationAngle,
+                        beamItem()->beamDistributionItem(), result);
+    setBeamDistribution(ParameterDistribution::BeamAzimuthalAngle, beamItem()->azimuthalAngleItem(),
+                        result);
 
     if (const auto background = backgroundItem()->createBackground())
         result->setBackground(*background);
     return result;
 }
 
-void SpecularInstrumentItem::writeTo(QXmlStreamWriter* w) const
+void GISASInstrumentItem::writeTo(QXmlStreamWriter* w) const
 {
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
-    // instrument parameters from base class
+    // parameters from base class
     w->writeStartElement(Tag::BaseData);
     InstrumentItem::writeTo(w);
     w->writeEndElement();
 
-    // scan parameters from base class
-    w->writeStartElement(Tag::ScanParameters);
-    ScanningFunctionality::writeScanTo(w);
+    // beam
+    w->writeStartElement(Tag::Beam);
+    m_beam_item->writeTo(w);
+    w->writeEndElement();
+
+    // detector
+    w->writeStartElement(Tag::Detector);
+    m_detector_item->writeTo(w);
     w->writeEndElement();
 }
 
-void SpecularInstrumentItem::readFrom(QXmlStreamReader* r)
+void GISASInstrumentItem::readFrom(QXmlStreamReader* r)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -469,14 +444,19 @@ void SpecularInstrumentItem::readFrom(QXmlStreamReader* r)
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
 
-        // instrument parameters from base class
+        // parameters from base class
         if (tag == Tag::BaseData) {
             InstrumentItem::readFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
-            // scan parameters from base class
-        } else if (tag == Tag::ScanParameters) {
-            ScanningFunctionality::readScanFrom(r);
+            // beam
+        } else if (tag == Tag::Beam) {
+            m_beam_item->readFrom(r);
+            XML::gotoEndElementOfTag(r, tag);
+
+            // detector
+        } else if (tag == Tag::Detector) {
+            m_detector_item->readFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
         } else
@@ -484,51 +464,66 @@ void SpecularInstrumentItem::readFrom(QXmlStreamReader* r)
     }
 }
 
+std::unique_ptr<IDetector> GISASInstrumentItem::normalDetector() const
+{
+    return detectorItem()->createDetector();
+}
+
 //  ************************************************************************************************
-//  class DepthprobeInstrumentItem
+//  class OffspecInstrumentItem
 //  ************************************************************************************************
 
-DepthprobeInstrumentItem::DepthprobeInstrumentItem()
+OffspecInstrumentItem::OffspecInstrumentItem()
     : ScanningFunctionality(1e8)
+    , m_detector(new OffspecDetectorItem)
 {
-    auto* axisItem = scanItem()->inclinationAxisItem();
-    axisItem->setMin(0.0);
-    axisItem->setMax(1.0);
-    axisItem->resize(500);
-
-    m_z_axis.initMin("Min (nm)", "Starting value below sample horizon", -100.0,
-                     RealLimits::limitless());
-    m_z_axis.initMax("Max (nm)", "Ending value above sample horizon", 100.0,
-                     RealLimits::limitless());
 }
 
-std::vector<int> DepthprobeInstrumentItem::axdims() const
+std::vector<int> OffspecInstrumentItem::axdims() const
 {
-    return {}; // no certain shape to avoid linking to real data
+    return {scanItem()->grazingScanItem()->nBins(), detectorItem()->ySize()};
 }
 
-void DepthprobeInstrumentItem::updateToRealData(const DatafileItem*)
+void OffspecInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
 {
-    ASSERT_NEVER;
+    if (!dfileItem)
+        return;
+
+    const auto data_shape = dfileItem->axdims();
+    if (axdims().size() != data_shape.size())
+        throw std::runtime_error("Offspec instrument type is incompatible with passed data shape");
+
+    throw std::runtime_error("OffspecInstrumentItem::updateToRealData not yet implemented");
+    // ... set to data_shape[0]
+
+    detectorItem()->setYSize(data_shape[1]);
 }
 
-std::unique_ptr<Frame> DepthprobeInstrumentItem::createFrame() const
+std::unique_ptr<Frame> OffspecInstrumentItem::createFrame() const
 {
     BasicAxisItem* const axis_item = scanItem()->inclinationAxisItem();
     Scale xAxis = axis_item->makeScale("alpha_i (rad)");
-    Scale zAxis = m_z_axis.createAxis("z (nm)");
-    std::vector<const Scale*> axes{xAxis.clone(), zAxis.clone()};
-    return std::make_unique<Frame>(axes);
+    return std::make_unique<Frame>(xAxis.clone(),
+                                   detectorItem()->createOffspecDetector()->axis(1).clone());
 }
 
-ISimulation* DepthprobeInstrumentItem::createSimulation(const MultiLayer& sample) const
+ISimulation* OffspecInstrumentItem::createSimulation(const MultiLayer& sample) const
 {
     const Frame frame = makeFrame();
-    std::unique_ptr<BeamScan> scan = createScan(frame.axis(0));
-    return new DepthprobeSimulation(*scan, sample, frame.axis(1));
+    const auto detector = detectorItem()->createOffspecDetector();
+    std::unique_ptr<PhysicalScan> scan = createScan(frame.axis(0));
+    if (withPolarizer())
+        scan->setPolarization(m_polarizer_bloch_vector);
+    if (withAnalyzer())
+        detector->setAnalyzer(m_analyzer_bloch_vector); // offspec uses detector analyzer, not scan
+    auto* result = new OffspecSimulation(*scan, sample, *detector);
+
+    if (const auto background = backgroundItem()->createBackground())
+        result->setBackground(*background);
+    return result;
 }
 
-void DepthprobeInstrumentItem::writeTo(QXmlStreamWriter* w) const
+void OffspecInstrumentItem::writeTo(QXmlStreamWriter* w) const
 {
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
@@ -542,13 +537,13 @@ void DepthprobeInstrumentItem::writeTo(QXmlStreamWriter* w) const
     ScanningFunctionality::writeScanTo(w);
     w->writeEndElement();
 
-    // z axis
-    w->writeStartElement(Tag::ZAxis);
-    m_z_axis.writeTo(w);
+    // detector
+    w->writeStartElement(Tag::Detector);
+    m_detector->writeTo(w);
     w->writeEndElement();
 }
 
-void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r)
+void OffspecInstrumentItem::readFrom(QXmlStreamReader* r)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -566,9 +561,9 @@ void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r)
             ScanningFunctionality::readScanFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
-            // z axis
-        } else if (tag == Tag::ZAxis) {
-            m_z_axis.readFrom(r);
+            // detector
+        } else if (tag == Tag::Detector) {
+            m_detector->readFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
         } else
@@ -577,60 +572,91 @@ void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r)
 }
 
 //  ************************************************************************************************
-//  class OffspecInstrumentItem
+//  class SpecularInstrumentItem
 //  ************************************************************************************************
 
-OffspecInstrumentItem::OffspecInstrumentItem()
-    : ScanningFunctionality(1e8)
-    , m_detector(new OffspecDetectorItem)
+SpecularInstrumentItem::SpecularInstrumentItem()
+    : ScanningFunctionality(1e6)
 {
 }
 
-std::vector<int> OffspecInstrumentItem::axdims() const
+std::vector<int> SpecularInstrumentItem::axdims() const
 {
-    return {scanItem()->grazingScanItem()->nBins(), detectorItem()->ySize()};
+    return {scanItem()->inclinationAxisItem()->size()};
 }
 
-void OffspecInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
+void SpecularInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
 {
-    if (!dfileItem)
-        return;
+    if (axdims().size() != dfileItem->axdims().size())
+        throw std::runtime_error("Specular instrument type is incompatible with passed data shape");
 
-    const auto data_shape = dfileItem->axdims();
-    if (axdims().size() != data_shape.size())
-        throw std::runtime_error("Offspec instrument type is incompatible with passed data shape");
+    const auto& dataAxis = dfileItem->dataItem()->c_field()->axis(0);
+    scanItem()->updateToData(dataAxis);
+    scanItem()->grazingScanItem()->updateAxIndicators(makeFrame());
+}
 
-    throw std::runtime_error("OffspecInstrumentItem::updateToRealData not yet implemented");
-    // ... set to data_shape[0]
+bool SpecularInstrumentItem::alignedWith(const DatafileItem* dfileItem) const
+{
+    if (!dfileItem->holdsDimensionalData())
+        return scanItem()->grazingScanItem()->uniformAlphaAxisSelected()
+               && axdims() == dfileItem->axdims();
 
-    detectorItem()->setYSize(data_shape[1]);
+    if (!scanItem()->grazingScanItem()->pointwiseAlphaAxisSelected())
+        return false;
+
+    const auto* axisItem =
+        dynamic_cast<const PointwiseAxisItem*>(scanItem()->grazingScanItem()->alphaAxisItem());
+    ASSERT(axisItem);
+
+    const auto* instrumentAxis = axisItem->axis();
+    if (!instrumentAxis)
+        return false;
+
+    const auto& native_axis = dfileItem->dataItem()->c_field()->axis(0);
+    return *instrumentAxis == native_axis;
 }
 
-std::unique_ptr<Frame> OffspecInstrumentItem::createFrame() const
+std::unique_ptr<Frame> SpecularInstrumentItem::createFrame() const
 {
-    BasicAxisItem* const axis_item = scanItem()->inclinationAxisItem();
-    Scale xAxis = axis_item->makeScale("alpha_i (rad)");
-    return std::make_unique<Frame>(xAxis.clone(),
-                                   detectorItem()->createOffspecDetector()->axis(1).clone());
+    auto* axis_item = scanItem()->inclinationAxisItem();
+    ASSERT(axis_item);
+
+    if (auto* pointwise_axis = dynamic_cast<PointwiseAxisItem*>(axis_item)) {
+        const Scale* pAxis = pointwise_axis->axis();
+        if (!pAxis) // workaround for loading project
+            return {};
+
+        if (pAxis->unit() == "1/nm") {
+            double lambda = scanItem()->wavelength();
+            Scale ax =
+                pAxis->transformedScale(Coordinate("alpha_i", "rad").label(), [lambda](double qz) {
+                    return std::asin(qz * lambda / 4 / pi);
+                });
+            return std::make_unique<Frame>(ax.clone());
+        }
+        return std::make_unique<Frame>(pAxis->clone());
+    }
+
+    Scale axis = axis_item->makeScale("alpha_i (rad)");
+    return std::make_unique<Frame>(axis.clone());
 }
 
-ISimulation* OffspecInstrumentItem::createSimulation(const MultiLayer& sample) const
+ISimulation* SpecularInstrumentItem::createSimulation(const MultiLayer& sample) const
 {
-    const Frame frame = makeFrame();
-    const auto detector = detectorItem()->createOffspecDetector();
-    std::unique_ptr<PhysicalScan> scan = createScan(frame.axis(0));
+    auto frame = createFrame();
+    std::unique_ptr<BeamScan> scan = createScan(frame->axis(0));
     if (withPolarizer())
         scan->setPolarization(m_polarizer_bloch_vector);
     if (withAnalyzer())
-        detector->setAnalyzer(m_analyzer_bloch_vector); // offspec uses detector analyzer, not scan
-    auto* result = new OffspecSimulation(*scan, sample, *detector);
+        scan->setAnalyzer(m_analyzer_bloch_vector);
+    auto* result = new SpecularSimulation(*scan, sample);
 
     if (const auto background = backgroundItem()->createBackground())
         result->setBackground(*background);
     return result;
 }
 
-void OffspecInstrumentItem::writeTo(QXmlStreamWriter* w) const
+void SpecularInstrumentItem::writeTo(QXmlStreamWriter* w) const
 {
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
@@ -643,14 +669,9 @@ void OffspecInstrumentItem::writeTo(QXmlStreamWriter* w) const
     w->writeStartElement(Tag::ScanParameters);
     ScanningFunctionality::writeScanTo(w);
     w->writeEndElement();
-
-    // detector
-    w->writeStartElement(Tag::Detector);
-    m_detector->writeTo(w);
-    w->writeEndElement();
 }
 
-void OffspecInstrumentItem::readFrom(QXmlStreamReader* r)
+void SpecularInstrumentItem::readFrom(QXmlStreamReader* r)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -668,93 +689,76 @@ void OffspecInstrumentItem::readFrom(QXmlStreamReader* r)
             ScanningFunctionality::readScanFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
-            // detector
-        } else if (tag == Tag::Detector) {
-            m_detector->readFrom(r);
-            XML::gotoEndElementOfTag(r, tag);
-
         } else
             r->skipCurrentElement();
     }
 }
 
 //  ************************************************************************************************
-//  class GISASInstrumentItem
+//  class DepthprobeInstrumentItem
 //  ************************************************************************************************
 
-GISASInstrumentItem::GISASInstrumentItem()
+DepthprobeInstrumentItem::DepthprobeInstrumentItem()
+    : ScanningFunctionality(1e8)
 {
-    m_detector_item = std::make_unique<DetectorItem>();
-    m_beam_item = std::make_unique<BeamItem>();
+    auto* axisItem = scanItem()->inclinationAxisItem();
+    axisItem->setMin(0.0);
+    axisItem->setMax(1.0);
+    axisItem->resize(500);
+
+    m_z_axis.initMin("Min (nm)", "Starting value below sample horizon", -100.0,
+                     RealLimits::limitless());
+    m_z_axis.initMax("Max (nm)", "Ending value above sample horizon", 100.0,
+                     RealLimits::limitless());
 }
 
-std::vector<int> GISASInstrumentItem::axdims() const
+std::vector<int> DepthprobeInstrumentItem::axdims() const
 {
-    ASSERT(detectorItem());
-    return {(int)detectorItem()->phiAxis().nbins(), (int)detectorItem()->alphaAxis().nbins()};
+    return {}; // no certain shape to avoid linking to real data
 }
 
-void GISASInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
+void DepthprobeInstrumentItem::updateToRealData(const DatafileItem*)
 {
-    if (!dfileItem)
-        return;
-
-    const auto data_shape = dfileItem->axdims();
-    if (axdims().size() != data_shape.size())
-        throw std::runtime_error("GISAS instrument type is incompatible with passed data shape.");
-    ASSERT(detectorItem());
-    detectorItem()->phiAxis().setNbins(data_shape[0]);
-    detectorItem()->alphaAxis().setNbins(data_shape[1]);
+    ASSERT_NEVER;
 }
 
-std::unique_ptr<Frame> GISASInstrumentItem::createFrame() const
+std::unique_ptr<Frame> DepthprobeInstrumentItem::createFrame() const
 {
-    return std::make_unique<Frame>(normalDetector()->clippedFrame());
+    BasicAxisItem* const axis_item = scanItem()->inclinationAxisItem();
+    Scale xAxis = axis_item->makeScale("alpha_i (rad)");
+    Scale zAxis = m_z_axis.createAxis("z (nm)");
+    std::vector<const Scale*> axes{xAxis.clone(), zAxis.clone()};
+    return std::make_unique<Frame>(axes);
 }
 
-ISimulation* GISASInstrumentItem::createSimulation(const MultiLayer& sample) const
+ISimulation* DepthprobeInstrumentItem::createSimulation(const MultiLayer& sample) const
 {
-    const auto beam = beamItem()->createBeam();
-    if (withPolarizer())
-        beam->setPolarization(m_polarizer_bloch_vector);
-    const auto detector = detectorItem()->createDetector();
-    if (withAnalyzer())
-        detector->setAnalyzer(m_analyzer_bloch_vector);
-    auto* result = new ScatteringSimulation(*beam, sample, *detector);
-
-    setBeamDistribution(ParameterDistribution::BeamWavelength, beamItem()->wavelengthItem(),
-                        result);
-    setBeamDistribution(ParameterDistribution::BeamInclinationAngle,
-                        beamItem()->beamDistributionItem(), result);
-    setBeamDistribution(ParameterDistribution::BeamAzimuthalAngle, beamItem()->azimuthalAngleItem(),
-                        result);
-
-    if (const auto background = backgroundItem()->createBackground())
-        result->setBackground(*background);
-    return result;
+    const Frame frame = makeFrame();
+    std::unique_ptr<BeamScan> scan = createScan(frame.axis(0));
+    return new DepthprobeSimulation(*scan, sample, frame.axis(1));
 }
 
-void GISASInstrumentItem::writeTo(QXmlStreamWriter* w) const
+void DepthprobeInstrumentItem::writeTo(QXmlStreamWriter* w) const
 {
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
-    // parameters from base class
+    // instrument parameters from base class
     w->writeStartElement(Tag::BaseData);
     InstrumentItem::writeTo(w);
     w->writeEndElement();
 
-    // beam
-    w->writeStartElement(Tag::Beam);
-    m_beam_item->writeTo(w);
+    // scan parameters from base class
+    w->writeStartElement(Tag::ScanParameters);
+    ScanningFunctionality::writeScanTo(w);
     w->writeEndElement();
 
-    // detector
-    w->writeStartElement(Tag::Detector);
-    m_detector_item->writeTo(w);
+    // z axis
+    w->writeStartElement(Tag::ZAxis);
+    m_z_axis.writeTo(w);
     w->writeEndElement();
 }
 
-void GISASInstrumentItem::readFrom(QXmlStreamReader* r)
+void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -762,27 +766,22 @@ void GISASInstrumentItem::readFrom(QXmlStreamReader* r)
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
 
-        // parameters from base class
+        // instrument parameters from base class
         if (tag == Tag::BaseData) {
             InstrumentItem::readFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
-            // beam
-        } else if (tag == Tag::Beam) {
-            m_beam_item->readFrom(r);
+            // scan parameters from base class
+        } else if (tag == Tag::ScanParameters) {
+            ScanningFunctionality::readScanFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
-            // detector
-        } else if (tag == Tag::Detector) {
-            m_detector_item->readFrom(r);
+            // z axis
+        } else if (tag == Tag::ZAxis) {
+            m_z_axis.readFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
         } else
             r->skipCurrentElement();
     }
 }
-
-std::unique_ptr<IDetector> GISASInstrumentItem::normalDetector() const
-{
-    return detectorItem()->createDetector();
-}
diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h
index b9662308e95..d85db407f57 100644
--- a/GUI/Model/Device/InstrumentItems.h
+++ b/GUI/Model/Device/InstrumentItems.h
@@ -126,27 +126,34 @@ private:
 };
 
 
-class SpecularInstrumentItem : public InstrumentItem, public ScanningFunctionality {
+class GISASInstrumentItem : public InstrumentItem {
 public:
-    SpecularInstrumentItem();
-    QString instrumentType() const override { return "Specular"; }
+    GISASInstrumentItem();
 
+    QString instrumentType() const override { return "Scatter2D"; }
     std::vector<int> axdims() const override;
     void updateToRealData(const DatafileItem* dfileItem) override;
-    bool alignedWith(const DatafileItem* dfileItem) const override;
     std::unique_ptr<Frame> createFrame() const override;
     ISimulation* createSimulation(const MultiLayer& sample) const override;
-
     void writeTo(QXmlStreamWriter* w) const override;
     void readFrom(QXmlStreamReader* r) override;
+
+    BeamItem* beamItem() const { return m_beam_item.get(); }
+    DetectorItem* detectorItem() const { return m_detector_item.get(); }
+
+    std::unique_ptr<IDetector> normalDetector() const;
+
+private:
+    std::unique_ptr<BeamItem> m_beam_item;
+    std::unique_ptr<DetectorItem> m_detector_item;
 };
 
 
-class DepthprobeInstrumentItem : public InstrumentItem, public ScanningFunctionality {
+class OffspecInstrumentItem : public InstrumentItem, public ScanningFunctionality {
 public:
-    DepthprobeInstrumentItem();
+    OffspecInstrumentItem();
 
-    QString instrumentType() const override { return "Depthprobe"; }
+    QString instrumentType() const override { return "Offspecular"; }
     std::vector<int> axdims() const override;
     void updateToRealData(const DatafileItem* dfileItem) override;
     std::unique_ptr<Frame> createFrame() const override;
@@ -154,37 +161,34 @@ public:
     void writeTo(QXmlStreamWriter* w) const override;
     void readFrom(QXmlStreamReader* r) override;
 
-    AxisProperty& zAxis() { return m_z_axis; }
+    OffspecDetectorItem* detectorItem() const { return m_detector.get(); }
 
 private:
-    AxisProperty m_z_axis;
+    std::unique_ptr<OffspecDetectorItem> m_detector;
 };
 
 
-class OffspecInstrumentItem : public InstrumentItem, public ScanningFunctionality {
+class SpecularInstrumentItem : public InstrumentItem, public ScanningFunctionality {
 public:
-    OffspecInstrumentItem();
+    SpecularInstrumentItem();
+    QString instrumentType() const override { return "Specular"; }
 
-    QString instrumentType() const override { return "Offspecular"; }
     std::vector<int> axdims() const override;
     void updateToRealData(const DatafileItem* dfileItem) override;
+    bool alignedWith(const DatafileItem* dfileItem) const override;
     std::unique_ptr<Frame> createFrame() const override;
     ISimulation* createSimulation(const MultiLayer& sample) const override;
+
     void writeTo(QXmlStreamWriter* w) const override;
     void readFrom(QXmlStreamReader* r) override;
-
-    OffspecDetectorItem* detectorItem() const { return m_detector.get(); }
-
-private:
-    std::unique_ptr<OffspecDetectorItem> m_detector;
 };
 
 
-class GISASInstrumentItem : public InstrumentItem {
+class DepthprobeInstrumentItem : public InstrumentItem, public ScanningFunctionality {
 public:
-    GISASInstrumentItem();
+    DepthprobeInstrumentItem();
 
-    QString instrumentType() const override { return "Scatter2D"; }
+    QString instrumentType() const override { return "Depthprobe"; }
     std::vector<int> axdims() const override;
     void updateToRealData(const DatafileItem* dfileItem) override;
     std::unique_ptr<Frame> createFrame() const override;
@@ -192,14 +196,10 @@ public:
     void writeTo(QXmlStreamWriter* w) const override;
     void readFrom(QXmlStreamReader* r) override;
 
-    BeamItem* beamItem() const { return m_beam_item.get(); }
-    DetectorItem* detectorItem() const { return m_detector_item.get(); }
-
-    std::unique_ptr<IDetector> normalDetector() const;
+    AxisProperty& zAxis() { return m_z_axis; }
 
 private:
-    std::unique_ptr<BeamItem> m_beam_item;
-    std::unique_ptr<DetectorItem> m_detector_item;
+    AxisProperty m_z_axis;
 };
 
 
-- 
GitLab


From bccdb8d4218fd8192070e2eea69f6bfd26dbc25c Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 17:50:27 +0100
Subject: [PATCH 020/108] rename class and sources
 GUI/View/Instrument/GISASInstrumentEditor ->
 GUI/View/Instrument/Scatter2DInstrumentEditor

---
 ...entEditor.cpp => Scatter2DInstrumentEditor.cpp} |  8 ++++----
 ...trumentEditor.h => Scatter2DInstrumentEditor.h} | 14 +++++++-------
 GUI/View/Views/InstrumentView.cpp                  |  4 ++--
 3 files changed, 13 insertions(+), 13 deletions(-)
 rename GUI/View/Instrument/{GISASInstrumentEditor.cpp => Scatter2DInstrumentEditor.cpp} (87%)
 rename GUI/View/Instrument/{GISASInstrumentEditor.h => Scatter2DInstrumentEditor.h} (61%)

diff --git a/GUI/View/Instrument/GISASInstrumentEditor.cpp b/GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
similarity index 87%
rename from GUI/View/Instrument/GISASInstrumentEditor.cpp
rename to GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
index 3ea79b2f8d5..3fff673accd 100644
--- a/GUI/View/Instrument/GISASInstrumentEditor.cpp
+++ b/GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/View/Instrument/GISASInstrumentEditor.cpp
-//! @brief     Implements class GISASInstrumentEditor.
+//! @file      GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
+//! @brief     Implements class Scatter2DInstrumentEditor.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,7 +12,7 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/View/Instrument/GISASInstrumentEditor.h"
+#include "GUI/View/Instrument/Scatter2DInstrumentEditor.h"
 #include "Base/Util/Assert.h"
 #include "GUI/Model/Device/InstrumentItems.h"
 #include "GUI/View/Device/BackgroundForm.h"
@@ -20,7 +20,7 @@
 #include "GUI/View/Device/GISASBeamEditor.h"
 #include "GUI/View/Device/PolarizationAnalysisEditor.h"
 
-GISASInstrumentEditor::GISASInstrumentEditor(GISASInstrumentItem* instrument)
+Scatter2DInstrumentEditor::Scatter2DInstrumentEditor(GISASInstrumentItem* instrument)
 {
     ASSERT(instrument);
     auto* layout = new QVBoxLayout(this);
diff --git a/GUI/View/Instrument/GISASInstrumentEditor.h b/GUI/View/Instrument/Scatter2DInstrumentEditor.h
similarity index 61%
rename from GUI/View/Instrument/GISASInstrumentEditor.h
rename to GUI/View/Instrument/Scatter2DInstrumentEditor.h
index e9797f949ed..6141d02b8cb 100644
--- a/GUI/View/Instrument/GISASInstrumentEditor.h
+++ b/GUI/View/Instrument/Scatter2DInstrumentEditor.h
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/View/Instrument/GISASInstrumentEditor.h
-//! @brief     Defines class GISASInstrumentEditor.
+//! @file      GUI/View/Instrument/Scatter2DInstrumentEditor.h
+//! @brief     Defines class Scatter2DInstrumentEditor.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_GUI_VIEW_INSTRUMENT_GISASINSTRUMENTEDITOR_H
-#define BORNAGAIN_GUI_VIEW_INSTRUMENT_GISASINSTRUMENTEDITOR_H
+#ifndef BORNAGAIN_GUI_VIEW_INSTRUMENT_SCATTER2DINSTRUMENTEDITOR_H
+#define BORNAGAIN_GUI_VIEW_INSTRUMENT_SCATTER2DINSTRUMENTEDITOR_H
 
 #include "GUI/View/Widget/IComponentEditor.h"
 
@@ -21,10 +21,10 @@ class GISASInstrumentItem;
 
 //! Editor for GISAS instruments, for use in main scroll area of InstrumentView.
 
-class GISASInstrumentEditor : public IComponentEditor {
+class Scatter2DInstrumentEditor : public IComponentEditor {
     Q_OBJECT
 public:
-    GISASInstrumentEditor(GISASInstrumentItem* instrument);
+    Scatter2DInstrumentEditor(GISASInstrumentItem* instrument);
 };
 
-#endif // BORNAGAIN_GUI_VIEW_INSTRUMENT_GISASINSTRUMENTEDITOR_H
+#endif // BORNAGAIN_GUI_VIEW_INSTRUMENT_SCATTER2DINSTRUMENTEDITOR_H
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 88449921609..03dbc6bf842 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -18,8 +18,8 @@
 #include "GUI/Model/Device/InstrumentsSet.h"
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/View/Instrument/DepthprobeInstrumentEditor.h"
-#include "GUI/View/Instrument/GISASInstrumentEditor.h"
 #include "GUI/View/Instrument/OffspecInstrumentEditor.h"
+#include "GUI/View/Instrument/Scatter2DInstrumentEditor.h"
 #include "GUI/View/Instrument/SpecularInstrumentEditor.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/InstrumentsQListView.h"
@@ -120,7 +120,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
     else if (auto* ii = dynamic_cast<OffspecInstrumentItem*>(currentInstrument))
         editor = new OffspecInstrumentEditor(ii);
     else if (auto* ii = dynamic_cast<GISASInstrumentItem*>(currentInstrument))
-        editor = new GISASInstrumentEditor(ii);
+        editor = new Scatter2DInstrumentEditor(ii);
     else if (auto* ii = dynamic_cast<DepthprobeInstrumentItem*>(currentInstrument))
         editor = new DepthprobeInstrumentEditor(ii);
     else
-- 
GitLab


From 290aa0b19b2c5313ea02317f487566f81d008c4f Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 17:50:31 +0100
Subject: [PATCH 021/108] replace 'GISASInstr' by 'Scatter2DInstr'

---
 GUI/Model/Device/InstrumentItems.cpp           | 18 +++++++++---------
 GUI/Model/Device/InstrumentItems.h             |  4 ++--
 GUI/Model/Device/InstrumentsCatalog.cpp        |  4 ++--
 GUI/Model/FromCore/ItemizeSimulation.cpp       |  8 ++++----
 GUI/Model/Job/JobItem.cpp                      |  8 ++++----
 GUI/Model/Job/ParameterTreeBuilder.cpp         |  2 +-
 GUI/View/Device/DetectorEditor.cpp             |  2 +-
 GUI/View/Device/DetectorEditor.h               |  4 ++--
 GUI/View/Device/GISASBeamEditor.h              |  2 +-
 .../Instrument/Scatter2DInstrumentEditor.cpp   |  2 +-
 .../Instrument/Scatter2DInstrumentEditor.h     |  4 ++--
 GUI/View/List/InstrumentsQListView.cpp         |  2 +-
 GUI/View/List/InstrumentsQModel.cpp            |  4 ++--
 GUI/View/List/InstrumentsQModel.h              |  2 +-
 GUI/View/Views/InstrumentView.cpp              |  2 +-
 Tests/Unit/GUI/TestAutosaveController.cpp      |  6 +++---
 Tests/Unit/GUI/TestDatafilesModel.cpp          |  2 +-
 Tests/Unit/GUI/TestInstrumentsSet.cpp          |  4 ++--
 Tests/Unit/GUI/TestJobModel.cpp                |  6 +++---
 Tests/Unit/GUI/TestLinkInstrument.cpp          |  2 +-
 Tests/Unit/GUI/TestProjectDocument.cpp         |  6 +++---
 21 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index 181bd7ecf0c..348160516b9 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -361,22 +361,22 @@ void ScanningFunctionality::readScanFrom(QXmlStreamReader* r)
 }
 
 //  ************************************************************************************************
-//  class GISASInstrumentItem
+//  class Scatter2DInstrumentItem
 //  ************************************************************************************************
 
-GISASInstrumentItem::GISASInstrumentItem()
+Scatter2DInstrumentItem::Scatter2DInstrumentItem()
 {
     m_detector_item = std::make_unique<DetectorItem>();
     m_beam_item = std::make_unique<BeamItem>();
 }
 
-std::vector<int> GISASInstrumentItem::axdims() const
+std::vector<int> Scatter2DInstrumentItem::axdims() const
 {
     ASSERT(detectorItem());
     return {(int)detectorItem()->phiAxis().nbins(), (int)detectorItem()->alphaAxis().nbins()};
 }
 
-void GISASInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
+void Scatter2DInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
 {
     if (!dfileItem)
         return;
@@ -389,12 +389,12 @@ void GISASInstrumentItem::updateToRealData(const DatafileItem* dfileItem)
     detectorItem()->alphaAxis().setNbins(data_shape[1]);
 }
 
-std::unique_ptr<Frame> GISASInstrumentItem::createFrame() const
+std::unique_ptr<Frame> Scatter2DInstrumentItem::createFrame() const
 {
     return std::make_unique<Frame>(normalDetector()->clippedFrame());
 }
 
-ISimulation* GISASInstrumentItem::createSimulation(const MultiLayer& sample) const
+ISimulation* Scatter2DInstrumentItem::createSimulation(const MultiLayer& sample) const
 {
     const auto beam = beamItem()->createBeam();
     if (withPolarizer())
@@ -416,7 +416,7 @@ ISimulation* GISASInstrumentItem::createSimulation(const MultiLayer& sample) con
     return result;
 }
 
-void GISASInstrumentItem::writeTo(QXmlStreamWriter* w) const
+void Scatter2DInstrumentItem::writeTo(QXmlStreamWriter* w) const
 {
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
@@ -436,7 +436,7 @@ void GISASInstrumentItem::writeTo(QXmlStreamWriter* w) const
     w->writeEndElement();
 }
 
-void GISASInstrumentItem::readFrom(QXmlStreamReader* r)
+void Scatter2DInstrumentItem::readFrom(QXmlStreamReader* r)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -464,7 +464,7 @@ void GISASInstrumentItem::readFrom(QXmlStreamReader* r)
     }
 }
 
-std::unique_ptr<IDetector> GISASInstrumentItem::normalDetector() const
+std::unique_ptr<IDetector> Scatter2DInstrumentItem::normalDetector() const
 {
     return detectorItem()->createDetector();
 }
diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h
index d85db407f57..ab7250066c6 100644
--- a/GUI/Model/Device/InstrumentItems.h
+++ b/GUI/Model/Device/InstrumentItems.h
@@ -126,9 +126,9 @@ private:
 };
 
 
-class GISASInstrumentItem : public InstrumentItem {
+class Scatter2DInstrumentItem : public InstrumentItem {
 public:
-    GISASInstrumentItem();
+    Scatter2DInstrumentItem();
 
     QString instrumentType() const override { return "Scatter2D"; }
     std::vector<int> axdims() const override;
diff --git a/GUI/Model/Device/InstrumentsCatalog.cpp b/GUI/Model/Device/InstrumentsCatalog.cpp
index a00853df361..b27f61407c6 100644
--- a/GUI/Model/Device/InstrumentsCatalog.cpp
+++ b/GUI/Model/Device/InstrumentsCatalog.cpp
@@ -20,7 +20,7 @@ InstrumentItem* InstrumentsCatalog::create(Type type)
 {
     switch (type) {
     case Type::GISAS:
-        return new GISASInstrumentItem();
+        return new Scatter2DInstrumentItem();
     case Type::Offspec:
         return new OffspecInstrumentItem();
     case Type::Specular:
@@ -53,7 +53,7 @@ UiInfo InstrumentsCatalog::uiInfo(Type type)
 
 InstrumentsCatalog::Type InstrumentsCatalog::type(const InstrumentItem* item)
 {
-    if (dynamic_cast<const GISASInstrumentItem*>(item))
+    if (dynamic_cast<const Scatter2DInstrumentItem*>(item))
         return Type::GISAS;
     if (dynamic_cast<const OffspecInstrumentItem*>(item))
         return Type::Offspec;
diff --git a/GUI/Model/FromCore/ItemizeSimulation.cpp b/GUI/Model/FromCore/ItemizeSimulation.cpp
index 67c6d467adf..16a8858398a 100644
--- a/GUI/Model/FromCore/ItemizeSimulation.cpp
+++ b/GUI/Model/FromCore/ItemizeSimulation.cpp
@@ -251,7 +251,7 @@ void setPolarizer2(InstrumentItem* instrument_item, const PolFilter& analyzer)
     instrument_item->setAnalyzerBlochVector(analyzer.BlochVector());
 }
 
-void updateDetector(GISASInstrumentItem* instrument_item, const IDetector& detector)
+void updateDetector(Scatter2DInstrumentItem* instrument_item, const IDetector& detector)
 {
     auto* detector_item = instrument_item->detectorItem();
 
@@ -278,9 +278,9 @@ void setBackground(InstrumentItem* instrument_item, const ISimulation& simulatio
         instrument_item->setBackgroundItemType<PoissonBackgroundItem>();
 }
 
-GISASInstrumentItem* createGISASInstrumentItem(const ScatteringSimulation& simulation)
+Scatter2DInstrumentItem* createScatter2DInstrumentItem(const ScatteringSimulation& simulation)
 {
-    auto* result = new GISASInstrumentItem();
+    auto* result = new Scatter2DInstrumentItem();
     setGISASBeamItem(result->beamItem(), simulation);
     result->setPolarizerBlochVector(simulation.beam().polVector());
     const auto* det = dynamic_cast<const IDetector*>(simulation.getDetector());
@@ -344,7 +344,7 @@ InstrumentItem* GUI::FromCore::itemizeInstrument(const ISimulation& simulation)
     InstrumentItem* result;
 
     if (const auto* sim = dynamic_cast<const ScatteringSimulation*>(&simulation))
-        result = createGISASInstrumentItem(*sim);
+        result = createScatter2DInstrumentItem(*sim);
     else if (const auto* sim = dynamic_cast<const OffspecSimulation*>(&simulation))
         result = createOffspecInstrumentItem(*sim);
     else if (const auto* sim = dynamic_cast<const SpecularSimulation*>(&simulation))
diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index b0b1c960278..2944c8281d8 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -119,7 +119,7 @@ size_t JobItem::rank() const
 {
     if (instrumentItem()->is<SpecularInstrumentItem>())
         return 1;
-    else if (instrumentItem()->is<GISASInstrumentItem>()
+    else if (instrumentItem()->is<Scatter2DInstrumentItem>()
              || instrumentItem()->is<OffspecInstrumentItem>()
              || instrumentItem()->is<DepthprobeInstrumentItem>())
         return 2;
@@ -198,7 +198,7 @@ void JobItem::adjustReaDataToJobInstrument()
         m_dfile_item->data1DItem()->setDatafield(
             {frame.release(), old->flatVector(), old->errorSigmas()});
 
-    } else if (instrumentItem()->is<GISASInstrumentItem>()) {
+    } else if (instrumentItem()->is<Scatter2DInstrumentItem>()) {
 
         // Before copying masks on board of detector we need to ensure that
         // mask items are represented in proper coordinates.
@@ -212,7 +212,7 @@ void JobItem::adjustReaDataToJobInstrument()
 
 void JobItem::importMasksFromDatafileItem()
 {
-    if (auto* iiI = dynamic_cast<GISASInstrumentItem*>(instrumentItem()))
+    if (auto* iiI = dynamic_cast<Scatter2DInstrumentItem*>(instrumentItem()))
         if (const auto* d2i = dfileItem()->data2DItem())
             if (const auto* container = d2i->masksSet())
                 iiI->detectorItem()->importMasks(container);
@@ -234,7 +234,7 @@ void JobItem::convertMaskCoords()
 //! Crops DatafileItem to the region of interest.
 void JobItem::cropRealData()
 {
-    auto* iiI = dynamic_cast<GISASInstrumentItem*>(instrumentItem());
+    auto* iiI = dynamic_cast<Scatter2DInstrumentItem*>(instrumentItem());
     ASSERT(iiI);
 
     // Adjust real data to the size of region of interest
diff --git a/GUI/Model/Job/ParameterTreeBuilder.cpp b/GUI/Model/Job/ParameterTreeBuilder.cpp
index 7fe8fbf8e97..0a810fdee4a 100644
--- a/GUI/Model/Job/ParameterTreeBuilder.cpp
+++ b/GUI/Model/Job/ParameterTreeBuilder.cpp
@@ -317,7 +317,7 @@ void ParameterTreeBuilder::addInstrument()
     auto* label = new ParameterLabelItem(iI->instrumentType() + " instrument",
                                          parameterContainerItem()->parameterTreeRoot());
 
-    if (auto* iiI = dynamic_cast<GISASInstrumentItem*>(iI)) {
+    if (auto* iiI = dynamic_cast<Scatter2DInstrumentItem*>(iI)) {
         auto* beamItem = iiI->beamItem();
         auto* beamLabel = new ParameterLabelItem("Beam", label);
         addParameterItem(beamLabel, beamItem->intensity());
diff --git a/GUI/View/Device/DetectorEditor.cpp b/GUI/View/Device/DetectorEditor.cpp
index e7361e0cf21..26fd7791a0b 100644
--- a/GUI/View/Device/DetectorEditor.cpp
+++ b/GUI/View/Device/DetectorEditor.cpp
@@ -24,7 +24,7 @@
 #include "GUI/View/Numeric/SafeSpinBox.h"
 #include <QFormLayout>
 
-DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
+DetectorEditor::DetectorEditor(QWidget* parent, Scatter2DInstrumentItem* instrItem)
     : CollapsibleGroupBox("Detector parameters", parent, instrItem->expandDetector)
 {
     auto* layout = new QVBoxLayout;
diff --git a/GUI/View/Device/DetectorEditor.h b/GUI/View/Device/DetectorEditor.h
index 8b1bbeb8b3f..bbc810cbd65 100644
--- a/GUI/View/Device/DetectorEditor.h
+++ b/GUI/View/Device/DetectorEditor.h
@@ -17,14 +17,14 @@
 
 #include "GUI/View/Widget/GroupBoxes.h"
 
-class GISASInstrumentItem;
+class Scatter2DInstrumentItem;
 
 //! Detector section in GISAS instrument form.
 
 class DetectorEditor : public CollapsibleGroupBox {
     Q_OBJECT
 public:
-    DetectorEditor(QWidget* parent, GISASInstrumentItem* item);
+    DetectorEditor(QWidget* parent, Scatter2DInstrumentItem* item);
 
 signals:
     void dataChanged();
diff --git a/GUI/View/Device/GISASBeamEditor.h b/GUI/View/Device/GISASBeamEditor.h
index 9badf25b1fc..db5616de9d4 100644
--- a/GUI/View/Device/GISASBeamEditor.h
+++ b/GUI/View/Device/GISASBeamEditor.h
@@ -19,7 +19,7 @@
 
 class BeamItem;
 
-//! GISAS beam editor. Operates on GISASInstrumentItem.
+//! GISAS beam editor. Operates on Scatter2DInstrumentItem.
 
 class GISASBeamEditor : public CollapsibleGroupBox {
     Q_OBJECT
diff --git a/GUI/View/Instrument/Scatter2DInstrumentEditor.cpp b/GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
index 3fff673accd..9d534289298 100644
--- a/GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
+++ b/GUI/View/Instrument/Scatter2DInstrumentEditor.cpp
@@ -20,7 +20,7 @@
 #include "GUI/View/Device/GISASBeamEditor.h"
 #include "GUI/View/Device/PolarizationAnalysisEditor.h"
 
-Scatter2DInstrumentEditor::Scatter2DInstrumentEditor(GISASInstrumentItem* instrument)
+Scatter2DInstrumentEditor::Scatter2DInstrumentEditor(Scatter2DInstrumentItem* instrument)
 {
     ASSERT(instrument);
     auto* layout = new QVBoxLayout(this);
diff --git a/GUI/View/Instrument/Scatter2DInstrumentEditor.h b/GUI/View/Instrument/Scatter2DInstrumentEditor.h
index 6141d02b8cb..1b5b37db4f5 100644
--- a/GUI/View/Instrument/Scatter2DInstrumentEditor.h
+++ b/GUI/View/Instrument/Scatter2DInstrumentEditor.h
@@ -17,14 +17,14 @@
 
 #include "GUI/View/Widget/IComponentEditor.h"
 
-class GISASInstrumentItem;
+class Scatter2DInstrumentItem;
 
 //! Editor for GISAS instruments, for use in main scroll area of InstrumentView.
 
 class Scatter2DInstrumentEditor : public IComponentEditor {
     Q_OBJECT
 public:
-    Scatter2DInstrumentEditor(GISASInstrumentItem* instrument);
+    Scatter2DInstrumentEditor(Scatter2DInstrumentItem* instrument);
 };
 
 #endif // BORNAGAIN_GUI_VIEW_INSTRUMENT_SCATTER2DINSTRUMENTEDITOR_H
diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index b431a5daec5..c3828c0819c 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -37,7 +37,7 @@ InstrumentsQListView::InstrumentsQListView()
     setItemDelegate(new ListItemDelegate(this));
 
     connect(gActions->new_gisas_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::addNewGISASInstrument);
+            &InstrumentsQModel::addNewScatter2DInstrument);
 
     connect(gActions->new_offspec_instrument, &QAction::triggered, m_model,
             &InstrumentsQModel::addNewOffspecInstrument);
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index ae04aad7e7d..df41e97aa7c 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -47,9 +47,9 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     }
 }
 
-QModelIndex InstrumentsQModel::addNewGISASInstrument()
+QModelIndex InstrumentsQModel::addNewScatter2DInstrument()
 {
-    auto* t = new GISASInstrumentItem;
+    auto* t = new Scatter2DInstrumentItem;
     t->setInstrumentName("GISAS");
     return pushInstrument(t);
 }
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index f433d414359..65538d38613 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -29,7 +29,7 @@ public:
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 
-    QModelIndex addNewGISASInstrument();
+    QModelIndex addNewScatter2DInstrument();
     QModelIndex addNewOffspecInstrument();
     QModelIndex addNewSpecularInstrument();
     QModelIndex addNewDepthprobeInstrument();
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 03dbc6bf842..72751873c2e 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -119,7 +119,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
         editor = new SpecularInstrumentEditor(ii);
     else if (auto* ii = dynamic_cast<OffspecInstrumentItem*>(currentInstrument))
         editor = new OffspecInstrumentEditor(ii);
-    else if (auto* ii = dynamic_cast<GISASInstrumentItem*>(currentInstrument))
+    else if (auto* ii = dynamic_cast<Scatter2DInstrumentItem*>(currentInstrument))
         editor = new Scatter2DInstrumentEditor(ii);
     else if (auto* ii = dynamic_cast<DepthprobeInstrumentItem*>(currentInstrument))
         editor = new DepthprobeInstrumentEditor(ii);
diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index d36c18d51b5..2a6b1092278 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -38,7 +38,7 @@ TEST_F(TestAutosaveController, autoSaveController)
     const int autosave_time(100);
 
     gDoc = std::make_unique<ProjectDocument>();
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
     gDoc->saveProjectFileWithData(projectFileName);
@@ -83,7 +83,7 @@ TEST_F(TestAutosaveController, autoSaveController)
 TEST_F(TestAutosaveController, autoSaveControllerNewDocument)
 {
     gDoc = std::make_unique<ProjectDocument>();
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
 
@@ -118,7 +118,7 @@ TEST_F(TestAutosaveController, autosaveEnabled)
     EXPECT_TRUE(gDoc);
 
     gDoc->setProjectFullPath(projectFileName);
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
 
diff --git a/Tests/Unit/GUI/TestDatafilesModel.cpp b/Tests/Unit/GUI/TestDatafilesModel.cpp
index 18a62a3230b..42a09d5b816 100644
--- a/Tests/Unit/GUI/TestDatafilesModel.cpp
+++ b/Tests/Unit/GUI/TestDatafilesModel.cpp
@@ -97,7 +97,7 @@ TEST(TestDatafilesSet, saveXMLData)
     auto* intensity2 = new DatafileItem("Offspec", df2);
     model1.push_back(intensity1);
     model1.push_back(intensity2);
-    auto* t2 = new GISASInstrumentItem;
+    auto* t2 = new Scatter2DInstrumentItem;
     auto* t3 = new OffspecInstrumentItem;
     instrument_model.push_back(t2);
     instrument_model.push_back(t3);
diff --git a/Tests/Unit/GUI/TestInstrumentsSet.cpp b/Tests/Unit/GUI/TestInstrumentsSet.cpp
index 71ce2ec27c0..a7b21f3fb4a 100644
--- a/Tests/Unit/GUI/TestInstrumentsSet.cpp
+++ b/Tests/Unit/GUI/TestInstrumentsSet.cpp
@@ -18,7 +18,7 @@ TEST(TestInstrumentsSet, instrumentAddedRemoved)
     EXPECT_TRUE(spy.isValid());
 
     // populating instrument model
-    auto* p = new GISASInstrumentItem;
+    auto* p = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(p);
 
     // checking that a signal was emitted about the new instrument
@@ -37,7 +37,7 @@ TEST(TestInstrumentsSet, instrumentChanged)
     gDoc = std::make_unique<ProjectDocument>();
 
     // populating instrument model
-    auto* instrument1 = new GISASInstrumentItem;
+    auto* instrument1 = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument1);
     auto* instrument2 = new SpecularInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument2);
diff --git a/Tests/Unit/GUI/TestJobModel.cpp b/Tests/Unit/GUI/TestJobModel.cpp
index 12fc76089ae..ef84dd3035a 100644
--- a/Tests/Unit/GUI/TestJobModel.cpp
+++ b/Tests/Unit/GUI/TestJobModel.cpp
@@ -25,7 +25,7 @@ TEST(TestJobsSet, nonXMLData)
 
     // adding JobItem
     auto* job_item = jobs.createJobItem();
-    auto* instrumentItem = new GISASInstrumentItem();
+    auto* instrumentItem = new Scatter2DInstrumentItem();
     job_item->copyInstrumentIntoJob(instrumentItem);
     job_item->createSimulatedDataItem();
     EXPECT_EQ(jobs.dataItems().size(), 1);
@@ -49,7 +49,7 @@ TEST(TestJobsSet, saveNonXMLData)
 
     // adding JobItem with instrument
     auto* job_item = jobs.createJobItem();
-    auto* instrumentItem = new GISASInstrumentItem();
+    auto* instrumentItem = new Scatter2DInstrumentItem();
     job_item->copyInstrumentIntoJob(instrumentItem);
 
     // create simulated data
@@ -117,7 +117,7 @@ TEST(TestJobsSet, masksToDetector)
 
     // create JobItem
     JobItem job_item;
-    auto* instrumentItem = new GISASInstrumentItem;
+    auto* instrumentItem = new Scatter2DInstrumentItem;
     instrumentItem->detectorItem()->phiAxis().setNbins(nx);
     instrumentItem->detectorItem()->alphaAxis().setNbins(ny);
     job_item.copyInstrumentIntoJob(instrumentItem);
diff --git a/Tests/Unit/GUI/TestLinkInstrument.cpp b/Tests/Unit/GUI/TestLinkInstrument.cpp
index 3d005585f37..a99c8f7045e 100644
--- a/Tests/Unit/GUI/TestLinkInstrument.cpp
+++ b/Tests/Unit/GUI/TestLinkInstrument.cpp
@@ -35,7 +35,7 @@ TEST(TestLinkInstrument, canLinkToGisas)
     gDoc = std::make_unique<ProjectDocument>();
 
     // populating instrument model
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     const QString identifier = instrument->id();
     ASSERT_TRUE(!identifier.isEmpty());
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index 8fedf71ef30..3972c0d4a3f 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -40,7 +40,7 @@ TEST_F(TestProjectDocument, projectDocument)
     EXPECT_EQ(gDoc->projectName(), QString());
     EXPECT_EQ(gDoc->projectFullPath(), QString());
 
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
 
@@ -77,7 +77,7 @@ TEST_F(TestProjectDocument, projectDocumentWithData)
     UTest::GUI::create_dir(projectDir);
     const QString ext = QString(GUI::Util::Project::projectFileExtension);
 
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
     DatafileItem* realData =
@@ -111,7 +111,7 @@ TEST_F(TestProjectDocument, failingProjectSave)
     const QString projectFileName(projectDir + "/document" + ext);
 
     gDoc = std::make_unique<ProjectDocument>();
-    auto* instrument = new GISASInstrumentItem;
+    auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
     instrument->setInstrumentName("GISAS");
     modelsModifier(*gDoc);
-- 
GitLab


From 63f58baef57ebf486fc785b93f643973f98f482a Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 17:52:27 +0100
Subject: [PATCH 022/108] instrument type names in catalog as in
 Item::instrumentType

---
 GUI/Model/Device/InstrumentsCatalog.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/GUI/Model/Device/InstrumentsCatalog.cpp b/GUI/Model/Device/InstrumentsCatalog.cpp
index b27f61407c6..afd9dc997ea 100644
--- a/GUI/Model/Device/InstrumentsCatalog.cpp
+++ b/GUI/Model/Device/InstrumentsCatalog.cpp
@@ -40,13 +40,13 @@ UiInfo InstrumentsCatalog::uiInfo(Type type)
 {
     switch (type) {
     case Type::GISAS:
-        return {"GISAS", "", ""};
+        return {"Scatter2D", "", ""};
     case Type::Offspec:
-        return {"Off specular", "", ""};
+        return {"Offspecular", "", ""};
     case Type::Specular:
         return {"Specular", "", ""};
     case Type::Depthprobe:
-        return {"Depth probe", "", ""};
+        return {"Depthprobe", "", ""};
     }
     ASSERT_NEVER;
 }
-- 
GitLab


From 76f6f98709e168a632f969aa25e2e801cc096a8a Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 17:54:10 +0100
Subject: [PATCH 023/108] rename enum

---
 GUI/Model/Device/InstrumentsCatalog.cpp | 8 ++++----
 GUI/Model/Device/InstrumentsCatalog.h   | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/GUI/Model/Device/InstrumentsCatalog.cpp b/GUI/Model/Device/InstrumentsCatalog.cpp
index afd9dc997ea..50fe1d740db 100644
--- a/GUI/Model/Device/InstrumentsCatalog.cpp
+++ b/GUI/Model/Device/InstrumentsCatalog.cpp
@@ -19,7 +19,7 @@
 InstrumentItem* InstrumentsCatalog::create(Type type)
 {
     switch (type) {
-    case Type::GISAS:
+    case Type::Scatter2D:
         return new Scatter2DInstrumentItem();
     case Type::Offspec:
         return new OffspecInstrumentItem();
@@ -33,13 +33,13 @@ InstrumentItem* InstrumentsCatalog::create(Type type)
 
 QVector<InstrumentsCatalog::Type> InstrumentsCatalog::types()
 {
-    return {Type::GISAS, Type::Offspec, Type::Specular, Type::Depthprobe};
+    return {Type::Scatter2D, Type::Offspec, Type::Specular, Type::Depthprobe};
 }
 
 UiInfo InstrumentsCatalog::uiInfo(Type type)
 {
     switch (type) {
-    case Type::GISAS:
+    case Type::Scatter2D:
         return {"Scatter2D", "", ""};
     case Type::Offspec:
         return {"Offspecular", "", ""};
@@ -54,7 +54,7 @@ UiInfo InstrumentsCatalog::uiInfo(Type type)
 InstrumentsCatalog::Type InstrumentsCatalog::type(const InstrumentItem* item)
 {
     if (dynamic_cast<const Scatter2DInstrumentItem*>(item))
-        return Type::GISAS;
+        return Type::Scatter2D;
     if (dynamic_cast<const OffspecInstrumentItem*>(item))
         return Type::Offspec;
     if (dynamic_cast<const SpecularInstrumentItem*>(item))
diff --git a/GUI/Model/Device/InstrumentsCatalog.h b/GUI/Model/Device/InstrumentsCatalog.h
index 64786dff4f8..dc59798d024 100644
--- a/GUI/Model/Device/InstrumentsCatalog.h
+++ b/GUI/Model/Device/InstrumentsCatalog.h
@@ -26,7 +26,7 @@ public:
     using BaseType = InstrumentItem;
 
     // Do not change the numbering! It is serialized!
-    enum class Type : uint8_t { GISAS = 0, Offspec = 1, Specular = 2, Depthprobe = 3 };
+    enum class Type : uint8_t { Scatter2D = 0, Offspec = 1, Specular = 2, Depthprobe = 3 };
 
     //! Creates the item of the given type.
     static InstrumentItem* create(Type type);
-- 
GitLab


From 63f5eee28280d22cd56df6c8301cb345a32a2162 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 17:56:21 +0100
Subject: [PATCH 024/108] uniform Offspec for Offspecular

---
 GUI/Model/Device/InstrumentItems.h      | 2 +-
 GUI/Model/Device/InstrumentsCatalog.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h
index ab7250066c6..03a497fb8f7 100644
--- a/GUI/Model/Device/InstrumentItems.h
+++ b/GUI/Model/Device/InstrumentItems.h
@@ -153,7 +153,7 @@ class OffspecInstrumentItem : public InstrumentItem, public ScanningFunctionalit
 public:
     OffspecInstrumentItem();
 
-    QString instrumentType() const override { return "Offspecular"; }
+    QString instrumentType() const override { return "Offspec"; }
     std::vector<int> axdims() const override;
     void updateToRealData(const DatafileItem* dfileItem) override;
     std::unique_ptr<Frame> createFrame() const override;
diff --git a/GUI/Model/Device/InstrumentsCatalog.cpp b/GUI/Model/Device/InstrumentsCatalog.cpp
index 50fe1d740db..481e1602b06 100644
--- a/GUI/Model/Device/InstrumentsCatalog.cpp
+++ b/GUI/Model/Device/InstrumentsCatalog.cpp
@@ -42,7 +42,7 @@ UiInfo InstrumentsCatalog::uiInfo(Type type)
     case Type::Scatter2D:
         return {"Scatter2D", "", ""};
     case Type::Offspec:
-        return {"Offspecular", "", ""};
+        return {"Offspec", "", ""};
     case Type::Specular:
         return {"Specular", "", ""};
     case Type::Depthprobe:
-- 
GitLab


From 335a4fd11027d61099384abbc1d46dc90ce2dd49 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 18:04:31 +0100
Subject: [PATCH 025/108] set name in item c'tors

---
 GUI/Model/Device/InstrumentItems.cpp | 9 +++++++--
 GUI/View/List/InstrumentsQModel.cpp  | 4 ----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index 348160516b9..accf3dbfcd3 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -365,9 +365,10 @@ void ScanningFunctionality::readScanFrom(QXmlStreamReader* r)
 //  ************************************************************************************************
 
 Scatter2DInstrumentItem::Scatter2DInstrumentItem()
+    : m_beam_item(std::make_unique<BeamItem>())
+    , m_detector_item(std::make_unique<DetectorItem>())
 {
-    m_detector_item = std::make_unique<DetectorItem>();
-    m_beam_item = std::make_unique<BeamItem>();
+    setInstrumentName("GISAS");
 }
 
 std::vector<int> Scatter2DInstrumentItem::axdims() const
@@ -477,6 +478,7 @@ OffspecInstrumentItem::OffspecInstrumentItem()
     : ScanningFunctionality(1e8)
     , m_detector(new OffspecDetectorItem)
 {
+    setInstrumentName("Offspec");
 }
 
 std::vector<int> OffspecInstrumentItem::axdims() const
@@ -578,6 +580,7 @@ void OffspecInstrumentItem::readFrom(QXmlStreamReader* r)
 SpecularInstrumentItem::SpecularInstrumentItem()
     : ScanningFunctionality(1e6)
 {
+    setInstrumentName("Specular");
 }
 
 std::vector<int> SpecularInstrumentItem::axdims() const
@@ -701,6 +704,8 @@ void SpecularInstrumentItem::readFrom(QXmlStreamReader* r)
 DepthprobeInstrumentItem::DepthprobeInstrumentItem()
     : ScanningFunctionality(1e8)
 {
+    setInstrumentName("Depthprobe");
+
     auto* axisItem = scanItem()->inclinationAxisItem();
     axisItem->setMin(0.0);
     axisItem->setMax(1.0);
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index df41e97aa7c..1479106bc14 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -50,28 +50,24 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 QModelIndex InstrumentsQModel::addNewScatter2DInstrument()
 {
     auto* t = new Scatter2DInstrumentItem;
-    t->setInstrumentName("GISAS");
     return pushInstrument(t);
 }
 
 QModelIndex InstrumentsQModel::addNewOffspecInstrument()
 {
     auto* t = new OffspecInstrumentItem;
-    t->setInstrumentName("Offspec");
     return pushInstrument(t);
 }
 
 QModelIndex InstrumentsQModel::addNewSpecularInstrument()
 {
     auto* t = new SpecularInstrumentItem;
-    t->setInstrumentName("Specular");
     return pushInstrument(t);
 }
 
 QModelIndex InstrumentsQModel::addNewDepthprobeInstrument()
 {
     auto* t = new DepthprobeInstrumentItem;
-    t->setInstrumentName("Depthprobe");
     return pushInstrument(t);
 }
 
-- 
GitLab


From 0031ffa11d0cbadf0339ca449ad87e31d5d11ff5 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 18:08:38 +0100
Subject: [PATCH 026/108] inline methods

---
 GUI/View/List/InstrumentsQListView.cpp | 16 ++++++++--------
 GUI/View/List/InstrumentsQModel.cpp    | 24 ------------------------
 GUI/View/List/InstrumentsQModel.h      |  5 -----
 3 files changed, 8 insertions(+), 37 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index c3828c0819c..4726a08a01a 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -36,17 +36,17 @@ InstrumentsQListView::InstrumentsQListView()
     setModel(m_model);
     setItemDelegate(new ListItemDelegate(this));
 
-    connect(gActions->new_gisas_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::addNewScatter2DInstrument);
+    connect(gActions->new_gisas_instrument, &QAction::triggered, [this]
+	{ m_model->pushInstrument(new Scatter2DInstrumentItem); });
 
-    connect(gActions->new_offspec_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::addNewOffspecInstrument);
+    connect(gActions->new_offspec_instrument, &QAction::triggered, [this]
+	{ m_model->pushInstrument(new OffspecInstrumentItem); });
 
-    connect(gActions->new_specular_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::addNewSpecularInstrument);
+    connect(gActions->new_specular_instrument, &QAction::triggered, [this]
+	{ m_model->pushInstrument(new SpecularInstrumentItem); });
 
-    connect(gActions->new_depthprobe_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::addNewDepthprobeInstrument);
+    connect(gActions->new_depthprobe_instrument, &QAction::triggered, [this]
+	{ m_model->pushInstrument(new DepthprobeInstrumentItem); });
 
     connect(gActions->remove_instrument, &QAction::triggered, m_model,
             &InstrumentsQModel::removeInstrument);
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 1479106bc14..ea7c46695e5 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -47,30 +47,6 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     }
 }
 
-QModelIndex InstrumentsQModel::addNewScatter2DInstrument()
-{
-    auto* t = new Scatter2DInstrumentItem;
-    return pushInstrument(t);
-}
-
-QModelIndex InstrumentsQModel::addNewOffspecInstrument()
-{
-    auto* t = new OffspecInstrumentItem;
-    return pushInstrument(t);
-}
-
-QModelIndex InstrumentsQModel::addNewSpecularInstrument()
-{
-    auto* t = new SpecularInstrumentItem;
-    return pushInstrument(t);
-}
-
-QModelIndex InstrumentsQModel::addNewDepthprobeInstrument()
-{
-    auto* t = new DepthprobeInstrumentItem;
-    return pushInstrument(t);
-}
-
 void InstrumentsQModel::removeInstrument()
 {
     InstrumentsSet* set = gDoc->instrumentsModifier();
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index 65538d38613..6ae8a991940 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -29,11 +29,6 @@ public:
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 
-    QModelIndex addNewScatter2DInstrument();
-    QModelIndex addNewOffspecInstrument();
-    QModelIndex addNewSpecularInstrument();
-    QModelIndex addNewDepthprobeInstrument();
-
     void removeInstrument();
     QModelIndex copyInstrument();
     QModelIndex pushInstrument(InstrumentItem*);
-- 
GitLab


From 71ef98c59c6a09f12c14d5321fd06fbba2ed68b6 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 18:19:41 +0100
Subject: [PATCH 027/108] prepare InstrumentsQModel for reuse

---
 GUI/View/List/InstrumentsQModel.cpp | 39 ++++++++++++++++-------------
 GUI/View/List/InstrumentsQModel.h   |  5 ++++
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index ea7c46695e5..97dd95225b7 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -22,26 +22,35 @@
 
 InstrumentsQModel::InstrumentsQModel() {}
 
+InstrumentsSet* InstrumentsQModel::set()
+{
+    return gDoc->instrumentsModifier();
+}
+
+const InstrumentsSet* InstrumentsQModel::set() const
+{
+    return gDoc->instruments();
+}
+
 int InstrumentsQModel::rowCount(const QModelIndex&) const
 {
-    return gDoc->instruments()->instrumentItems().size();
+    return set()->instrumentItems().size();
 }
 
 QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 {
-    const InstrumentsSet* set = gDoc->instruments();
     if (!index.isValid())
         return {};
     size_t row = index.row();
-    if (row >= set->size())
+    if (row >= set()->size())
         return {};
-    const InstrumentItem* t = set->at(row);
+    const InstrumentItem* t = set()->at(row);
 
     switch (role) {
     case Qt::DisplayRole:
         return t->instrumentName();
     case Qt::BackgroundRole:
-        return row == set->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
+        return row == set()->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
     default:
         return {};
     }
@@ -49,21 +58,19 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 
 void InstrumentsQModel::removeInstrument()
 {
-    InstrumentsSet* set = gDoc->instrumentsModifier();
-    const InstrumentItem* t = set->currentItem();
+    const InstrumentItem* t = set()->currentItem();
 
-    const int row = set->index_of(t);
+    const int row = set()->index_of(t);
     beginRemoveRows({}, row, row);
-    set->delete_element(t);
+    set()->delete_element(t);
     endRemoveRows();
 
-    emit set->setChanged();
+    emit set()->setChanged();
 }
 
 QModelIndex InstrumentsQModel::copyInstrument()
 {
-    InstrumentsSet* set = gDoc->instrumentsModifier();
-    const InstrumentItem* t = set->currentItem();
+    const InstrumentItem* t = set()->currentItem();
     InstrumentItem* t2 = t->createItemCopy();
     t2->setId(QUuid::createUuid().toString());
     return pushInstrument(t2);
@@ -71,13 +78,11 @@ QModelIndex InstrumentsQModel::copyInstrument()
 
 QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 {
-    InstrumentsSet* set = gDoc->instrumentsModifier();
-
-    const int row = set->instrumentItems().size();
+    const int row = set()->instrumentItems().size();
     beginInsertRows({}, row, row);
-    set->push_back(t);
+    set()->push_back(t);
     endInsertRows();
-    emit set->setChanged();
+    emit set()->setChanged();
 
     return createIndex(row, 0);
 }
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index 6ae8a991940..8be19427d5b 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -18,6 +18,7 @@
 #include <QAbstractListModel>
 
 class InstrumentItem;
+class InstrumentsSet;
 
 //! Data model for InstrumentsQListView.
 
@@ -32,6 +33,10 @@ public:
     void removeInstrument();
     QModelIndex copyInstrument();
     QModelIndex pushInstrument(InstrumentItem*);
+
+private:
+    InstrumentsSet* set();
+    const InstrumentsSet* set() const;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_INSTRUMENTSQMODEL_H
-- 
GitLab


From f50d6cb0f8e68cafc88a7e0a162213e52a20e817 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 18:23:00 +0100
Subject: [PATCH 028/108] + VectorWC::delete_current, simplify instrs model
 code

rename member var
---
 Base/Types/VectorWC.h               | 6 ++++++
 GUI/View/List/InstrumentsQModel.cpp | 9 ++++-----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/Base/Types/VectorWC.h b/Base/Types/VectorWC.h
index c193c1cca3e..fb2e2929586 100644
--- a/Base/Types/VectorWC.h
+++ b/Base/Types/VectorWC.h
@@ -52,6 +52,12 @@ public:
         super::delete_at(i);
         update_current();
     }
+    void delete_current()
+    {
+	ASSERT(m_current_index != size_t(-1));
+	super::delete_at(m_current_index);
+	update_current();
+    }
     T* release_at(size_t i)
     {
         super::release_at(i);
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 97dd95225b7..ee37de0a2fc 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -58,11 +58,10 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 
 void InstrumentsQModel::removeInstrument()
 {
-    const InstrumentItem* t = set()->currentItem();
-
-    const int row = set()->index_of(t);
+    const size_t row = set()->currentIndex();
+    ASSERT(row != size_t(-1));
     beginRemoveRows({}, row, row);
-    set()->delete_element(t);
+    set()->delete_current();
     endRemoveRows();
 
     emit set()->setChanged();
@@ -78,7 +77,7 @@ QModelIndex InstrumentsQModel::copyInstrument()
 
 QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 {
-    const int row = set()->instrumentItems().size();
+    const size_t row = set()->size();
     beginInsertRows({}, row, row);
     set()->push_back(t);
     endInsertRows();
-- 
GitLab


From 99aea2bba368eb2fea057af36dbc28904938ac0b Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:00:03 +0100
Subject: [PATCH 029/108] rename member var

---
 GUI/View/Views/InstrumentView.cpp | 8 ++++----
 GUI/View/Views/InstrumentView.h   | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 72751873c2e..295a390fb1c 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -32,7 +32,7 @@
 #include <iostream>
 
 InstrumentView::InstrumentView()
-    : m_listing(new InstrumentsQListView)
+    : m_qlistview(new InstrumentsQListView)
     , m_scroll_area(new QScrollArea)
 {
     auto* layout = new QVBoxLayout(this);
@@ -57,7 +57,7 @@ InstrumentView::InstrumentView()
 
     // Left margin: instrument list
 
-    hLayout->addWidget(m_listing);
+    hLayout->addWidget(m_qlistview);
 
     // Large widget: current instrument
 
@@ -100,7 +100,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
 
     auto* nameEdit = new QLineEdit(g);
     nameEdit->setText(currentInstrument->instrumentName());
-    connect(nameEdit, &QLineEdit::textEdited, [this] { m_listing->repaint(); });
+    connect(nameEdit, &QLineEdit::textEdited, [this] { m_qlistview->repaint(); });
     formLayout->addRow("Name:", nameEdit);
 
     auto* descriptionEdit = new QTextEdit(g);
@@ -109,7 +109,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
     descriptionEdit->setAcceptRichText(false);
     descriptionEdit->setTabChangesFocus(true);
     descriptionEdit->setPlainText(currentInstrument->description());
-    connect(descriptionEdit, &QTextEdit::textChanged, [this] { m_listing->repaint(); });
+    connect(descriptionEdit, &QTextEdit::textChanged, [this] { m_qlistview->repaint(); });
     formLayout->addRow("Description:", descriptionEdit);
 
     //... All remaining content depends on instrument type
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index 47832162d6b..ee4193b8320 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -33,7 +33,7 @@ private slots:
 private:
     void createWidgetsForCurrentInstrument();
 
-    InstrumentsQListView* m_listing;
+    InstrumentsQListView* m_qlistview;
     QScrollArea* m_scroll_area;
 };
 
-- 
GitLab


From 1c28529f55787b10db9fa159b233f5d9b7df6835 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:06:46 +0100
Subject: [PATCH 030/108] rm disconnect

---
 GUI/View/List/InstrumentsQListView.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 4726a08a01a..7c558a3ea6f 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -76,7 +76,6 @@ InstrumentsQListView::InstrumentsQListView()
 
 InstrumentsQListView::~InstrumentsQListView()
 {
-    disconnect(this, nullptr, nullptr, nullptr);
     delete m_model;
 }
 
-- 
GitLab


From f4c75e9c2622b822b16cf668652a40b1e6150ee2 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:15:47 +0100
Subject: [PATCH 031/108] Cloned GUI/Model/Sample/Item3D.h ->
 GUI/Model/Type/NamedItem.h

---
 GUI/Model/Type/NamedItem.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 GUI/Model/Type/NamedItem.h

diff --git a/GUI/Model/Type/NamedItem.h b/GUI/Model/Type/NamedItem.h
new file mode 100644
index 00000000000..d932435da8b
--- /dev/null
+++ b/GUI/Model/Type/NamedItem.h
@@ -0,0 +1,24 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Model/Type/NamedItem.h
+//! @brief     Defines and implements class Item3D.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2021
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#ifndef BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
+#define BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
+
+//! Base class of items that can be at the root of a realspace 3D representation
+class Item3D {
+public:
+    virtual ~Item3D() = default;
+};
+
+#endif // BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
-- 
GitLab


From 2a8ca1d9a86570909d20aae59532a8ceb4ad8a73 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:25:50 +0100
Subject: [PATCH 032/108] InstrumentItem inherits from NamedItem

---
 GUI/Model/Device/InstrumentItems.cpp      | 12 ++++++------
 GUI/Model/Device/InstrumentItems.h        |  7 ++-----
 GUI/Model/Device/InstrumentsSet.cpp       |  8 ++++----
 GUI/Model/Device/InstrumentsSet.h         |  2 +-
 GUI/Model/Type/NamedItem.h                | 14 +++++++++++---
 GUI/Support/XML/UtilXML.cpp               |  5 +++++
 GUI/Support/XML/UtilXML.h                 |  2 ++
 GUI/View/Data/DatafileEditor.cpp          |  2 +-
 GUI/View/Job/JobparQModel.cpp             |  2 +-
 GUI/View/List/InstrumentsQListView.cpp    |  2 +-
 GUI/View/List/InstrumentsQModel.cpp       |  2 +-
 GUI/View/Views/InstrumentView.cpp         |  2 +-
 Tests/Unit/GUI/TestAutosaveController.cpp |  8 ++++----
 Tests/Unit/GUI/TestInstrumentsSet.cpp     |  8 ++++----
 Tests/Unit/GUI/TestProjectDocument.cpp    |  8 ++++----
 15 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index accf3dbfcd3..1f8d78766a3 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -133,7 +133,7 @@ void InstrumentItem::writeTo(QXmlStreamWriter* w) const
 
     // name
     w->writeStartElement(Tag::Name);
-    XML::writeAttribute(w, XML::Attrib::value, m_name);
+    XML::writeAttribute(w, XML::Attrib::value, name());
     w->writeEndElement();
 
     // description
@@ -201,7 +201,7 @@ void InstrumentItem::readFrom(QXmlStreamReader* r)
 
             // name
         } else if (tag == Tag::Name) {
-            XML::readAttribute(r, XML::Attrib::value, &m_name);
+            setName(XML::readAttributeString(r, XML::Attrib::value));
             XML::gotoEndElementOfTag(r, tag);
 
             // description
@@ -368,7 +368,7 @@ Scatter2DInstrumentItem::Scatter2DInstrumentItem()
     : m_beam_item(std::make_unique<BeamItem>())
     , m_detector_item(std::make_unique<DetectorItem>())
 {
-    setInstrumentName("GISAS");
+    setName("GISAS");
 }
 
 std::vector<int> Scatter2DInstrumentItem::axdims() const
@@ -478,7 +478,7 @@ OffspecInstrumentItem::OffspecInstrumentItem()
     : ScanningFunctionality(1e8)
     , m_detector(new OffspecDetectorItem)
 {
-    setInstrumentName("Offspec");
+    setName("Offspec");
 }
 
 std::vector<int> OffspecInstrumentItem::axdims() const
@@ -580,7 +580,7 @@ void OffspecInstrumentItem::readFrom(QXmlStreamReader* r)
 SpecularInstrumentItem::SpecularInstrumentItem()
     : ScanningFunctionality(1e6)
 {
-    setInstrumentName("Specular");
+    setName("Specular");
 }
 
 std::vector<int> SpecularInstrumentItem::axdims() const
@@ -704,7 +704,7 @@ void SpecularInstrumentItem::readFrom(QXmlStreamReader* r)
 DepthprobeInstrumentItem::DepthprobeInstrumentItem()
     : ScanningFunctionality(1e8)
 {
-    setInstrumentName("Depthprobe");
+    setName("Depthprobe");
 
     auto* axisItem = scanItem()->inclinationAxisItem();
     axisItem->setMin(0.0);
diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h
index 03a497fb8f7..82d976652a7 100644
--- a/GUI/Model/Device/InstrumentItems.h
+++ b/GUI/Model/Device/InstrumentItems.h
@@ -19,6 +19,7 @@
 #include "GUI/Model/Descriptor/PolyItem.h"
 #include "GUI/Model/Descriptor/VectorProperty.h"
 #include "GUI/Model/Device/BackgroundItemCatalog.h"
+#include "GUI/Model/Type/NamedItem.h"
 #include <memory>
 
 class BackgroundItem;
@@ -36,7 +37,7 @@ class ScanItem;
 
 //! Abstract base class for instrument-specific item classes.
 
-class InstrumentItem {
+class InstrumentItem : public NamedItem {
 public:
     InstrumentItem();
     virtual ~InstrumentItem();
@@ -64,9 +65,6 @@ public:
     QString id() const { return m_id; }
     void setId(const QString& id) { m_id = id; }
 
-    QString instrumentName() const { return m_name; }
-    void setInstrumentName(const QString& instrumentName) { m_name = instrumentName; }
-
     template <typename T> bool is() const { return dynamic_cast<const T*>(this) != nullptr; }
 
     QString description() const { return m_description; }
@@ -98,7 +96,6 @@ protected:
     explicit InstrumentItem(const QString& modelType);
 
     QString m_id;
-    QString m_name;
     QString m_description;
     bool m_with_polarizer;
     bool m_with_analyzer;
diff --git a/GUI/Model/Device/InstrumentsSet.cpp b/GUI/Model/Device/InstrumentsSet.cpp
index 4ec4702b227..16128125441 100644
--- a/GUI/Model/Device/InstrumentsSet.cpp
+++ b/GUI/Model/Device/InstrumentsSet.cpp
@@ -86,7 +86,7 @@ QStringList InstrumentsSet::instrumentNames() const
 {
     QStringList existingNames;
     for (const auto* t : *this)
-        existingNames << t->instrumentName();
+        existingNames << t->name();
     return existingNames;
 }
 
@@ -103,10 +103,10 @@ bool InstrumentsSet::instrumentExists(const QString& instrumentId) const
     return findInstrumentItemById(instrumentId) != nullptr;
 }
 
-void InstrumentsSet::setInstrumentName(InstrumentItem* instrument, const QString& name)
+void InstrumentsSet::setName(InstrumentItem* instrument, const QString& name)
 {
-    if (instrument->instrumentName() != name) {
-        instrument->setInstrumentName(name);
+    if (instrument->name() != name) {
+        instrument->setName(name);
         emit currentModified();
         emit setChanged();
     }
diff --git a/GUI/Model/Device/InstrumentsSet.h b/GUI/Model/Device/InstrumentsSet.h
index 059eda1af11..03864531d0d 100644
--- a/GUI/Model/Device/InstrumentsSet.h
+++ b/GUI/Model/Device/InstrumentsSet.h
@@ -39,7 +39,7 @@ public:
     QStringList instrumentNames() const;
 
     //! Set an instrument's name and emit the respective signal.
-    void setInstrumentName(InstrumentItem* instrument, const QString& name);
+    void setName(InstrumentItem* instrument, const QString& name);
 
 signals:
     void setChanged() const;
diff --git a/GUI/Model/Type/NamedItem.h b/GUI/Model/Type/NamedItem.h
index d932435da8b..2c67239ed50 100644
--- a/GUI/Model/Type/NamedItem.h
+++ b/GUI/Model/Type/NamedItem.h
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit reflection and scattering
 //
 //! @file      GUI/Model/Type/NamedItem.h
-//! @brief     Defines and implements class Item3D.
+//! @brief     Defines and implements class NamedItem.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -15,10 +15,18 @@
 #ifndef BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
 #define BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
 
+#include <QString>
+
 //! Base class of items that can be at the root of a realspace 3D representation
-class Item3D {
+class NamedItem {
 public:
-    virtual ~Item3D() = default;
+    virtual ~NamedItem() = default;
+
+    void setName(const QString& name) { m_name = name; }
+    QString name() const { return m_name; }
+
+private:
+    QString m_name;
 };
 
 #endif // BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
diff --git a/GUI/Support/XML/UtilXML.cpp b/GUI/Support/XML/UtilXML.cpp
index e83eb2d0751..41c0bdbbdfb 100644
--- a/GUI/Support/XML/UtilXML.cpp
+++ b/GUI/Support/XML/UtilXML.cpp
@@ -169,3 +169,8 @@ void XML::readAttribute(QXmlStreamReader* reader, const QString& attributeBaseNa
     c->real(r);
     c->imag(i);
 }
+
+QString XML::readAttributeString(QXmlStreamReader* reader, const QString& attributeName)
+{
+    return reader->attributes().value(attributeName).toString();
+}
diff --git a/GUI/Support/XML/UtilXML.h b/GUI/Support/XML/UtilXML.h
index ff0cfd39bf8..8454df4ab3e 100644
--- a/GUI/Support/XML/UtilXML.h
+++ b/GUI/Support/XML/UtilXML.h
@@ -66,6 +66,8 @@ void readAttribute(QXmlStreamReader* reader, const QString& attributeName, QColo
 void readAttribute(QXmlStreamReader* reader, const QString& attributeBaseName, R3* vec);
 void readAttribute(QXmlStreamReader* reader, const QString& attributeBaseName, complex_t* c);
 
+QString readAttributeString(QXmlStreamReader* reader, const QString& attributeName);
+
 } // namespace XML
 
 #endif // BORNAGAIN_GUI_SUPPORT_XML_UTILXML_H
diff --git a/GUI/View/Data/DatafileEditor.cpp b/GUI/View/Data/DatafileEditor.cpp
index 6b3031de105..bba896f35a0 100644
--- a/GUI/View/Data/DatafileEditor.cpp
+++ b/GUI/View/Data/DatafileEditor.cpp
@@ -98,7 +98,7 @@ void DatafileEditor::updateInstrumentComboEntries()
     // fill the combo. Userdata contains instrument's uid
     m_instrument_combo->addItem("Undefined", ""); // undefined instrument
     for (auto* instrumentItem : gDoc->instruments()->instrumentItems())
-        m_instrument_combo->addItem(instrumentItem->instrumentName(), instrumentItem->id());
+        m_instrument_combo->addItem(instrumentItem->name(), instrumentItem->id());
 
     updateInstrumentComboIndex();
 
diff --git a/GUI/View/Job/JobparQModel.cpp b/GUI/View/Job/JobparQModel.cpp
index 5dc790dd7be..17fd2321af3 100644
--- a/GUI/View/Job/JobparQModel.cpp
+++ b/GUI/View/Job/JobparQModel.cpp
@@ -80,7 +80,7 @@ QVariant JobparQModel::data(const QModelIndex& index, int role) const
         case Row::Sample:
             return m_job_item->sampleItem()->sampleName();
         case Row::Instrument:
-            return m_job_item->instrumentItem()->instrumentName();
+            return m_job_item->instrumentItem()->name();
         case Row::Status:
             return jobStatusToString(m_job_item->batchInfo()->status());
         case Row::Begin:
diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 7c558a3ea6f..72263222c83 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -96,7 +96,7 @@ void InstrumentsQListView::onStoreInLibrary() const
         return;
 
     QString fname = GUI::Dialog::fileSaveDialog("Save instrument", appSettings->xml_dir,
-                                                "XML Files (*.xml)", t->instrumentName() + ".xml");
+                                                "XML Files (*.xml)", t->name() + ".xml");
     if (fname.isEmpty())
         return;
 
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index ee37de0a2fc..e879abf5298 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -48,7 +48,7 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
 
     switch (role) {
     case Qt::DisplayRole:
-        return t->instrumentName();
+        return t->name();
     case Qt::BackgroundRole:
         return row == set()->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
     default:
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 295a390fb1c..bc083071895 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -99,7 +99,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
     layout->addWidget(g);
 
     auto* nameEdit = new QLineEdit(g);
-    nameEdit->setText(currentInstrument->instrumentName());
+    nameEdit->setText(currentInstrument->name());
     connect(nameEdit, &QLineEdit::textEdited, [this] { m_qlistview->repaint(); });
     formLayout->addRow("Name:", nameEdit);
 
diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index 2a6b1092278..b68d4e2006c 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -20,7 +20,7 @@ protected:
     void modelsModifier(ProjectDocument& doc)
     {
         auto* instrument = doc.instrumentsModifier()->instrumentItems().front();
-        doc.instrumentsModifier()->setInstrumentName(instrument, QUuid::createUuid().toString());
+        doc.instrumentsModifier()->setName(instrument, QUuid::createUuid().toString());
     }
     const int m_save_wait = 3000;
 };
@@ -40,7 +40,7 @@ TEST_F(TestAutosaveController, autoSaveController)
     gDoc = std::make_unique<ProjectDocument>();
     auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
-    instrument->setInstrumentName("GISAS");
+    instrument->setName("GISAS");
     gDoc->saveProjectFileWithData(projectFileName);
 
     // setting up autosave
@@ -85,7 +85,7 @@ TEST_F(TestAutosaveController, autoSaveControllerNewDocument)
     gDoc = std::make_unique<ProjectDocument>();
     auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
-    instrument->setInstrumentName("GISAS");
+    instrument->setName("GISAS");
 
     const int autosave_time(100);
 
@@ -120,7 +120,7 @@ TEST_F(TestAutosaveController, autosaveEnabled)
     gDoc->setProjectFullPath(projectFileName);
     auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
-    instrument->setInstrumentName("GISAS");
+    instrument->setName("GISAS");
 
     DatafileItem* realData =
         UTest::GUI::createRealData2D("TestData", *gDoc->datafilesModifier(), 0.);
diff --git a/Tests/Unit/GUI/TestInstrumentsSet.cpp b/Tests/Unit/GUI/TestInstrumentsSet.cpp
index a7b21f3fb4a..2f29e47e6a1 100644
--- a/Tests/Unit/GUI/TestInstrumentsSet.cpp
+++ b/Tests/Unit/GUI/TestInstrumentsSet.cpp
@@ -46,7 +46,7 @@ TEST(TestInstrumentsSet, instrumentChanged)
     EXPECT_TRUE(spy.isValid());
 
     // change name of instrument 1
-    gDoc->instrumentsModifier()->setInstrumentName(instrument1, "A");
+    gDoc->instrumentsModifier()->setName(instrument1, "A");
     EXPECT_EQ(spy.count(), 1);
 
     // change other properties, e.g. id
@@ -55,7 +55,7 @@ TEST(TestInstrumentsSet, instrumentChanged)
     EXPECT_EQ(spy.count(), 2);
 
     // change name of instrument 2
-    gDoc->instrumentsModifier()->setInstrumentName(instrument2, "B");
+    gDoc->instrumentsModifier()->setName(instrument2, "B");
     EXPECT_EQ(spy.count(), 3);
 
     // Add another instrument
@@ -63,10 +63,10 @@ TEST(TestInstrumentsSet, instrumentChanged)
     gDoc->instrumentsModifier()->push_back(instrument3);
 
     // Change instrument2
-    gDoc->instrumentsModifier()->setInstrumentName(instrument2, "BB");
+    gDoc->instrumentsModifier()->setName(instrument2, "BB");
     EXPECT_EQ(spy.count(), 4);
 
     // Change instrument3
-    gDoc->instrumentsModifier()->setInstrumentName(instrument3, "C");
+    gDoc->instrumentsModifier()->setName(instrument3, "C");
     EXPECT_EQ(spy.count(), 5);
 }
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index 3972c0d4a3f..f994c475717 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -21,7 +21,7 @@ protected:
     void modelsModifier(ProjectDocument& doc)
     {
         auto* instrument = doc.instrumentsModifier()->instrumentItems().front();
-        doc.instrumentsModifier()->setInstrumentName(instrument, QUuid::createUuid().toString());
+        doc.instrumentsModifier()->setName(instrument, QUuid::createUuid().toString());
     }
 };
 
@@ -42,7 +42,7 @@ TEST_F(TestProjectDocument, projectDocument)
 
     auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
-    instrument->setInstrumentName("GISAS");
+    instrument->setName("GISAS");
 
     // Checking document name and isModified status after project save
     gDoc->saveProjectFileWithData(projectFileName);
@@ -79,7 +79,7 @@ TEST_F(TestProjectDocument, projectDocumentWithData)
 
     auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
-    instrument->setInstrumentName("GISAS");
+    instrument->setName("GISAS");
     DatafileItem* realData =
         UTest::GUI::createRealData2D("TestData", *gDoc->datafilesModifier(), 0.);
     ASSERT(realData);
@@ -113,7 +113,7 @@ TEST_F(TestProjectDocument, failingProjectSave)
     gDoc = std::make_unique<ProjectDocument>();
     auto* instrument = new Scatter2DInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument);
-    instrument->setInstrumentName("GISAS");
+    instrument->setName("GISAS");
     modelsModifier(*gDoc);
 
     EXPECT_FALSE(QFile::exists(projectFileName));
-- 
GitLab


From 95a8ab7c5c59deb95f42734de796ad9e4924ddaf Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:36:37 +0100
Subject: [PATCH 033/108] CollapsibleGroupBox + c'tor w/o title

---
 GUI/View/Sample/LayerForm.cpp  | 2 +-
 GUI/View/Widget/GroupBoxes.cpp | 9 +++++++--
 GUI/View/Widget/GroupBoxes.h   | 1 +
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/GUI/View/Sample/LayerForm.cpp b/GUI/View/Sample/LayerForm.cpp
index 0734225d201..b7539847fe6 100644
--- a/GUI/View/Sample/LayerForm.cpp
+++ b/GUI/View/Sample/LayerForm.cpp
@@ -30,7 +30,7 @@
 #include <QPushButton>
 
 LayerForm::LayerForm(QWidget* parent, LayerItem* layerItem, SampleEditorController* ec)
-    : CollapsibleGroupBox(layerItem->layerName(), parent, layerItem->expandLayer)
+    : CollapsibleGroupBox(parent, layerItem->expandLayer)
     , m_layout(new HeinzFormLayout(ec))
     , m_layer(layerItem)
     , m_ec(ec)
diff --git a/GUI/View/Widget/GroupBoxes.cpp b/GUI/View/Widget/GroupBoxes.cpp
index 07688de8f58..9ac41c1a596 100644
--- a/GUI/View/Widget/GroupBoxes.cpp
+++ b/GUI/View/Widget/GroupBoxes.cpp
@@ -43,7 +43,7 @@ StaticGroupBox::StaticGroupBox(const QString& title, QWidget* parent)
 //  class CollapsibleGroupBox
 //  ************************************************************************************************
 
-CollapsibleGroupBox::CollapsibleGroupBox(const QString& title, QWidget* parent, bool& expanded)
+CollapsibleGroupBox::CollapsibleGroupBox(QWidget* parent, bool& expanded)
     : QssWidget(parent)
     , m_title_widget(new QWidget)
     , m_title_layout(new QHBoxLayout(m_title_widget))
@@ -68,7 +68,6 @@ CollapsibleGroupBox::CollapsibleGroupBox(const QString& title, QWidget* parent,
     m_toggle_button->setObjectName("GroupBoxToggler");
     m_toggle_button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
     m_toggle_button->setCheckable(true);
-    m_toggle_button->setText(title);
     m_toggle_button->setArrowType(Qt::ArrowType::DownArrow);
     m_toggle_button->setChecked(expanded);
     m_toggle_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
@@ -87,6 +86,12 @@ CollapsibleGroupBox::CollapsibleGroupBox(const QString& title, QWidget* parent,
             });
 }
 
+CollapsibleGroupBox::CollapsibleGroupBox(const QString& title, QWidget* parent, bool& expanded)
+    : CollapsibleGroupBox(parent, expanded)
+{
+    setTitle(title);
+}
+
 void CollapsibleGroupBox::setTitle(const QString& title)
 {
     m_toggle_button->setText(title);
diff --git a/GUI/View/Widget/GroupBoxes.h b/GUI/View/Widget/GroupBoxes.h
index f97292ddc25..4fb548adddc 100644
--- a/GUI/View/Widget/GroupBoxes.h
+++ b/GUI/View/Widget/GroupBoxes.h
@@ -39,6 +39,7 @@ private:
 class CollapsibleGroupBox : public QssWidget {
     Q_OBJECT
 public:
+    CollapsibleGroupBox(QWidget* parent, bool& expanded);
     CollapsibleGroupBox(const QString& title, QWidget* parent, bool& expanded);
     QWidget* body() { return m_body; }
     void setTitle(const QString& title);
-- 
GitLab


From fa5931e3a233b0c1c335737a9ec814b26a0b85b7 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:38:17 +0100
Subject: [PATCH 034/108] LayerItem rm name

---
 GUI/Model/Sample/LayerItem.cpp | 11 -----------
 GUI/Model/Sample/LayerItem.h   |  4 ----
 2 files changed, 15 deletions(-)

diff --git a/GUI/Model/Sample/LayerItem.cpp b/GUI/Model/Sample/LayerItem.cpp
index 921de078a6b..548cf662f3c 100644
--- a/GUI/Model/Sample/LayerItem.cpp
+++ b/GUI/Model/Sample/LayerItem.cpp
@@ -69,7 +69,6 @@ std::vector<ItemWithMaterial*> layoutItemsWithMaterial(ParticleLayoutItem* layou
 
 LayerItem::LayerItem(const MaterialsSet* materials)
     : ItemWithMaterial(materials)
-    , m_name("Layer")
 {
     m_thickness.init("Thickness (nm)", "Thickness of the layer", 0.0, 3,
                      RealLimits::lowerLimited(0.0), "thickness");
@@ -127,11 +126,6 @@ void LayerItem::writeTo(QXmlStreamWriter* w) const
     ItemWithMaterial::writeTo(w);
     w->writeEndElement();
 
-    // name
-    w->writeStartElement(Tag::Name);
-    XML::writeAttribute(w, XML::Attrib::value, m_name);
-    w->writeEndElement();
-
     // color
     w->writeStartElement(Tag::Color);
     XML::writeAttribute(w, XML::Attrib::value, m_color);
@@ -180,11 +174,6 @@ void LayerItem::readFrom(QXmlStreamReader* r)
             ItemWithMaterial::readFrom(r);
             XML::gotoEndElementOfTag(r, tag);
 
-            // name
-        } else if (tag == Tag::Name) {
-            XML::readAttribute(r, XML::Attrib::value, &m_name);
-            XML::gotoEndElementOfTag(r, tag);
-
             // color
         } else if (tag == Tag::Color) {
             XML::readAttribute(r, XML::Attrib::value, &m_color);
diff --git a/GUI/Model/Sample/LayerItem.h b/GUI/Model/Sample/LayerItem.h
index e03b6295481..ac1e294eeae 100644
--- a/GUI/Model/Sample/LayerItem.h
+++ b/GUI/Model/Sample/LayerItem.h
@@ -32,9 +32,6 @@ public:
     explicit LayerItem(const MaterialsSet* materials);
     ~LayerItem();
 
-    QString layerName() const { return m_name; }
-    void setLayerName(const QString& n) { m_name = n; }
-
     std::vector<ItemWithMaterial*> itemsWithMaterial();
     std::vector<ItemWithParticles*> itemsWithParticles() const;
 
@@ -68,7 +65,6 @@ public:
     bool expandLayer = false;
 
 private:
-    QString m_name;
     uint m_num_slices = 1;
     DoubleProperty m_thickness;
     QColor m_color;
-- 
GitLab


From a2bbb4216ff6071fc91113b1443aafa71557becf Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:42:24 +0100
Subject: [PATCH 035/108] SampleItem inherits from NamedItem

---
 GUI/Model/FromCore/ItemizeSample.cpp               |  2 +-
 GUI/Model/Sample/SampleItem.cpp                    |  5 ++---
 GUI/Model/Sample/SampleItem.h                      |  7 ++-----
 GUI/Model/Sample/SamplesSet.cpp                    |  2 +-
 GUI/View/Job/JobparQModel.cpp                      |  2 +-
 GUI/View/List/SamplesQModel.cpp                    |  8 ++++----
 GUI/View/Manager/PyImportAssistant.cpp             |  4 ++--
 GUI/View/Sample/SampleEditorController.cpp         |  4 ++--
 GUI/View/Sample/SampleEditorController.h           |  2 +-
 GUI/View/Sample/SampleForm.cpp                     |  4 ++--
 Sample/Multilayer/MultiLayer.h                     |  4 ++--
 .../LayersWithAbsorptionBuilder.cpp                |  2 +-
 Sample/StandardSamples/ParacrystalBuilder.cpp      |  2 +-
 Sample/StandardSamples/ParticleInVacuumBuilder.cpp |  2 +-
 auto/Wrap/libBornAgainSample.py                    |  6 +++---
 auto/Wrap/libBornAgainSample_wrap.cpp              | 14 +++++++-------
 16 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/GUI/Model/FromCore/ItemizeSample.cpp b/GUI/Model/FromCore/ItemizeSample.cpp
index 89998c41df5..163acd16706 100644
--- a/GUI/Model/FromCore/ItemizeSample.cpp
+++ b/GUI/Model/FromCore/ItemizeSample.cpp
@@ -625,7 +625,7 @@ namespace GUI::FromCore {
 SampleItem* itemizeSample(const MultiLayer& sample, const QString& nodeName)
 {
     auto* result = new SampleItem();
-    result->setSampleName(nodeName.isEmpty() ? QString::fromStdString(sample.sampleName())
+    result->setName(nodeName.isEmpty() ? QString::fromStdString(sample.name())
                                              : nodeName);
     result->setCrossCorLength(sample.crossCorrLength());
     result->setExternalField(sample.externalField());
diff --git a/GUI/Model/Sample/SampleItem.cpp b/GUI/Model/Sample/SampleItem.cpp
index ba40dab3b6b..4e7af36b312 100644
--- a/GUI/Model/Sample/SampleItem.cpp
+++ b/GUI/Model/Sample/SampleItem.cpp
@@ -34,7 +34,6 @@ const QString ExpandInfoGroupbox("ExpandInfoGroupbox");
 } // namespace
 
 SampleItem::SampleItem()
-    : m_name("Sample")
 {
 
     m_cross_correlation_length.init("Cross-correlation length (nm)",
@@ -131,7 +130,7 @@ void SampleItem::writeTo(QXmlStreamWriter* w) const
 
     // name
     w->writeStartElement(Tag::Name);
-    XML::writeAttribute(w, XML::Attrib::value, m_name);
+    XML::writeAttribute(w, XML::Attrib::value, name());
     w->writeEndElement();
 
     // description
@@ -179,7 +178,7 @@ void SampleItem::readFrom(QXmlStreamReader* r)
 
         // sample name
         if (tag == Tag::Name) {
-            XML::readAttribute(r, XML::Attrib::value, &m_name);
+            setName(XML::readAttributeString(r, XML::Attrib::value));
             XML::gotoEndElementOfTag(r, tag);
 
             // description
diff --git a/GUI/Model/Sample/SampleItem.h b/GUI/Model/Sample/SampleItem.h
index e0ec826fe83..375e301dd93 100644
--- a/GUI/Model/Sample/SampleItem.h
+++ b/GUI/Model/Sample/SampleItem.h
@@ -19,13 +19,14 @@
 #include "GUI/Model/Descriptor/VectorProperty.h"
 #include "GUI/Model/Material/MaterialsSet.h"
 #include "GUI/Model/Sample/Item3D.h"
+#include "GUI/Model/Type/NamedItem.h"
 #include <QString>
 #include <QXmlStreamReader>
 
 class ItemWithMaterial;
 class LayerItem;
 
-class SampleItem : public virtual Item3D {
+class SampleItem : public virtual Item3D, public NamedItem {
 public:
     SampleItem();
     ~SampleItem();
@@ -36,9 +37,6 @@ public:
 
     void addStandardMaterials();
 
-    QString sampleName() const { return m_name; }
-    void setSampleName(const QString& s) { m_name = s; }
-
     QString description() const { return m_description; }
     void setDescription(const QString& s) { m_description = s; }
 
@@ -71,7 +69,6 @@ public:
     bool expandInfo = true;
 
 private:
-    QString m_name;
     QString m_description;
     DoubleProperty m_cross_correlation_length;
     VectorProperty m_external_field;
diff --git a/GUI/Model/Sample/SamplesSet.cpp b/GUI/Model/Sample/SamplesSet.cpp
index 2dcc5475e81..7acd2db5769 100644
--- a/GUI/Model/Sample/SamplesSet.cpp
+++ b/GUI/Model/Sample/SamplesSet.cpp
@@ -32,7 +32,7 @@ QStringList SamplesSet::sampleNames() const
 {
     QStringList existingNames;
     for (const auto* item : *this)
-        existingNames << item->sampleName();
+        existingNames << item->name();
     return existingNames;
 }
 
diff --git a/GUI/View/Job/JobparQModel.cpp b/GUI/View/Job/JobparQModel.cpp
index 17fd2321af3..71cd13ea2fd 100644
--- a/GUI/View/Job/JobparQModel.cpp
+++ b/GUI/View/Job/JobparQModel.cpp
@@ -78,7 +78,7 @@ QVariant JobparQModel::data(const QModelIndex& index, int role) const
         case Row::Name:
             return m_job_item->batchInfo()->jobName();
         case Row::Sample:
-            return m_job_item->sampleItem()->sampleName();
+            return m_job_item->sampleItem()->name();
         case Row::Instrument:
             return m_job_item->instrumentItem()->name();
         case Row::Status:
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 2db6b6e9694..84eef45dcf4 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -39,7 +39,7 @@ QVariant SamplesQModel::data(const QModelIndex& index, int role) const
         return item->description();
 
     if (role == Qt::DisplayRole)
-        return item->sampleName();
+        return item->name();
 
     return {};
 }
@@ -79,7 +79,7 @@ QModelIndex SamplesQModel::copySample(SampleItem* item)
     const int row = gDoc->samples()->shared().size();
     beginInsertRows(QModelIndex(), row, row);
     SampleItem* copied_item = item->clone();
-    copied_item->setSampleName(GUI::Util::String::suggestName(existingNames, item->sampleName()));
+    copied_item->setName(GUI::Util::String::suggestName(existingNames, item->name()));
     gDoc->samplesModifier()->push_back(copied_item);
     endInsertRows();
     return indexForItem(copied_item);
@@ -90,7 +90,7 @@ QModelIndex SamplesQModel::createSample()
     const QStringList existingNames = gDoc->samples()->sampleNames();
 
     auto* t = new SampleItem;
-    t->setSampleName(GUI::Util::String::suggestName(existingNames, "Sample"));
+    t->setName(GUI::Util::String::suggestName(existingNames, "Sample"));
     t->addStandardMaterials();
 
     const int row = gDoc->samples()->shared().size();
@@ -108,7 +108,7 @@ QModelIndex SamplesQModel::createSampleFromExamples(const QString& className, co
     auto* t = dynamic_cast<SampleItem*>(GUI::ExamplesFactory::itemizeSample(className));
     if (!t)
         return {};
-    t->setSampleName(title);
+    t->setName(title);
     t->setDescription(description);
 
     const int row = gDoc->samples()->shared().size();
diff --git a/GUI/View/Manager/PyImportAssistant.cpp b/GUI/View/Manager/PyImportAssistant.cpp
index d8d3395b56a..35e124065ad 100644
--- a/GUI/View/Manager/PyImportAssistant.cpp
+++ b/GUI/View/Manager/PyImportAssistant.cpp
@@ -181,8 +181,8 @@ std::unique_ptr<MultiLayer> PyImportAssistant::importMultiLayer()
         if (!sample)
             throw std::runtime_error("Import did not yield MultiLayer object");
 
-        if (sample->sampleName() == "Unnamed")
-            sample->setSampleName(GUI::Path::baseName(fname).toStdString());
+        if (sample->name() == "Unnamed")
+            sample->setName(GUI::Path::baseName(fname).toStdString());
 
         return sample;
     } catch (const std::exception& ex) {
diff --git a/GUI/View/Sample/SampleEditorController.cpp b/GUI/View/Sample/SampleEditorController.cpp
index 65b78dffba7..fa6fc9313af 100644
--- a/GUI/View/Sample/SampleEditorController.cpp
+++ b/GUI/View/Sample/SampleEditorController.cpp
@@ -403,9 +403,9 @@ void SampleEditorController::onStoppedToMoveLayer(QWidget* widgetToMove,
     emit modified();
 }
 
-void SampleEditorController::setSampleName(const QString& name)
+void SampleEditorController::setName(const QString& name)
 {
-    m_sample_item->setSampleName(name);
+    m_sample_item->setName(name);
     emit modified();
 }
 
diff --git a/GUI/View/Sample/SampleEditorController.h b/GUI/View/Sample/SampleEditorController.h
index 924b86c5abc..609629526b9 100644
--- a/GUI/View/Sample/SampleEditorController.h
+++ b/GUI/View/Sample/SampleEditorController.h
@@ -110,7 +110,7 @@ public:
 
     void onStoppedToMoveLayer(QWidget* widgetToMove, QWidget* moveAboveThisWidget);
 
-    void setSampleName(const QString& name);
+    void setName(const QString& name);
     void setSampleDescription(const QString& description);
 
 signals:
diff --git a/GUI/View/Sample/SampleForm.cpp b/GUI/View/Sample/SampleForm.cpp
index 6da7880f560..d69020f94c5 100644
--- a/GUI/View/Sample/SampleForm.cpp
+++ b/GUI/View/Sample/SampleForm.cpp
@@ -75,9 +75,9 @@ SampleForm::SampleForm(SampleItem* sampleItem, SampleEditorController* ec)
 
     auto* nameEdit = new QLineEdit;
     gLayout->addBoldRow("Name:", nameEdit);
-    nameEdit->setText(sampleItem->sampleName());
+    nameEdit->setText(sampleItem->name());
     nameEdit->setFixedWidth(585);
-    connect(nameEdit, &QLineEdit::textEdited, ec, &SampleEditorController::setSampleName);
+    connect(nameEdit, &QLineEdit::textEdited, ec, &SampleEditorController::setName);
 
     auto* descriptionEdit = new QTextEdit;
     gLayout->addBoldRow("Description:", descriptionEdit);
diff --git a/Sample/Multilayer/MultiLayer.h b/Sample/Multilayer/MultiLayer.h
index a3ea91ae37a..3f4f7a35a8b 100644
--- a/Sample/Multilayer/MultiLayer.h
+++ b/Sample/Multilayer/MultiLayer.h
@@ -55,14 +55,14 @@ public:
     //! Sets the external field applied to the sample (units: A/m)
     void setExternalField(R3 ext_field);
 
-    void setSampleName(const std::string& name) { m_sample_name = name; }
+    void setName(const std::string& name) { m_sample_name = name; }
 
 #ifndef SWIG
     std::vector<const INode*> nodeChildren() const override;
 
     std::string validate() const override;
 
-    const std::string& sampleName() const
+    const std::string& name() const
     {
         return m_sample_name;
     }
diff --git a/Sample/StandardSamples/LayersWithAbsorptionBuilder.cpp b/Sample/StandardSamples/LayersWithAbsorptionBuilder.cpp
index 24ee3c124d3..d66ad4fa999 100644
--- a/Sample/StandardSamples/LayersWithAbsorptionBuilder.cpp
+++ b/Sample/StandardSamples/LayersWithAbsorptionBuilder.cpp
@@ -44,7 +44,7 @@ MultiLayer* ExemplarySamples::createLayersWithAbsorptionWithFF(const IFormFactor
     middle_layer.addLayout(layout);
 
     auto* result = new MultiLayer();
-    result->setSampleName(ff->className());
+    result->setName(ff->className());
     result->addLayer(vacuum_layer);
     result->addLayer(middle_layer);
     result->addLayer(substrate);
diff --git a/Sample/StandardSamples/ParacrystalBuilder.cpp b/Sample/StandardSamples/ParacrystalBuilder.cpp
index a8966f5ce1a..7335e9739a5 100644
--- a/Sample/StandardSamples/ParacrystalBuilder.cpp
+++ b/Sample/StandardSamples/ParacrystalBuilder.cpp
@@ -79,7 +79,7 @@ MultiLayer* ExemplarySamples::createBasic2DParacrystalWithFTDis(const IProfile2D
     vacuum_layer.addLayout(particle_layout);
 
     auto* result = new MultiLayer();
-    result->setSampleName("Basic2DParacrystal_" + pdf2->className());
+    result->setName("Basic2DParacrystal_" + pdf2->className());
     result->addLayer(vacuum_layer);
     result->addLayer(substrate_layer);
     return result;
diff --git a/Sample/StandardSamples/ParticleInVacuumBuilder.cpp b/Sample/StandardSamples/ParticleInVacuumBuilder.cpp
index 26dfb93c9b4..166b0065b7f 100644
--- a/Sample/StandardSamples/ParticleInVacuumBuilder.cpp
+++ b/Sample/StandardSamples/ParticleInVacuumBuilder.cpp
@@ -30,7 +30,7 @@ MultiLayer* ExemplarySamples::createParticleInVacuumWithFF(const IFormFactor* ff
     vacuum_layer.addLayout(particle_layout);
 
     auto* result = new MultiLayer();
-    result->setSampleName("ParticleInVacuum_" + ff->className());
+    result->setName("ParticleInVacuum_" + ff->className());
     result->addLayer(vacuum_layer);
     return result;
 }
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 6a86acb46a9..4496e545fa4 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -4293,9 +4293,9 @@ class MultiLayer(ISampleNode):
         r"""setExternalField(MultiLayer self, R3 ext_field)"""
         return _libBornAgainSample.MultiLayer_setExternalField(self, ext_field)
 
-    def setSampleName(self, name):
-        r"""setSampleName(MultiLayer self, std::string const & name)"""
-        return _libBornAgainSample.MultiLayer_setSampleName(self, name)
+    def setName(self, name):
+        r"""setName(MultiLayer self, std::string const & name)"""
+        return _libBornAgainSample.MultiLayer_setName(self, name)
 
 # Register MultiLayer in _libBornAgainSample:
 _libBornAgainSample.MultiLayer_swigregister(MultiLayer)
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index c2a7c3c4499..c4c2b6973f7 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -51790,7 +51790,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_MultiLayer_setSampleName(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_MultiLayer_setName(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
   MultiLayer *arg1 = (MultiLayer *) 0 ;
   std::string *arg2 = 0 ;
@@ -51800,26 +51800,26 @@ SWIGINTERN PyObject *_wrap_MultiLayer_setSampleName(PyObject *self, PyObject *ar
   PyObject *swig_obj[2] ;
   
   (void)self;
-  if (!SWIG_Python_UnpackTuple(args, "MultiLayer_setSampleName", 2, 2, swig_obj)) SWIG_fail;
+  if (!SWIG_Python_UnpackTuple(args, "MultiLayer_setName", 2, 2, swig_obj)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MultiLayer, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MultiLayer_setSampleName" "', argument " "1"" of type '" "MultiLayer *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MultiLayer_setName" "', argument " "1"" of type '" "MultiLayer *""'"); 
   }
   arg1 = reinterpret_cast< MultiLayer * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(swig_obj[1], &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MultiLayer_setSampleName" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MultiLayer_setName" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "MultiLayer_setSampleName" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "MultiLayer_setName" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
   {
     try {
-      (arg1)->setSampleName((std::string const &)*arg2);
+      (arg1)->setName((std::string const &)*arg2);
     } catch (const std::exception& ex) {
       // message shown in the Python interpreter
       const std::string msg {
@@ -71788,7 +71788,7 @@ static PyMethodDef SwigMethods[] = {
 	 { "MultiLayer_setRoughnessModel", _wrap_MultiLayer_setRoughnessModel, METH_VARARGS, "MultiLayer_setRoughnessModel(MultiLayer self, RoughnessModel roughnessModel)"},
 	 { "MultiLayer_setCrossCorrLength", _wrap_MultiLayer_setCrossCorrLength, METH_VARARGS, "MultiLayer_setCrossCorrLength(MultiLayer self, double crossCorrLength)"},
 	 { "MultiLayer_setExternalField", _wrap_MultiLayer_setExternalField, METH_VARARGS, "MultiLayer_setExternalField(MultiLayer self, R3 ext_field)"},
-	 { "MultiLayer_setSampleName", _wrap_MultiLayer_setSampleName, METH_VARARGS, "MultiLayer_setSampleName(MultiLayer self, std::string const & name)"},
+	 { "MultiLayer_setName", _wrap_MultiLayer_setName, METH_VARARGS, "MultiLayer_setName(MultiLayer self, std::string const & name)"},
 	 { "MultiLayer_swigregister", MultiLayer_swigregister, METH_O, NULL},
 	 { "MultiLayer_swiginit", MultiLayer_swiginit, METH_VARARGS, NULL},
 	 { "delete_RoughnessModel", _wrap_delete_RoughnessModel, METH_O, "delete_RoughnessModel(RoughnessModel self)"},
-- 
GitLab


From a392a7bb4090bd07865ca62ea7a7d2d8e9ac5498 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 21:42:47 +0100
Subject: [PATCH 036/108] format

---
 Base/Types/VectorWC.h                  |  6 +++---
 GUI/Model/FromCore/ItemizeSample.cpp   |  3 +--
 GUI/View/List/InstrumentsQListView.cpp | 16 ++++++++--------
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/Base/Types/VectorWC.h b/Base/Types/VectorWC.h
index fb2e2929586..5b22dc82adc 100644
--- a/Base/Types/VectorWC.h
+++ b/Base/Types/VectorWC.h
@@ -54,9 +54,9 @@ public:
     }
     void delete_current()
     {
-	ASSERT(m_current_index != size_t(-1));
-	super::delete_at(m_current_index);
-	update_current();
+        ASSERT(m_current_index != size_t(-1));
+        super::delete_at(m_current_index);
+        update_current();
     }
     T* release_at(size_t i)
     {
diff --git a/GUI/Model/FromCore/ItemizeSample.cpp b/GUI/Model/FromCore/ItemizeSample.cpp
index 163acd16706..ab612650524 100644
--- a/GUI/Model/FromCore/ItemizeSample.cpp
+++ b/GUI/Model/FromCore/ItemizeSample.cpp
@@ -625,8 +625,7 @@ namespace GUI::FromCore {
 SampleItem* itemizeSample(const MultiLayer& sample, const QString& nodeName)
 {
     auto* result = new SampleItem();
-    result->setName(nodeName.isEmpty() ? QString::fromStdString(sample.name())
-                                             : nodeName);
+    result->setName(nodeName.isEmpty() ? QString::fromStdString(sample.name()) : nodeName);
     result->setCrossCorLength(sample.crossCorrLength());
     result->setExternalField(sample.externalField());
 
diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 72263222c83..25443764810 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -36,17 +36,17 @@ InstrumentsQListView::InstrumentsQListView()
     setModel(m_model);
     setItemDelegate(new ListItemDelegate(this));
 
-    connect(gActions->new_gisas_instrument, &QAction::triggered, [this]
-	{ m_model->pushInstrument(new Scatter2DInstrumentItem); });
+    connect(gActions->new_gisas_instrument, &QAction::triggered,
+            [this] { m_model->pushInstrument(new Scatter2DInstrumentItem); });
 
-    connect(gActions->new_offspec_instrument, &QAction::triggered, [this]
-	{ m_model->pushInstrument(new OffspecInstrumentItem); });
+    connect(gActions->new_offspec_instrument, &QAction::triggered,
+            [this] { m_model->pushInstrument(new OffspecInstrumentItem); });
 
-    connect(gActions->new_specular_instrument, &QAction::triggered, [this]
-	{ m_model->pushInstrument(new SpecularInstrumentItem); });
+    connect(gActions->new_specular_instrument, &QAction::triggered,
+            [this] { m_model->pushInstrument(new SpecularInstrumentItem); });
 
-    connect(gActions->new_depthprobe_instrument, &QAction::triggered, [this]
-	{ m_model->pushInstrument(new DepthprobeInstrumentItem); });
+    connect(gActions->new_depthprobe_instrument, &QAction::triggered,
+            [this] { m_model->pushInstrument(new DepthprobeInstrumentItem); });
 
     connect(gActions->remove_instrument, &QAction::triggered, m_model,
             &InstrumentsQModel::removeInstrument);
-- 
GitLab


From dc362f07cfc81c04df40a4ab63cc0d4a17bc811d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 22:12:23 +0100
Subject: [PATCH 037/108] Cloned GUI/View/Loader/PythonScriptWidget ->
 GUI/View/Loader/ComponentRW

---
 GUI/View/Loader/ComponentRW.cpp | 138 ++++++++++++++++++++++++++++++++
 GUI/View/Loader/ComponentRW.h   |  48 +++++++++++
 2 files changed, 186 insertions(+)
 create mode 100644 GUI/View/Loader/ComponentRW.cpp
 create mode 100644 GUI/View/Loader/ComponentRW.h

diff --git a/GUI/View/Loader/ComponentRW.cpp b/GUI/View/Loader/ComponentRW.cpp
new file mode 100644
index 00000000000..969a820ddcc
--- /dev/null
+++ b/GUI/View/Loader/ComponentRW.cpp
@@ -0,0 +1,138 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/View/Loader/ComponentRW.cpp
+//! @brief     Implements class PythonScriptWidget.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#include "GUI/View/Loader/PythonScriptWidget.h"
+#include "GUI/Model/ToCore/SimulationToCore.h"
+#include "GUI/Support/Style/Style.h"
+#include "GUI/View/Info/CautionSign.h"
+#include "GUI/View/Info/PythonSyntaxHighlighter.h"
+#include "GUI/View/Layout/ApplicationSettings.h"
+#include "GUI/View/Widget/StyledToolbar.h"
+#include "Sim/Export/ExportToPython.h"
+#include "Sim/Simulation/ScatteringSimulation.h"
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QStandardPaths>
+#include <QStyle>
+#include <QTextStream>
+#include <QToolBar>
+#include <QVBoxLayout>
+#include <memory>
+
+PythonScriptWidget::PythonScriptWidget(QWidget* parent)
+    : QDialog(parent)
+    , m_text_edit(new QTextEdit)
+    , m_caution_sign(new CautionSign(m_text_edit))
+{
+    auto* layout = new QVBoxLayout;
+    setLayout(layout);
+    layout->setContentsMargins(0, 0, 0, 0);
+
+    setObjectName("PythonScriptWidget");
+    setWindowTitle("Python Script");
+    setMinimumSize(128, 128);
+    resize(512, 400);
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+    auto* toolbar = new StyledToolbar;
+    layout->addWidget(toolbar);
+    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+
+    auto* exportAction = new QAction(this);
+    exportAction->setIcon(QIcon(":/images/content-save-outline.svg"));
+    exportAction->setText("Save to file");
+    exportAction->setToolTip("Opens dialog to save given script into the file");
+    connect(exportAction, &QAction::triggered, this, &PythonScriptWidget::onExportToFileButton);
+
+    toolbar->addAction(exportAction);
+
+    layout->addWidget(m_text_edit);
+    m_text_edit->setReadOnly(true);
+    QFont textFont("Monospace");
+    m_text_edit->setFont(textFont);
+    m_text_edit->setFontPointSize(GUI::Style::fontSizeRegular());
+    m_text_edit->setLineWrapMode(QTextEdit::NoWrap);
+    auto* highlighter = new PythonSyntaxHighlighter(m_text_edit->document());
+    Q_UNUSED(highlighter);
+
+    setAttribute(Qt::WA_DeleteOnClose, true);
+    GUI::Style::setResizable(this);
+    appSettings->loadWindowSizeAndPos(this);
+}
+
+
+PythonScriptWidget::~PythonScriptWidget()
+{
+    appSettings->saveWindowSizeAndPos(this);
+}
+
+void PythonScriptWidget::generatePythonScript(const SampleItem& sampleItem,
+                                              const InstrumentItem& instrumentItem,
+                                              const SimulationOptionsItem& optionItem,
+                                              const QString& outputDir)
+{
+    m_output_dir = outputDir;
+    m_caution_sign->clear();
+
+    try {
+        const auto simulation =
+            GUI::ToCore::itemsToSimulation(sampleItem, instrumentItem, optionItem);
+
+        QString code = QString::fromStdString(Py::Export::simulationPlotCode(*simulation));
+        m_text_edit->clear();
+        m_text_edit->setText(code);
+    } catch (const std::exception& ex) {
+        QString message =
+            QString(
+                "Generation of Python Script failed. Code is not complete.\n\n"
+                "It can happen if sample requires further assembling or some of sample parameters "
+                "are not valid. See details below.\n\n%1")
+                .arg(QString::fromStdString(ex.what()));
+
+        m_caution_sign->setCautionMessage(message);
+    }
+}
+
+void PythonScriptWidget::onExportToFileButton()
+{
+    QString dirname(m_output_dir);
+    if (dirname.isEmpty())
+        dirname = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
+
+    QString filters("Python scripts (*.py)");
+    QString defaultFilter("Python scripts (*.py)");
+    QString defaultName = dirname + "/untitled";
+
+    QString fname = QFileDialog::getSaveFileName(
+        nullptr, "Save file", defaultName, filters, &defaultFilter,
+        appSettings->useNativeFileDialog() ? QFileDialog::Options()
+                                           : QFileDialog::DontUseNativeDialog);
+
+    if (fname.isEmpty())
+        return;
+
+    if (!fname.endsWith(".py"))
+        fname += ".py";
+
+    QFile file(fname);
+    if (!file.open(QIODevice::WriteOnly)) {
+        QMessageBox::warning(this, "Save Python file", "File could not be opened for writing!");
+        return;
+    }
+    QTextStream out(&file);
+    out << m_text_edit->toPlainText();
+    file.close();
+    raise();
+}
diff --git a/GUI/View/Loader/ComponentRW.h b/GUI/View/Loader/ComponentRW.h
new file mode 100644
index 00000000000..2d72b5a4e10
--- /dev/null
+++ b/GUI/View/Loader/ComponentRW.h
@@ -0,0 +1,48 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/View/Loader/ComponentRW.h
+//! @brief     Defines class PythonScriptWidget.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#ifndef BORNAGAIN_GUI_VIEW_LOADER_COMPONENTRW_H
+#define BORNAGAIN_GUI_VIEW_LOADER_COMPONENTRW_H
+
+#include <QDialog>
+#include <QTextEdit>
+
+class CautionSign;
+class InstrumentItem;
+class SampleItem;
+class SimulationOptionsItem;
+
+//! The PythonScriptWidget displays a python script which represents full simulation.
+//! Part of SimulationSetupWidget
+
+class PythonScriptWidget : public QDialog {
+    Q_OBJECT
+public:
+    PythonScriptWidget(QWidget* parent = nullptr);
+    ~PythonScriptWidget() override;
+
+    void generatePythonScript(const SampleItem& sampleItem, const InstrumentItem& instrumentItem,
+                              const SimulationOptionsItem& optionItem,
+                              const QString& outputDir = "");
+
+private slots:
+    void onExportToFileButton();
+
+private:
+    QTextEdit* m_text_edit;
+    CautionSign* m_caution_sign;
+    QString m_output_dir;
+};
+
+#endif // BORNAGAIN_GUI_VIEW_LOADER_COMPONENTRW_H
-- 
GitLab


From e149af20d042459f64c5f3585ff5c49e054fec0b Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Feb 2024 22:51:48 +0100
Subject: [PATCH 038/108] use ComponentRW to save instrument as XML

---
 GUI/View/List/InstrumentsQListView.cpp |  18 +---
 GUI/View/Loader/ComponentRW.cpp        | 128 +++++--------------------
 GUI/View/Loader/ComponentRW.h          |  32 +------
 3 files changed, 29 insertions(+), 149 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 25443764810..4b8f1ea9947 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -20,6 +20,7 @@
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/InstrumentsQModel.h"
+#include "GUI/View/Loader/ComponentRW.h"
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/FileDialog.h"
 #include "GUI/View/Widget/ItemViewOverlayButtons.h"
@@ -91,22 +92,7 @@ QSize InstrumentsQListView::minimumSizeHint() const
 
 void InstrumentsQListView::onStoreInLibrary() const
 {
-    const InstrumentItem* t = gDoc->instruments()->currentItem();
-    if (!t)
-        return;
-
-    QString fname = GUI::Dialog::fileSaveDialog("Save instrument", appSettings->xml_dir,
-                                                "XML Files (*.xml)", t->name() + ".xml");
-    if (fname.isEmpty())
-        return;
-
-    try {
-        InstrumentXML::save(fname, t);
-    } catch (const std::exception& ex) {
-        QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", ex.what(), QMessageBox::Ok,
-                    nullptr)
-            .exec();
-    }
+    RW::saveComponent("instrument", gDoc->instruments()->currentItem());
 }
 
 void InstrumentsQListView::onLoadFromLibrary()
diff --git a/GUI/View/Loader/ComponentRW.cpp b/GUI/View/Loader/ComponentRW.cpp
index 969a820ddcc..a9098a58530 100644
--- a/GUI/View/Loader/ComponentRW.cpp
+++ b/GUI/View/Loader/ComponentRW.cpp
@@ -12,127 +12,43 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/View/Loader/PythonScriptWidget.h"
-#include "GUI/Model/ToCore/SimulationToCore.h"
-#include "GUI/Support/Style/Style.h"
-#include "GUI/View/Info/CautionSign.h"
-#include "GUI/View/Info/PythonSyntaxHighlighter.h"
+#include "GUI/View/Loader/ComponentRW.h"
+#include "GUI/Model/Device/InstrumentItems.h"
+#include "GUI/Model/Device/InstrumentXML.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
-#include "GUI/View/Widget/StyledToolbar.h"
-#include "Sim/Export/ExportToPython.h"
-#include "Sim/Simulation/ScatteringSimulation.h"
-#include <QFileDialog>
+#include "GUI/View/Widget/FileDialog.h"
 #include <QMessageBox>
-#include <QPushButton>
-#include <QStandardPaths>
-#include <QStyle>
-#include <QTextStream>
-#include <QToolBar>
-#include <QVBoxLayout>
-#include <memory>
 
-PythonScriptWidget::PythonScriptWidget(QWidget* parent)
-    : QDialog(parent)
-    , m_text_edit(new QTextEdit)
-    , m_caution_sign(new CautionSign(m_text_edit))
-{
-    auto* layout = new QVBoxLayout;
-    setLayout(layout);
-    layout->setContentsMargins(0, 0, 0, 0);
-
-    setObjectName("PythonScriptWidget");
-    setWindowTitle("Python Script");
-    setMinimumSize(128, 128);
-    resize(512, 400);
-    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-
-    auto* toolbar = new StyledToolbar;
-    layout->addWidget(toolbar);
-    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+namespace {
 
-    auto* exportAction = new QAction(this);
-    exportAction->setIcon(QIcon(":/images/content-save-outline.svg"));
-    exportAction->setText("Save to file");
-    exportAction->setToolTip("Opens dialog to save given script into the file");
-    connect(exportAction, &QAction::triggered, this, &PythonScriptWidget::onExportToFileButton);
+template <class T> void save(const QString& fname, const T* t);
 
-    toolbar->addAction(exportAction);
-
-    layout->addWidget(m_text_edit);
-    m_text_edit->setReadOnly(true);
-    QFont textFont("Monospace");
-    m_text_edit->setFont(textFont);
-    m_text_edit->setFontPointSize(GUI::Style::fontSizeRegular());
-    m_text_edit->setLineWrapMode(QTextEdit::NoWrap);
-    auto* highlighter = new PythonSyntaxHighlighter(m_text_edit->document());
-    Q_UNUSED(highlighter);
-
-    setAttribute(Qt::WA_DeleteOnClose, true);
-    GUI::Style::setResizable(this);
-    appSettings->loadWindowSizeAndPos(this);
-}
-
-
-PythonScriptWidget::~PythonScriptWidget()
+template <> void save<InstrumentItem>(const QString& fname, const InstrumentItem* t)
 {
-    appSettings->saveWindowSizeAndPos(this);
+    InstrumentXML::save(fname, t);
 }
 
-void PythonScriptWidget::generatePythonScript(const SampleItem& sampleItem,
-                                              const InstrumentItem& instrumentItem,
-                                              const SimulationOptionsItem& optionItem,
-                                              const QString& outputDir)
-{
-    m_output_dir = outputDir;
-    m_caution_sign->clear();
+} // namespace
 
-    try {
-        const auto simulation =
-            GUI::ToCore::itemsToSimulation(sampleItem, instrumentItem, optionItem);
 
-        QString code = QString::fromStdString(Py::Export::simulationPlotCode(*simulation));
-        m_text_edit->clear();
-        m_text_edit->setText(code);
-    } catch (const std::exception& ex) {
-        QString message =
-            QString(
-                "Generation of Python Script failed. Code is not complete.\n\n"
-                "It can happen if sample requires further assembling or some of sample parameters "
-                "are not valid. See details below.\n\n%1")
-                .arg(QString::fromStdString(ex.what()));
+// Force instantiation by assigning the function to a global variable that will never be used:
+auto dummy_saveComponent_InstrumentItem = &RW::saveComponent<class InstrumentItem>;
 
-        m_caution_sign->setCautionMessage(message);
-    }
-}
-
-void PythonScriptWidget::onExportToFileButton()
+template <class T> void RW::saveComponent(const QString& type, const T* t)
 {
-    QString dirname(m_output_dir);
-    if (dirname.isEmpty())
-        dirname = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
-
-    QString filters("Python scripts (*.py)");
-    QString defaultFilter("Python scripts (*.py)");
-    QString defaultName = dirname + "/untitled";
-
-    QString fname = QFileDialog::getSaveFileName(
-        nullptr, "Save file", defaultName, filters, &defaultFilter,
-        appSettings->useNativeFileDialog() ? QFileDialog::Options()
-                                           : QFileDialog::DontUseNativeDialog);
+    if (!t)
+        return;
 
+    QString fname = GUI::Dialog::fileSaveDialog("Save " + type, appSettings->xml_dir,
+                                                "XML Files (*.xml)", t->name() + ".xml");
     if (fname.isEmpty())
         return;
 
-    if (!fname.endsWith(".py"))
-        fname += ".py";
-
-    QFile file(fname);
-    if (!file.open(QIODevice::WriteOnly)) {
-        QMessageBox::warning(this, "Save Python file", "File could not be opened for writing!");
-        return;
+    try {
+        ::save<T>(fname, t);
+    } catch (const std::exception& ex) {
+        QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", ex.what(), QMessageBox::Ok,
+                    nullptr)
+            .exec();
     }
-    QTextStream out(&file);
-    out << m_text_edit->toPlainText();
-    file.close();
-    raise();
 }
diff --git a/GUI/View/Loader/ComponentRW.h b/GUI/View/Loader/ComponentRW.h
index 2d72b5a4e10..bb141642f28 100644
--- a/GUI/View/Loader/ComponentRW.h
+++ b/GUI/View/Loader/ComponentRW.h
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit reflection and scattering
 //
 //! @file      GUI/View/Loader/ComponentRW.h
-//! @brief     Defines class PythonScriptWidget.
+//! @brief     Defines functions in namespace RW
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -15,34 +15,12 @@
 #ifndef BORNAGAIN_GUI_VIEW_LOADER_COMPONENTRW_H
 #define BORNAGAIN_GUI_VIEW_LOADER_COMPONENTRW_H
 
-#include <QDialog>
-#include <QTextEdit>
+#include <QString>
 
-class CautionSign;
-class InstrumentItem;
-class SampleItem;
-class SimulationOptionsItem;
+namespace RW {
 
-//! The PythonScriptWidget displays a python script which represents full simulation.
-//! Part of SimulationSetupWidget
+template <class T> void saveComponent(const QString& type, const T* t);
 
-class PythonScriptWidget : public QDialog {
-    Q_OBJECT
-public:
-    PythonScriptWidget(QWidget* parent = nullptr);
-    ~PythonScriptWidget() override;
-
-    void generatePythonScript(const SampleItem& sampleItem, const InstrumentItem& instrumentItem,
-                              const SimulationOptionsItem& optionItem,
-                              const QString& outputDir = "");
-
-private slots:
-    void onExportToFileButton();
-
-private:
-    QTextEdit* m_text_edit;
-    CautionSign* m_caution_sign;
-    QString m_output_dir;
-};
+} // namespace RW
 
 #endif // BORNAGAIN_GUI_VIEW_LOADER_COMPONENTRW_H
-- 
GitLab


From ab6922861d03a9286fb69cca891f415b23ef9c5f Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 08:22:35 +0100
Subject: [PATCH 039/108] ownership of instrs list model transfered from
 listview to InstrView

---
 GUI/View/List/InstrumentsQListView.cpp | 9 ++-------
 GUI/View/List/InstrumentsQListView.h   | 5 ++---
 GUI/View/List/InstrumentsQModel.cpp    | 5 ++++-
 GUI/View/List/InstrumentsQModel.h      | 2 +-
 GUI/View/Views/InstrumentView.cpp      | 4 +++-
 GUI/View/Views/InstrumentView.h        | 2 ++
 6 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 4b8f1ea9947..1e5540bb878 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -27,8 +27,8 @@
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QMessageBox>
 
-InstrumentsQListView::InstrumentsQListView()
-    : m_model(new InstrumentsQModel)
+InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
+    : m_model(model)
 {
     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
     setMovement(QListView::Static);
@@ -75,11 +75,6 @@ InstrumentsQListView::InstrumentsQListView()
     setContextMenuPolicy(Qt::ActionsContextMenu);
 }
 
-InstrumentsQListView::~InstrumentsQListView()
-{
-    delete m_model;
-}
-
 QSize InstrumentsQListView::sizeHint() const
 {
     return {170, 400};
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 558602eaaed..1ce9c60f2c6 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -25,8 +25,7 @@ class InstrumentsQModel;
 class InstrumentsQListView : public QListView {
     Q_OBJECT
 public:
-    InstrumentsQListView();
-    ~InstrumentsQListView();
+    InstrumentsQListView(InstrumentsQModel*);
 
     QSize sizeHint() const override;
     QSize minimumSizeHint() const override;
@@ -36,7 +35,7 @@ private slots:
     void onLoadFromLibrary();
 
 private:
-    InstrumentsQModel* m_model;
+    InstrumentsQModel* const m_model;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_INSTRUMENTSQLISTVIEW_H
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index e879abf5298..f749b493703 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -20,7 +20,10 @@
 #include <QColor>
 #include <QUuid>
 
-InstrumentsQModel::InstrumentsQModel() {}
+InstrumentsQModel::InstrumentsQModel(QObject* parent)
+    : QAbstractListModel(parent) // parent needed to ensure end of life
+{
+}
 
 InstrumentsSet* InstrumentsQModel::set()
 {
diff --git a/GUI/View/List/InstrumentsQModel.h b/GUI/View/List/InstrumentsQModel.h
index 8be19427d5b..ac106d15393 100644
--- a/GUI/View/List/InstrumentsQModel.h
+++ b/GUI/View/List/InstrumentsQModel.h
@@ -25,7 +25,7 @@ class InstrumentsSet;
 class InstrumentsQModel : public QAbstractListModel {
     Q_OBJECT
 public:
-    InstrumentsQModel();
+    InstrumentsQModel(QObject* parent);
 
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index bc083071895..fa4e5e4205b 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -23,6 +23,7 @@
 #include "GUI/View/Instrument/SpecularInstrumentEditor.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/InstrumentsQListView.h"
+#include "GUI/View/List/InstrumentsQModel.h"
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/GroupBoxes.h"
 #include "GUI/View/Widget/StyledToolbar.h"
@@ -32,7 +33,8 @@
 #include <iostream>
 
 InstrumentView::InstrumentView()
-    : m_qlistview(new InstrumentsQListView)
+    : m_qlistmodel(new InstrumentsQModel(this))
+    , m_qlistview(new InstrumentsQListView(m_qlistmodel))
     , m_scroll_area(new QScrollArea)
 {
     auto* layout = new QVBoxLayout(this);
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index ee4193b8320..ad76a451848 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -21,6 +21,7 @@
 
 class InstrumentItem;
 class InstrumentsQListView;
+class InstrumentsQModel;
 
 class InstrumentView : public QWidget {
     Q_OBJECT
@@ -33,6 +34,7 @@ private slots:
 private:
     void createWidgetsForCurrentInstrument();
 
+    InstrumentsQModel* m_qlistmodel;
     InstrumentsQListView* m_qlistview;
     QScrollArea* m_scroll_area;
 };
-- 
GitLab


From f159bf76ee82863e2f8dfa53b0706d3e9922a513 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 08:25:52 +0100
Subject: [PATCH 040/108] connect actions in InstrsView

---
 GUI/View/List/InstrumentsQListView.cpp | 18 ------------------
 GUI/View/Views/InstrumentView.cpp      | 18 ++++++++++++++++++
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 1e5540bb878..e9eb8532329 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -37,24 +37,6 @@ InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
     setModel(m_model);
     setItemDelegate(new ListItemDelegate(this));
 
-    connect(gActions->new_gisas_instrument, &QAction::triggered,
-            [this] { m_model->pushInstrument(new Scatter2DInstrumentItem); });
-
-    connect(gActions->new_offspec_instrument, &QAction::triggered,
-            [this] { m_model->pushInstrument(new OffspecInstrumentItem); });
-
-    connect(gActions->new_specular_instrument, &QAction::triggered,
-            [this] { m_model->pushInstrument(new SpecularInstrumentItem); });
-
-    connect(gActions->new_depthprobe_instrument, &QAction::triggered,
-            [this] { m_model->pushInstrument(new DepthprobeInstrumentItem); });
-
-    connect(gActions->remove_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::removeInstrument);
-
-    connect(gActions->copy_instrument, &QAction::triggered, m_model,
-            &InstrumentsQModel::copyInstrument);
-
     connect(gActions->store_in_library_instrument, &QAction::triggered, this,
             &InstrumentsQListView::onStoreInLibrary);
 
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index fa4e5e4205b..999a5f5c279 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -72,6 +72,24 @@ InstrumentView::InstrumentView()
 
     //... Finalize
 
+    connect(gActions->new_gisas_instrument, &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new Scatter2DInstrumentItem); });
+
+    connect(gActions->new_offspec_instrument, &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new OffspecInstrumentItem); });
+
+    connect(gActions->new_specular_instrument, &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new SpecularInstrumentItem); });
+
+    connect(gActions->new_depthprobe_instrument, &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new DepthprobeInstrumentItem); });
+
+    connect(gActions->remove_instrument, &QAction::triggered, m_qlistmodel,
+            &InstrumentsQModel::removeInstrument);
+
+    connect(gActions->copy_instrument, &QAction::triggered, m_qlistmodel,
+            &InstrumentsQModel::copyInstrument);
+
     connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
-- 
GitLab


From 01e3ac941f809e66d224c7bbb5ef2db956804001 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 08:43:16 +0100
Subject: [PATCH 041/108] + RW::loadComponent

---
 GUI/View/List/InstrumentsQListView.cpp | 14 +-------------
 GUI/View/List/InstrumentsQModel.cpp    |  3 +++
 GUI/View/Loader/ComponentRW.cpp        | 23 +++++++++++++++++++++++
 GUI/View/Loader/ComponentRW.h          |  1 +
 4 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index e9eb8532329..a4cb4f64c0a 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -74,17 +74,5 @@ void InstrumentsQListView::onStoreInLibrary() const
 
 void InstrumentsQListView::onLoadFromLibrary()
 {
-    QString fname =
-        GUI::Dialog::fileOpenDialog("Load instrument", appSettings->xml_dir, "XML Files (*.xml)");
-    if (fname.isEmpty())
-        return;
-
-    try {
-        if (InstrumentItem* t = InstrumentXML::load(fname))
-            m_model->pushInstrument(t);
-    } catch (const std::exception& ex) {
-        QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", ex.what(), QMessageBox::Ok,
-                    nullptr)
-            .exec();
-    }
+    m_model->pushInstrument(RW::loadComponent<InstrumentItem>("instrument"));
 }
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index f749b493703..ae7f3162b04 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -73,6 +73,7 @@ void InstrumentsQModel::removeInstrument()
 QModelIndex InstrumentsQModel::copyInstrument()
 {
     const InstrumentItem* t = set()->currentItem();
+    ASSERT(t);
     InstrumentItem* t2 = t->createItemCopy();
     t2->setId(QUuid::createUuid().toString());
     return pushInstrument(t2);
@@ -80,6 +81,8 @@ QModelIndex InstrumentsQModel::copyInstrument()
 
 QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 {
+    if (!t)
+	return {};
     const size_t row = set()->size();
     beginInsertRows({}, row, row);
     set()->push_back(t);
diff --git a/GUI/View/Loader/ComponentRW.cpp b/GUI/View/Loader/ComponentRW.cpp
index a9098a58530..f5db8e1027f 100644
--- a/GUI/View/Loader/ComponentRW.cpp
+++ b/GUI/View/Loader/ComponentRW.cpp
@@ -22,17 +22,23 @@
 namespace {
 
 template <class T> void save(const QString& fname, const T* t);
+template <class T> T* load(const QString& fname);
 
 template <> void save<InstrumentItem>(const QString& fname, const InstrumentItem* t)
 {
     InstrumentXML::save(fname, t);
 }
+template <> InstrumentItem* load<InstrumentItem>(const QString& fname)
+{
+    return InstrumentXML::load(fname);
+}
 
 } // namespace
 
 
 // Force instantiation by assigning the function to a global variable that will never be used:
 auto dummy_saveComponent_InstrumentItem = &RW::saveComponent<class InstrumentItem>;
+auto dummy_loadComponent_InstrumentItem = &RW::loadComponent<class InstrumentItem>;
 
 template <class T> void RW::saveComponent(const QString& type, const T* t)
 {
@@ -52,3 +58,20 @@ template <class T> void RW::saveComponent(const QString& type, const T* t)
             .exec();
     }
 }
+
+template <class T> T* RW::loadComponent(const QString& type)
+{
+    QString fname =
+        GUI::Dialog::fileOpenDialog("Load " + type, appSettings->xml_dir, "XML Files (*.xml)");
+    if (fname.isEmpty())
+        return nullptr;
+
+    try {
+        return ::load<T>(fname);
+    } catch (const std::exception& ex) {
+        QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", ex.what(), QMessageBox::Ok,
+                    nullptr)
+            .exec();
+    }
+    return nullptr;
+}
diff --git a/GUI/View/Loader/ComponentRW.h b/GUI/View/Loader/ComponentRW.h
index bb141642f28..a191249df71 100644
--- a/GUI/View/Loader/ComponentRW.h
+++ b/GUI/View/Loader/ComponentRW.h
@@ -20,6 +20,7 @@
 namespace RW {
 
 template <class T> void saveComponent(const QString& type, const T* t);
+template <class T> T* loadComponent(const QString& type);
 
 } // namespace RW
 
-- 
GitLab


From 6f217874ee4213e46f30cb2dfebfc961b9ec81a0 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 08:47:16 +0100
Subject: [PATCH 042/108] mv save/load slots out of InstrsQListView

---
 GUI/View/List/InstrumentsQListView.cpp | 17 -----------------
 GUI/View/List/InstrumentsQListView.h   |  4 ----
 GUI/View/Views/InstrumentView.cpp      |  7 +++++++
 3 files changed, 7 insertions(+), 21 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index a4cb4f64c0a..87ef050ba65 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -20,7 +20,6 @@
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/InstrumentsQModel.h"
-#include "GUI/View/Loader/ComponentRW.h"
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/FileDialog.h"
 #include "GUI/View/Widget/ItemViewOverlayButtons.h"
@@ -37,12 +36,6 @@ InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
     setModel(m_model);
     setItemDelegate(new ListItemDelegate(this));
 
-    connect(gActions->store_in_library_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onStoreInLibrary);
-
-    connect(gActions->load_from_library_instrument, &QAction::triggered, this,
-            &InstrumentsQListView::onLoadFromLibrary);
-
     connect(this, &QListView::clicked, [](const QModelIndex& qi) {
         gDoc->instrumentsModifier()->setCurrentIndex(qi.row());
         emit gDoc->instruments()->setChanged();
@@ -66,13 +59,3 @@ QSize InstrumentsQListView::minimumSizeHint() const
 {
     return {96, 200};
 }
-
-void InstrumentsQListView::onStoreInLibrary() const
-{
-    RW::saveComponent("instrument", gDoc->instruments()->currentItem());
-}
-
-void InstrumentsQListView::onLoadFromLibrary()
-{
-    m_model->pushInstrument(RW::loadComponent<InstrumentItem>("instrument"));
-}
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 1ce9c60f2c6..43c9a132231 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -30,10 +30,6 @@ public:
     QSize sizeHint() const override;
     QSize minimumSizeHint() const override;
 
-private slots:
-    void onStoreInLibrary() const;
-    void onLoadFromLibrary();
-
 private:
     InstrumentsQModel* const m_model;
 };
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 999a5f5c279..9eea8930fd7 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -24,6 +24,7 @@
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/InstrumentsQListView.h"
 #include "GUI/View/List/InstrumentsQModel.h"
+#include "GUI/View/Loader/ComponentRW.h"
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/GroupBoxes.h"
 #include "GUI/View/Widget/StyledToolbar.h"
@@ -93,6 +94,12 @@ InstrumentView::InstrumentView()
     connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
+    connect(gActions->store_in_library_instrument, &QAction::triggered, []
+	{ RW::saveComponent("instrument", gDoc->instruments()->currentItem()); });
+
+    connect(gActions->load_from_library_instrument, &QAction::triggered, [this]
+	{ m_qlistmodel->pushInstrument(RW::loadComponent<InstrumentItem>("instrument")); });
+
     updateActions();
 }
 
-- 
GitLab


From 11b5cfe6cde4a9b09371fea9401a75b66057a3fb Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 08:51:32 +0100
Subject: [PATCH 043/108] rm includes

---
 GUI/View/List/InstrumentsQListView.cpp | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 87ef050ba65..3b334328f2d 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -13,18 +13,11 @@
 //  ************************************************************************************************
 
 #include "GUI/View/List/InstrumentsQListView.h"
-#include "Base/Util/Assert.h"
-#include "GUI/Model/Device/InstrumentItems.h"
-#include "GUI/Model/Device/InstrumentXML.h"
 #include "GUI/Model/Device/InstrumentsSet.h"
 #include "GUI/Model/Project/ProjectDocument.h"
-#include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/InstrumentsQModel.h"
-#include "GUI/View/Setup/FrameActions.h"
-#include "GUI/View/Widget/FileDialog.h"
 #include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
-#include <QMessageBox>
 
 InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
     : m_model(model)
-- 
GitLab


From 94d7a1ad1cb87a0883a909a520940a891f75909a Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 08:53:39 +0100
Subject: [PATCH 044/108] rm InstrumentsQListView::m_model

---
 GUI/View/List/InstrumentsQListView.cpp | 7 +++----
 GUI/View/List/InstrumentsQListView.h   | 4 ----
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 3b334328f2d..32c80704af3 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -20,13 +20,12 @@
 #include "GUI/View/Widget/ListItemDelegate.h"
 
 InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
-    : m_model(model)
 {
     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
     setMovement(QListView::Static);
     setSelectionMode(QAbstractItemView::NoSelection);
 
-    setModel(m_model);
+    setModel(model);
     setItemDelegate(new ListItemDelegate(this));
 
     connect(this, &QListView::clicked, [](const QModelIndex& qi) {
@@ -35,8 +34,8 @@ InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
     });
 
     disconnect(gDoc->instruments(), &InstrumentsSet::setChanged, nullptr, nullptr);
-    connect(gDoc->instruments(), &InstrumentsSet::setChanged, [this] {
-        setCurrentIndex(m_model->index(gDoc->instruments()->currentIndex(), 0));
+    connect(gDoc->instruments(), &InstrumentsSet::setChanged, [this, model] {
+        setCurrentIndex(model->index(gDoc->instruments()->currentIndex(), 0));
         repaint();
     });
 
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 43c9a132231..54973da1821 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -17,7 +17,6 @@
 
 #include <QListView>
 
-class InstrumentItem;
 class InstrumentsQModel;
 
 //! Instrument selector on the left side of InstrumentView.
@@ -29,9 +28,6 @@ public:
 
     QSize sizeHint() const override;
     QSize minimumSizeHint() const override;
-
-private:
-    InstrumentsQModel* const m_model;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_INSTRUMENTSQLISTVIEW_H
-- 
GitLab


From cf6d058e9f524d5f84abd67f7da13125e050f810 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 09:07:45 +0100
Subject: [PATCH 045/108] simplify setting of list width

---
 GUI/View/List/InstrumentsQListView.cpp | 10 ----------
 GUI/View/List/InstrumentsQListView.h   |  3 ---
 GUI/View/Views/InstrumentView.cpp      |  1 +
 3 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 32c80704af3..d129035608f 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -41,13 +41,3 @@ InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
 
     setContextMenuPolicy(Qt::ActionsContextMenu);
 }
-
-QSize InstrumentsQListView::sizeHint() const
-{
-    return {170, 400};
-}
-
-QSize InstrumentsQListView::minimumSizeHint() const
-{
-    return {96, 200};
-}
diff --git a/GUI/View/List/InstrumentsQListView.h b/GUI/View/List/InstrumentsQListView.h
index 54973da1821..c53676d3b2e 100644
--- a/GUI/View/List/InstrumentsQListView.h
+++ b/GUI/View/List/InstrumentsQListView.h
@@ -25,9 +25,6 @@ class InstrumentsQListView : public QListView {
     Q_OBJECT
 public:
     InstrumentsQListView(InstrumentsQModel*);
-
-    QSize sizeHint() const override;
-    QSize minimumSizeHint() const override;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_INSTRUMENTSQLISTVIEW_H
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 9eea8930fd7..27195e4e19d 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -61,6 +61,7 @@ InstrumentView::InstrumentView()
     // Left margin: instrument list
 
     hLayout->addWidget(m_qlistview);
+    m_qlistview->setMinimumWidth(200);
 
     // Large widget: current instrument
 
-- 
GitLab


From 8346a9f2689ae8a8f7f5c548be0416cdea2d62f4 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 09:16:50 +0100
Subject: [PATCH 046/108] mv description to NamedItem

---
 GUI/Model/Device/InstrumentItems.cpp | 4 ++--
 GUI/Model/Device/InstrumentItems.h   | 4 ----
 GUI/Model/Sample/SampleItem.cpp      | 4 ++--
 GUI/Model/Sample/SampleItem.h        | 4 ----
 GUI/Model/Type/NamedItem.h           | 7 ++++++-
 5 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index 1f8d78766a3..a5f12b514c6 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -138,7 +138,7 @@ void InstrumentItem::writeTo(QXmlStreamWriter* w) const
 
     // description
     w->writeStartElement(Tag::Description);
-    XML::writeAttribute(w, XML::Attrib::value, m_description);
+    XML::writeAttribute(w, XML::Attrib::value, description());
     w->writeEndElement();
 
     // with polarizer?
@@ -206,7 +206,7 @@ void InstrumentItem::readFrom(QXmlStreamReader* r)
 
             // description
         } else if (tag == Tag::Description) {
-            XML::readAttribute(r, XML::Attrib::value, &m_description);
+            setDescription(XML::readAttributeString(r, XML::Attrib::value));
             XML::gotoEndElementOfTag(r, tag);
 
             // with polarizer or analyzer? (OBSOLETE since v21 (version == 2))
diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h
index 82d976652a7..83ee21087ed 100644
--- a/GUI/Model/Device/InstrumentItems.h
+++ b/GUI/Model/Device/InstrumentItems.h
@@ -67,9 +67,6 @@ public:
 
     template <typename T> bool is() const { return dynamic_cast<const T*>(this) != nullptr; }
 
-    QString description() const { return m_description; }
-    void setDescription(const QString& description) { m_description = description; }
-
     template <typename T> T* setBackgroundItemType();
     PolyItem<BackgroundItemCatalog>& backgroundSelection() { return m_background; }
     BackgroundItem* backgroundItem() const { return m_background.certainItem(); }
@@ -96,7 +93,6 @@ protected:
     explicit InstrumentItem(const QString& modelType);
 
     QString m_id;
-    QString m_description;
     bool m_with_polarizer;
     bool m_with_analyzer;
     PolyItem<BackgroundItemCatalog> m_background;
diff --git a/GUI/Model/Sample/SampleItem.cpp b/GUI/Model/Sample/SampleItem.cpp
index 4e7af36b312..dd8cbb8e452 100644
--- a/GUI/Model/Sample/SampleItem.cpp
+++ b/GUI/Model/Sample/SampleItem.cpp
@@ -135,7 +135,7 @@ void SampleItem::writeTo(QXmlStreamWriter* w) const
 
     // description
     w->writeStartElement(Tag::Description);
-    XML::writeAttribute(w, XML::Attrib::value, m_description);
+    XML::writeAttribute(w, XML::Attrib::value, description());
     w->writeEndElement();
 
     // cross-correlation length
@@ -183,7 +183,7 @@ void SampleItem::readFrom(QXmlStreamReader* r)
 
             // description
         } else if (tag == Tag::Description) {
-            XML::readAttribute(r, XML::Attrib::value, &m_description);
+            setDescription(XML::readAttributeString(r, XML::Attrib::value));
             XML::gotoEndElementOfTag(r, tag);
 
             // cross-correlation length
diff --git a/GUI/Model/Sample/SampleItem.h b/GUI/Model/Sample/SampleItem.h
index 375e301dd93..f5708cfd504 100644
--- a/GUI/Model/Sample/SampleItem.h
+++ b/GUI/Model/Sample/SampleItem.h
@@ -37,9 +37,6 @@ public:
 
     void addStandardMaterials();
 
-    QString description() const { return m_description; }
-    void setDescription(const QString& s) { m_description = s; }
-
     DoubleProperty& crossCorrLength() { return m_cross_correlation_length; }
     const DoubleProperty& crossCorrLength() const { return m_cross_correlation_length; }
     void setCrossCorLength(double d) { m_cross_correlation_length.setValue(d); }
@@ -69,7 +66,6 @@ public:
     bool expandInfo = true;
 
 private:
-    QString m_description;
     DoubleProperty m_cross_correlation_length;
     VectorProperty m_external_field;
     OwningVector<LayerItem> m_layers;
diff --git a/GUI/Model/Type/NamedItem.h b/GUI/Model/Type/NamedItem.h
index 2c67239ed50..d982eace4c5 100644
--- a/GUI/Model/Type/NamedItem.h
+++ b/GUI/Model/Type/NamedItem.h
@@ -17,7 +17,8 @@
 
 #include <QString>
 
-//! Base class of items that can be at the root of a realspace 3D representation
+//! Base class of items that have a name and a description.
+
 class NamedItem {
 public:
     virtual ~NamedItem() = default;
@@ -25,8 +26,12 @@ public:
     void setName(const QString& name) { m_name = name; }
     QString name() const { return m_name; }
 
+    QString description() const { return m_description; }
+    void setDescription(const QString& description) { m_description = description; }
+
 private:
     QString m_name;
+    QString m_description;
 };
 
 #endif // BORNAGAIN_GUI_MODEL_TYPE_NAMEDITEM_H
-- 
GitLab


From 21a4100e835b30ae910b3952331ced470aafda04 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 12:59:29 +0100
Subject: [PATCH 047/108] start standardization of SamplesQModel

---
 GUI/View/List/InstrumentsQModel.cpp |  2 +-
 GUI/View/List/SamplesQListView.cpp  |  2 +-
 GUI/View/List/SamplesQModel.cpp     | 21 +++++++++++++++++----
 GUI/View/List/SamplesQModel.h       |  7 +++++++
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index ae7f3162b04..97b3e84b833 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -37,7 +37,7 @@ const InstrumentsSet* InstrumentsQModel::set() const
 
 int InstrumentsQModel::rowCount(const QModelIndex&) const
 {
-    return set()->instrumentItems().size();
+    return set()->size();
 }
 
 QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 78f0d3be4ab..2b89045a120 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -27,7 +27,7 @@
 #include <QPainter>
 
 SamplesQListView::SamplesQListView()
-    : m_model(new SamplesQModel)
+    : m_model(new SamplesQModel(this))
     , m_new_sample_action(new QAction(this))
     , m_import_sample_action(new QAction(this))
     , m_choose_from_library_action(new QAction(this))
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 84eef45dcf4..43f9aeae75e 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -23,14 +23,27 @@
 #include "GUI/View/Manager/PyImportAssistant.h"
 #include "Sample/Multilayer/MultiLayer.h"
 
-int SamplesQModel::rowCount(const QModelIndex& parent) const
+SamplesQModel::SamplesQModel(QObject* parent)
+    : QAbstractListModel(parent) // parent needed to ensure end of life
 {
-    if (parent.isValid())
-        return 0;
+}
 
-    return gDoc->samples()->shared().size();
+SamplesSet* SamplesQModel::set()
+{
+    return gDoc->samplesModifier();
+}
+
+const SamplesSet* SamplesQModel::set() const
+{
+    return gDoc->samples();
 }
 
+int SamplesQModel::rowCount(const QModelIndex&) const
+{
+    return set()->size();
+}
+
+
 QVariant SamplesQModel::data(const QModelIndex& index, int role) const
 {
     auto* const item = itemForIndex(index);
diff --git a/GUI/View/List/SamplesQModel.h b/GUI/View/List/SamplesQModel.h
index c92752a0d0e..90cea5640ca 100644
--- a/GUI/View/List/SamplesQModel.h
+++ b/GUI/View/List/SamplesQModel.h
@@ -18,12 +18,15 @@
 #include <QAbstractListModel>
 
 class SampleItem;
+class SamplesSet;
 
 //! Data model for SamplesQListView.
 
 class SamplesQModel : public QAbstractListModel {
     Q_OBJECT
 public:
+    SamplesQModel(QObject* parent);
+
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 
@@ -51,6 +54,10 @@ public:
     //! Returns invalid index if anything went wrong.
     QModelIndex createSampleFromPython();
 #endif
+
+private:
+    SamplesSet* set();
+    const SamplesSet* set() const;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_SAMPLESQMODEL_H
-- 
GitLab


From aaccf19ac342775965a986746a3fd58afa3623cb Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 13:20:35 +0100
Subject: [PATCH 048/108] use fct set()

---
 GUI/View/List/InstrumentsQModel.cpp |  2 +-
 GUI/View/List/SamplesQModel.cpp     | 37 ++++++++++++++++-------------
 GUI/View/List/SamplesQModel.h       |  3 ++-
 GUI/View/Views/InstrumentView.cpp   |  9 +++----
 4 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 97b3e84b833..17bbbdfdbff 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -82,7 +82,7 @@ QModelIndex InstrumentsQModel::copyInstrument()
 QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
 {
     if (!t)
-	return {};
+        return {};
     const size_t row = set()->size();
     beginInsertRows({}, row, row);
     set()->push_back(t);
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 43f9aeae75e..0dd1d761376 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -46,7 +46,7 @@ int SamplesQModel::rowCount(const QModelIndex&) const
 
 QVariant SamplesQModel::data(const QModelIndex& index, int role) const
 {
-    auto* const item = itemForIndex(index);
+    const auto* item = itemForIndex(index);
 
     if (role == Qt::ToolTipRole)
         return item->description();
@@ -57,19 +57,24 @@ QVariant SamplesQModel::data(const QModelIndex& index, int role) const
     return {};
 }
 
-SampleItem* SamplesQModel::itemForIndex(const QModelIndex& index) const
+const SampleItem* SamplesQModel::itemForIndex(const QModelIndex& index) const
 {
     if (!index.isValid())
         return nullptr;
+    return set()->at(index.row());
+}
 
-    return gDoc->samples()->shared()[index.row()];
+SampleItem* SamplesQModel::itemForIndex(const QModelIndex& index)
+{
+    if (!index.isValid())
+        return nullptr;
+    return set()->at(index.row());
 }
 
 QModelIndex SamplesQModel::indexForItem(SampleItem* item) const
 {
-    if (auto row = gDoc->samples()->index_of(item); row >= 0)
+    if (auto row = set()->index_of(item); row >= 0)
         return index(row, 0);
-
     return {};
 }
 
@@ -80,36 +85,36 @@ void SamplesQModel::removeSample(SampleItem* item)
         return;
 
     beginRemoveRows(index.parent(), index.row(), index.row());
-    gDoc->samplesModifier()->delete_element(item);
+    set()->delete_element(item);
     endRemoveRows();
 }
 
 QModelIndex SamplesQModel::copySample(SampleItem* item)
 {
     ASSERT(item);
-    const QStringList existingNames = gDoc->samples()->sampleNames();
+    const QStringList existingNames = set()->sampleNames();
 
-    const int row = gDoc->samples()->shared().size();
+    const int row = set()->size();
     beginInsertRows(QModelIndex(), row, row);
     SampleItem* copied_item = item->clone();
     copied_item->setName(GUI::Util::String::suggestName(existingNames, item->name()));
-    gDoc->samplesModifier()->push_back(copied_item);
+    set()->push_back(copied_item);
     endInsertRows();
     return indexForItem(copied_item);
 }
 
 QModelIndex SamplesQModel::createSample()
 {
-    const QStringList existingNames = gDoc->samples()->sampleNames();
+    const QStringList existingNames = set()->sampleNames();
 
     auto* t = new SampleItem;
     t->setName(GUI::Util::String::suggestName(existingNames, "Sample"));
     t->addStandardMaterials();
 
-    const int row = gDoc->samples()->shared().size();
+    const int row = set()->size();
 
     beginInsertRows(QModelIndex(), row, row);
-    gDoc->samplesModifier()->push_back(t);
+    set()->push_back(t);
     endInsertRows();
 
     return indexForItem(t);
@@ -124,10 +129,10 @@ QModelIndex SamplesQModel::createSampleFromExamples(const QString& className, co
     t->setName(title);
     t->setDescription(description);
 
-    const int row = gDoc->samples()->shared().size();
+    const int row = set()->size();
 
     beginInsertRows(QModelIndex(), row, row);
-    gDoc->samplesModifier()->push_back(t);
+    set()->push_back(t);
     endInsertRows();
 
     return indexForItem(t);
@@ -145,10 +150,10 @@ QModelIndex SamplesQModel::createSampleFromPython()
         return {}; // any messages already shown to user
     t->setDescription("Imported from python code");
 
-    const int row = gDoc->samples()->shared().size();
+    const int row = set()->size();
 
     beginInsertRows(QModelIndex(), row, row);
-    gDoc->samplesModifier()->push_back(t);
+    set()->push_back(t);
     endInsertRows();
 
     return indexForItem(t);
diff --git a/GUI/View/List/SamplesQModel.h b/GUI/View/List/SamplesQModel.h
index 90cea5640ca..17dadc98505 100644
--- a/GUI/View/List/SamplesQModel.h
+++ b/GUI/View/List/SamplesQModel.h
@@ -30,7 +30,8 @@ public:
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 
-    SampleItem* itemForIndex(const QModelIndex& index) const;
+    SampleItem* itemForIndex(const QModelIndex& index);
+    const SampleItem* itemForIndex(const QModelIndex& index) const;
     QModelIndex indexForItem(SampleItem* item) const;
 
     //! Remove the given sample. nullptr is allowed.
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 27195e4e19d..1d2d61ba876 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -95,11 +95,12 @@ InstrumentView::InstrumentView()
     connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
-    connect(gActions->store_in_library_instrument, &QAction::triggered, []
-	{ RW::saveComponent("instrument", gDoc->instruments()->currentItem()); });
+    connect(gActions->store_in_library_instrument, &QAction::triggered,
+            [] { RW::saveComponent("instrument", gDoc->instruments()->currentItem()); });
 
-    connect(gActions->load_from_library_instrument, &QAction::triggered, [this]
-	{ m_qlistmodel->pushInstrument(RW::loadComponent<InstrumentItem>("instrument")); });
+    connect(gActions->load_from_library_instrument, &QAction::triggered, [this] {
+        m_qlistmodel->pushInstrument(RW::loadComponent<InstrumentItem>("instrument"));
+    });
 
     updateActions();
 }
-- 
GitLab


From f5d5b1dcd93df916658cbd7b375a630bc9fa8ce4 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 13:22:47 +0100
Subject: [PATCH 049/108] same data() for Instr & Sample

---
 GUI/View/List/InstrumentsQModel.cpp |  2 ++
 GUI/View/List/SamplesQModel.cpp     | 28 ++++++++++++++++++----------
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 17bbbdfdbff..424cbe5ffc6 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -52,6 +52,8 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     switch (role) {
     case Qt::DisplayRole:
         return t->name();
+    case Qt::ToolTipRole:
+        return t->description();
     case Qt::BackgroundRole:
         return row == set()->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
     default:
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 0dd1d761376..5e9d589d918 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -22,6 +22,7 @@
 #include "GUI/Support/Util/String.h"
 #include "GUI/View/Manager/PyImportAssistant.h"
 #include "Sample/Multilayer/MultiLayer.h"
+#include <QColor>
 
 SamplesQModel::SamplesQModel(QObject* parent)
     : QAbstractListModel(parent) // parent needed to ensure end of life
@@ -43,18 +44,25 @@ int SamplesQModel::rowCount(const QModelIndex&) const
     return set()->size();
 }
 
-
 QVariant SamplesQModel::data(const QModelIndex& index, int role) const
 {
-    const auto* item = itemForIndex(index);
-
-    if (role == Qt::ToolTipRole)
-        return item->description();
-
-    if (role == Qt::DisplayRole)
-        return item->name();
-
-    return {};
+    if (!index.isValid())
+        return {};
+    size_t row = index.row();
+    if (row >= set()->size())
+        return {};
+    const SampleItem* t = set()->at(row);
+
+    switch (role) {
+    case Qt::DisplayRole:
+        return t->name();
+    case Qt::ToolTipRole:
+        return t->description();
+    case Qt::BackgroundRole:
+        return row == set()->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
+    default:
+        return {};
+    }
 }
 
 const SampleItem* SamplesQModel::itemForIndex(const QModelIndex& index) const
-- 
GitLab


From cab600c788cbd37a0353686c7bd3e53c1490edb3 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 20:40:49 +0100
Subject: [PATCH 050/108] rm InstrumentsSet::instrumentItems

---
 GUI/Model/Device/InstrumentsSet.cpp       | 14 +++-----------
 GUI/Model/Device/InstrumentsSet.h         |  3 ---
 GUI/View/Data/DatafileEditor.cpp          |  4 ++--
 Tests/Unit/GUI/TestAutosaveController.cpp |  4 ++--
 Tests/Unit/GUI/TestProjectDocument.cpp    |  4 ++--
 5 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/GUI/Model/Device/InstrumentsSet.cpp b/GUI/Model/Device/InstrumentsSet.cpp
index 16128125441..2c0d6e2930e 100644
--- a/GUI/Model/Device/InstrumentsSet.cpp
+++ b/GUI/Model/Device/InstrumentsSet.cpp
@@ -74,14 +74,6 @@ void InstrumentsSet::readFrom(QXmlStreamReader* r)
     }
 }
 
-QVector<InstrumentItem*> InstrumentsSet::instrumentItems() const
-{
-    QVector<InstrumentItem*> output;
-    for (auto* t : *this)
-        output.append(t);
-    return output;
-}
-
 QStringList InstrumentsSet::instrumentNames() const
 {
     QStringList existingNames;
@@ -92,9 +84,9 @@ QStringList InstrumentsSet::instrumentNames() const
 
 InstrumentItem* InstrumentsSet::findInstrumentItemById(const QString& instrumentId) const
 {
-    for (auto* instrument : instrumentItems())
-        if (instrument->id() == instrumentId)
-            return instrument;
+    for (auto* t : *this)
+        if (t->id() == instrumentId)
+            return t;
     return nullptr;
 }
 
diff --git a/GUI/Model/Device/InstrumentsSet.h b/GUI/Model/Device/InstrumentsSet.h
index 03864531d0d..247b7ac76e8 100644
--- a/GUI/Model/Device/InstrumentsSet.h
+++ b/GUI/Model/Device/InstrumentsSet.h
@@ -17,7 +17,6 @@
 
 #include "Base/Types/VectorWC.h"
 #include <QObject>
-#include <QVector>
 #include <QXmlStreamWriter>
 
 class InstrumentItem;
@@ -31,8 +30,6 @@ public:
     void writeTo(QXmlStreamWriter* w) const;
     void readFrom(QXmlStreamReader* r);
 
-    QVector<InstrumentItem*> instrumentItems() const;
-
     InstrumentItem* findInstrumentItemById(const QString& instrumentId) const;
     bool instrumentExists(const QString& instrumentId) const;
 
diff --git a/GUI/View/Data/DatafileEditor.cpp b/GUI/View/Data/DatafileEditor.cpp
index bba896f35a0..38d5136571a 100644
--- a/GUI/View/Data/DatafileEditor.cpp
+++ b/GUI/View/Data/DatafileEditor.cpp
@@ -97,8 +97,8 @@ void DatafileEditor::updateInstrumentComboEntries()
 
     // fill the combo. Userdata contains instrument's uid
     m_instrument_combo->addItem("Undefined", ""); // undefined instrument
-    for (auto* instrumentItem : gDoc->instruments()->instrumentItems())
-        m_instrument_combo->addItem(instrumentItem->name(), instrumentItem->id());
+    for (auto* t : *gDoc->instruments())
+        m_instrument_combo->addItem(t->name(), t->id());
 
     updateInstrumentComboIndex();
 
diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index b68d4e2006c..8456cbdfc33 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -19,7 +19,7 @@ protected:
     // helper method to modify something in a model
     void modelsModifier(ProjectDocument& doc)
     {
-        auto* instrument = doc.instrumentsModifier()->instrumentItems().front();
+        auto* instrument = doc.instrumentsModifier()->front();
         doc.instrumentsModifier()->setName(instrument, QUuid::createUuid().toString());
     }
     const int m_save_wait = 3000;
@@ -125,7 +125,7 @@ TEST_F(TestAutosaveController, autosaveEnabled)
     DatafileItem* realData =
         UTest::GUI::createRealData2D("TestData", *gDoc->datafilesModifier(), 0.);
     DataItem* data_item = realData->dataItem();
-    auto frame = gDoc->instruments()->instrumentItems().front()->createFrame();
+    auto frame = gDoc->instruments()->front()->createFrame();
     Datafield df(frame.release());
     data_item->setDatafield(df);
     gDoc->clearModified();
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index f994c475717..9b41fd59f96 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -20,7 +20,7 @@ protected:
     //! helper method to modify something in a model
     void modelsModifier(ProjectDocument& doc)
     {
-        auto* instrument = doc.instrumentsModifier()->instrumentItems().front();
+        auto* instrument = doc.instrumentsModifier()->front();
         doc.instrumentsModifier()->setName(instrument, QUuid::createUuid().toString());
     }
 };
@@ -84,7 +84,7 @@ TEST_F(TestProjectDocument, projectDocumentWithData)
         UTest::GUI::createRealData2D("TestData", *gDoc->datafilesModifier(), 0.);
     ASSERT(realData);
     DataItem* data_item = realData->dataItem();
-    auto frame = gDoc->instruments()->instrumentItems().front()->createFrame();
+    auto frame = gDoc->instruments()->front()->createFrame();
     Datafield df(frame.release());
     data_item->setDatafield(df);
 
-- 
GitLab


From cdad680d31e7cce56bce078c306180593ed25347 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 20:48:16 +0100
Subject: [PATCH 051/108] rm InstrumentsSet::setName

---
 GUI/Model/Device/InstrumentsSet.cpp       |  9 ---------
 GUI/Model/Device/InstrumentsSet.h         |  3 ---
 Tests/Unit/GUI/TestAutosaveController.cpp |  2 +-
 Tests/Unit/GUI/TestInstrumentsSet.cpp     | 19 ++-----------------
 Tests/Unit/GUI/TestProjectDocument.cpp    |  2 +-
 5 files changed, 4 insertions(+), 31 deletions(-)

diff --git a/GUI/Model/Device/InstrumentsSet.cpp b/GUI/Model/Device/InstrumentsSet.cpp
index 2c0d6e2930e..f6326aba395 100644
--- a/GUI/Model/Device/InstrumentsSet.cpp
+++ b/GUI/Model/Device/InstrumentsSet.cpp
@@ -94,12 +94,3 @@ bool InstrumentsSet::instrumentExists(const QString& instrumentId) const
 {
     return findInstrumentItemById(instrumentId) != nullptr;
 }
-
-void InstrumentsSet::setName(InstrumentItem* instrument, const QString& name)
-{
-    if (instrument->name() != name) {
-        instrument->setName(name);
-        emit currentModified();
-        emit setChanged();
-    }
-}
diff --git a/GUI/Model/Device/InstrumentsSet.h b/GUI/Model/Device/InstrumentsSet.h
index 247b7ac76e8..229e905555c 100644
--- a/GUI/Model/Device/InstrumentsSet.h
+++ b/GUI/Model/Device/InstrumentsSet.h
@@ -35,9 +35,6 @@ public:
 
     QStringList instrumentNames() const;
 
-    //! Set an instrument's name and emit the respective signal.
-    void setName(InstrumentItem* instrument, const QString& name);
-
 signals:
     void setChanged() const;
     void currentModified() const;
diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index 8456cbdfc33..8ae97ca2651 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -20,7 +20,7 @@ protected:
     void modelsModifier(ProjectDocument& doc)
     {
         auto* instrument = doc.instrumentsModifier()->front();
-        doc.instrumentsModifier()->setName(instrument, QUuid::createUuid().toString());
+        instrument->setName(QUuid::createUuid().toString());
     }
     const int m_save_wait = 3000;
 };
diff --git a/Tests/Unit/GUI/TestInstrumentsSet.cpp b/Tests/Unit/GUI/TestInstrumentsSet.cpp
index 2f29e47e6a1..25cd091404a 100644
--- a/Tests/Unit/GUI/TestInstrumentsSet.cpp
+++ b/Tests/Unit/GUI/TestInstrumentsSet.cpp
@@ -45,28 +45,13 @@ TEST(TestInstrumentsSet, instrumentChanged)
     QSignalSpy spy(gDoc->instruments(), SIGNAL(currentModified()));
     EXPECT_TRUE(spy.isValid());
 
-    // change name of instrument 1
-    gDoc->instrumentsModifier()->setName(instrument1, "A");
-    EXPECT_EQ(spy.count(), 1);
-
     // change other properties, e.g. id
     instrument1->setId("xxxxx");
     emit gDoc->instruments()->currentModified();
-    EXPECT_EQ(spy.count(), 2);
-
-    // change name of instrument 2
-    gDoc->instrumentsModifier()->setName(instrument2, "B");
-    EXPECT_EQ(spy.count(), 3);
+    EXPECT_EQ(spy.count(), 1);
 
     // Add another instrument
     auto* instrument3 = new OffspecInstrumentItem;
     gDoc->instrumentsModifier()->push_back(instrument3);
-
-    // Change instrument2
-    gDoc->instrumentsModifier()->setName(instrument2, "BB");
-    EXPECT_EQ(spy.count(), 4);
-
-    // Change instrument3
-    gDoc->instrumentsModifier()->setName(instrument3, "C");
-    EXPECT_EQ(spy.count(), 5);
+    EXPECT_EQ(spy.count(), 2);
 }
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index 9b41fd59f96..f6ee1340bfa 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -21,7 +21,7 @@ protected:
     void modelsModifier(ProjectDocument& doc)
     {
         auto* instrument = doc.instrumentsModifier()->front();
-        doc.instrumentsModifier()->setName(instrument, QUuid::createUuid().toString());
+        instrument->setName(QUuid::createUuid().toString());
     }
 };
 
-- 
GitLab


From 0a14d3ec1b5256f054f347d125797bbf077a9974 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 21:21:06 +0100
Subject: [PATCH 052/108] rm test

---
 Tests/Unit/GUI/TestAutosaveController.cpp |  1 +
 Tests/Unit/GUI/TestInstrumentsSet.cpp     | 57 -----------------------
 Tests/Unit/GUI/TestProjectDocument.cpp    |  1 +
 3 files changed, 2 insertions(+), 57 deletions(-)
 delete mode 100644 Tests/Unit/GUI/TestInstrumentsSet.cpp

diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index 8ae97ca2651..74a9f47bc74 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -21,6 +21,7 @@ protected:
     {
         auto* instrument = doc.instrumentsModifier()->front();
         instrument->setName(QUuid::createUuid().toString());
+	emit gDoc->instruments()->currentModified();
     }
     const int m_save_wait = 3000;
 };
diff --git a/Tests/Unit/GUI/TestInstrumentsSet.cpp b/Tests/Unit/GUI/TestInstrumentsSet.cpp
deleted file mode 100644
index 25cd091404a..00000000000
--- a/Tests/Unit/GUI/TestInstrumentsSet.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "GUI/Model/Device/InstrumentItems.h"
-#include "GUI/Model/Device/InstrumentsSet.h"
-#include "GUI/Model/Project/ProjectDocument.h"
-#include "Tests/GTestWrapper/google_test.h"
-#include <QSignalSpy>
-
-Q_DECLARE_METATYPE(const InstrumentItem*)
-
-/* Disabled 18feb24: signal no longer emitted at InstrumentsSet level
-
-//! Checks whether instrumentAddedRemoved will be emitted as expected
-
-TEST(TestInstrumentsSet, instrumentAddedRemoved)
-{
-    gDoc = std::make_unique<ProjectDocument>();
-
-    QSignalSpy spy(gDoc->instruments(), SIGNAL(setChanged()));
-    EXPECT_TRUE(spy.isValid());
-
-    // populating instrument model
-    auto* p = new Scatter2DInstrumentItem;
-    gDoc->instrumentsModifier()->push_back(p);
-
-    // checking that a signal was emitted about the new instrument
-    EXPECT_EQ(spy.count(), 1);
-
-    // removing instrument
-    gDoc->instrumentsModifier()->delete_element(p);
-    EXPECT_EQ(spy.count(), 2);
-}
-*/
-
-//! Test whether instrumentChanged will be emitted as expected
-TEST(TestInstrumentsSet, instrumentChanged)
-{
-    qRegisterMetaType<const InstrumentItem*>();
-    gDoc = std::make_unique<ProjectDocument>();
-
-    // populating instrument model
-    auto* instrument1 = new Scatter2DInstrumentItem;
-    gDoc->instrumentsModifier()->push_back(instrument1);
-    auto* instrument2 = new SpecularInstrumentItem;
-    gDoc->instrumentsModifier()->push_back(instrument2);
-
-    QSignalSpy spy(gDoc->instruments(), SIGNAL(currentModified()));
-    EXPECT_TRUE(spy.isValid());
-
-    // change other properties, e.g. id
-    instrument1->setId("xxxxx");
-    emit gDoc->instruments()->currentModified();
-    EXPECT_EQ(spy.count(), 1);
-
-    // Add another instrument
-    auto* instrument3 = new OffspecInstrumentItem;
-    gDoc->instrumentsModifier()->push_back(instrument3);
-    EXPECT_EQ(spy.count(), 2);
-}
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index f6ee1340bfa..028eba4f9c2 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -22,6 +22,7 @@ protected:
     {
         auto* instrument = doc.instrumentsModifier()->front();
         instrument->setName(QUuid::createUuid().toString());
+	emit gDoc->instruments()->currentModified();
     }
 };
 
-- 
GitLab


From 4bb1460c3e576286d5f0d98063fdeba1737f4c93 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 21:37:03 +0100
Subject: [PATCH 053/108] format

---
 Tests/Unit/GUI/TestAutosaveController.cpp | 2 +-
 Tests/Unit/GUI/TestProjectDocument.cpp    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Tests/Unit/GUI/TestAutosaveController.cpp b/Tests/Unit/GUI/TestAutosaveController.cpp
index 74a9f47bc74..85a62e8e51e 100644
--- a/Tests/Unit/GUI/TestAutosaveController.cpp
+++ b/Tests/Unit/GUI/TestAutosaveController.cpp
@@ -21,7 +21,7 @@ protected:
     {
         auto* instrument = doc.instrumentsModifier()->front();
         instrument->setName(QUuid::createUuid().toString());
-	emit gDoc->instruments()->currentModified();
+        emit gDoc->instruments()->currentModified();
     }
     const int m_save_wait = 3000;
 };
diff --git a/Tests/Unit/GUI/TestProjectDocument.cpp b/Tests/Unit/GUI/TestProjectDocument.cpp
index 028eba4f9c2..8767fd43511 100644
--- a/Tests/Unit/GUI/TestProjectDocument.cpp
+++ b/Tests/Unit/GUI/TestProjectDocument.cpp
@@ -22,7 +22,7 @@ protected:
     {
         auto* instrument = doc.instrumentsModifier()->front();
         instrument->setName(QUuid::createUuid().toString());
-	emit gDoc->instruments()->currentModified();
+        emit gDoc->instruments()->currentModified();
     }
 };
 
-- 
GitLab


From b67a8e126655cccaf23740ef745252bc8fa5ef15 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 21:46:13 +0100
Subject: [PATCH 054/108] rm includes

---
 GUI/Model/Device/InstrumentsSet.cpp | 2 --
 GUI/Model/Sample/SamplesSet.cpp     | 9 ++++-----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/GUI/Model/Device/InstrumentsSet.cpp b/GUI/Model/Device/InstrumentsSet.cpp
index f6326aba395..7dfe0456733 100644
--- a/GUI/Model/Device/InstrumentsSet.cpp
+++ b/GUI/Model/Device/InstrumentsSet.cpp
@@ -13,10 +13,8 @@
 //  ************************************************************************************************
 
 #include "GUI/Model/Device/InstrumentsSet.h"
-#include "GUI/Model/Device/BackgroundItems.h"
 #include "GUI/Model/Device/InstrumentItems.h"
 #include "GUI/Model/Device/InstrumentsCatalog.h"
-#include "GUI/Support/Util/String.h"
 
 namespace {
 namespace Tag {
diff --git a/GUI/Model/Sample/SamplesSet.cpp b/GUI/Model/Sample/SamplesSet.cpp
index 7acd2db5769..49796667263 100644
--- a/GUI/Model/Sample/SamplesSet.cpp
+++ b/GUI/Model/Sample/SamplesSet.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "GUI/Model/Sample/SamplesSet.h"
-#include "GUI/Model/Sample/ItemWithMaterial.h"
 #include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Support/XML/Backup.h"
 #include "GUI/Support/XML/UtilXML.h"
@@ -31,8 +30,8 @@ const QString CurrentIndex("CurrentIndex");
 QStringList SamplesSet::sampleNames() const
 {
     QStringList existingNames;
-    for (const auto* item : *this)
-        existingNames << item->name();
+    for (const auto* t : *this)
+        existingNames << t->name();
     return existingNames;
 }
 
@@ -41,9 +40,9 @@ void SamplesSet::writeTo(QXmlStreamWriter* w) const
     XML::writeAttribute(w, XML::Attrib::version, uint(1));
 
     // samples
-    for (const auto* sample : *this) {
+    for (const auto* t : *this) {
         w->writeStartElement(Tag::Sample);
-        sample->writeTo(w);
+        t->writeTo(w);
         w->writeEndElement();
     }
 
-- 
GitLab


From 760d62bd92fd777f0144342c5f3f976c7b00bb99 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 21:56:51 +0100
Subject: [PATCH 055/108] rm SamplesQListView::setCurrentSample

---
 GUI/View/List/SamplesQListView.cpp | 7 +------
 GUI/View/List/SamplesQListView.h   | 1 -
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 2b89045a120..e873a0ad027 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -89,11 +89,6 @@ SamplesQListView::SamplesQListView()
     }
 }
 
-void SamplesQListView::setCurrentSample(SampleItem* sample)
-{
-    setCurrentIndex(m_model->indexForItem(sample));
-}
-
 SampleItem* SamplesQListView::currentSampleItem()
 {
     return m_model->itemForIndex(currentIndex());
@@ -161,7 +156,7 @@ void SamplesQListView::restoreSelection()
     QModelIndex currentIndex = m_model->index(selected, 0, QModelIndex());
     if (currentIndex.isValid()) {
         selectionModel()->select(currentIndex, QItemSelectionModel::ClearAndSelect);
-        setCurrentSample(gDoc->samples()->shared()[selected]);
+        gDoc->samplesModifier()->setCurrentIndex(selected);
     }
 }
 
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index adeba637267..fe95a2e33a9 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,7 +26,6 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView();
 
-    void setCurrentSample(SampleItem* sample);
     SampleItem* currentSampleItem();
 
     void restoreSelection();
-- 
GitLab


From a403f7df4f178c17f3bf97764942eafe6e304402 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 22 Feb 2024 21:59:39 +0100
Subject: [PATCH 056/108] rm SamplesQListView::restoreSelection

---
 GUI/View/List/SamplesQListView.cpp | 13 -------------
 GUI/View/List/SamplesQListView.h   |  2 --
 GUI/View/Views/SampleView.cpp      |  6 ------
 GUI/View/Views/SampleView.h        |  2 --
 4 files changed, 23 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index e873a0ad027..10a4686f7f2 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -147,19 +147,6 @@ void SamplesQListView::onCurrentChanged(const QModelIndex& index)
     emit currentSampleChanged(m_model->itemForIndex(index));
 }
 
-void SamplesQListView::restoreSelection()
-{
-    int selected = gDoc->samples()->currentIndex();
-    if (selected < 0 || selected >= m_model->rowCount())
-        selected = m_model->rowCount() - 1;
-
-    QModelIndex currentIndex = m_model->index(selected, 0, QModelIndex());
-    if (currentIndex.isValid()) {
-        selectionModel()->select(currentIndex, QItemSelectionModel::ClearAndSelect);
-        gDoc->samplesModifier()->setCurrentIndex(selected);
-    }
-}
-
 void SamplesQListView::removeSample(SampleItem* item)
 {
     m_model->removeSample(item);
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index fe95a2e33a9..921c5e1595d 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -28,8 +28,6 @@ public:
 
     SampleItem* currentSampleItem();
 
-    void restoreSelection();
-
     QAction* newSampleAction() { return m_new_sample_action; }
     QAction* importSampleAction() { return m_import_sample_action; }
     QAction* chooseFromLibraryAction() { return m_choose_from_library_action; }
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index eae840f2586..a5de949a066 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -191,9 +191,3 @@ void SampleView::onAboutToRemoveItem(Item3D* item)
             widget->resetScene();
     }
 }
-
-void SampleView::showEvent(QShowEvent*)
-{
-    if (!m_listing->currentSampleItem())
-        m_listing->restoreSelection();
-}
diff --git a/GUI/View/Views/SampleView.h b/GUI/View/Views/SampleView.h
index 966472146db..448feabda0f 100644
--- a/GUI/View/Views/SampleView.h
+++ b/GUI/View/Views/SampleView.h
@@ -29,8 +29,6 @@ public:
     ~SampleView();
 
 private:
-    void showEvent(QShowEvent*) override;
-
     //! Show the item in the real space view
     //!
     //! If the real space view is not visible at the moment, it will be shown.
-- 
GitLab


From 12d2c8f21ec6834aa8e78e8f2bf0f6faa05ac102 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 09:04:55 +0100
Subject: [PATCH 057/108] rm fct

---
 GUI/View/List/SamplesQListView.cpp | 5 -----
 GUI/View/List/SamplesQListView.h   | 2 --
 GUI/View/Views/SampleView.cpp      | 3 ++-
 3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 10a4686f7f2..b064f5b1bca 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -89,11 +89,6 @@ SamplesQListView::SamplesQListView()
     }
 }
 
-SampleItem* SamplesQListView::currentSampleItem()
-{
-    return m_model->itemForIndex(currentIndex());
-}
-
 QSize SamplesQListView::sizeHint() const
 {
     QSize s = QListView::sizeHint();
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index 921c5e1595d..fd931476b89 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,8 +26,6 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView();
 
-    SampleItem* currentSampleItem();
-
     QAction* newSampleAction() { return m_new_sample_action; }
     QAction* importSampleAction() { return m_import_sample_action; }
     QAction* chooseFromLibraryAction() { return m_choose_from_library_action; }
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index a5de949a066..b7ed441ea19 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -19,6 +19,7 @@
 #include "GUI/Model/Sample/LayerItem.h"
 #include "GUI/Model/Sample/ParticleLayoutItem.h"
 #include "GUI/Model/Sample/SampleItem.h"
+#include "GUI/Model/Sample/SamplesSet.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Layout/mainwindow_constants.h"
 #include "GUI/View/List/SamplesQListView.h"
@@ -160,7 +161,7 @@ void SampleView::onRequestViewInRealspace(Item3D* item)
     }
 
     // m_docks->setDockVisible(REALSPACEPANEL);
-    m_realspace_panel->widget()->setDisplayedItem(m_listing->currentSampleItem(), item);
+    m_realspace_panel->widget()->setDisplayedItem(gDoc->samplesModifier()->currentItem(), item);
 }
 
 void SampleView::onAboutToRemoveItem(Item3D* item)
-- 
GitLab


From 323bbb285675f116994b89de69cb7e6b811102ab Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 09:05:15 +0100
Subject: [PATCH 058/108] rm sizeHint

---
 GUI/View/List/SamplesQListView.cpp | 7 -------
 GUI/View/List/SamplesQListView.h   | 2 --
 2 files changed, 9 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index b064f5b1bca..267c00a3881 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -89,13 +89,6 @@ SamplesQListView::SamplesQListView()
     }
 }
 
-QSize SamplesQListView::sizeHint() const
-{
-    QSize s = QListView::sizeHint();
-    s.setWidth(std::max(300, s.width()));
-    return s;
-}
-
 void SamplesQListView::createNewSample()
 {
     const QModelIndex newIndex = m_model->createSample();
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index fd931476b89..faf8f577fa2 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -30,8 +30,6 @@ public:
     QAction* importSampleAction() { return m_import_sample_action; }
     QAction* chooseFromLibraryAction() { return m_choose_from_library_action; }
 
-    QSize sizeHint() const override;
-
 signals:
     void currentSampleChanged(SampleItem* current);
 
-- 
GitLab


From e95bcd2ae2d7ffea6bcc8243d726977b8460c268 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 09:34:30 +0100
Subject: [PATCH 059/108] .

---
 GUI/View/Widget/ItemViewOverlayButtons.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/GUI/View/Widget/ItemViewOverlayButtons.h b/GUI/View/Widget/ItemViewOverlayButtons.h
index 8488b3a9736..3fa8b710b23 100644
--- a/GUI/View/Widget/ItemViewOverlayButtons.h
+++ b/GUI/View/Widget/ItemViewOverlayButtons.h
@@ -22,8 +22,6 @@
 
 //! Supports action buttons in the single rows of a list view.
 //! Buttons may be permanent or only show up when hovered over.
-//!
-//! In feb24, this code was restricted from self-made views to list views.
 
 class ItemViewOverlayButtons : public QObject {
     Q_OBJECT
@@ -43,5 +41,4 @@ private:
     QAbstractItemView* m_view;
 };
 
-
 #endif // BORNAGAIN_GUI_VIEW_WIDGET_ITEMVIEWOVERLAYBUTTONS_H
-- 
GitLab


From b08cef83ab5fcec77489f3fce7eeccf5c599918b Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 09:58:50 +0100
Subject: [PATCH 060/108]  rm global actions from item context menu

---
 GUI/View/List/SamplesQListView.cpp         | 3 ---
 GUI/View/Widget/ItemViewOverlayButtons.cpp | 1 -
 2 files changed, 4 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 267c00a3881..bcf8da13234 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -183,8 +183,5 @@ void SamplesQListView::showContextMenu(const QPoint& pos)
         menu.addAction(createRemoveAction(&menu, sampleAtPoint));
         menu.addSeparator();
     }
-
-    menu.addAction(m_new_sample_action);
-    menu.addAction(m_choose_from_library_action);
     menu.exec(mapToGlobal(pos));
 }
diff --git a/GUI/View/Widget/ItemViewOverlayButtons.cpp b/GUI/View/Widget/ItemViewOverlayButtons.cpp
index c5fbec29c68..b73810d8e0a 100644
--- a/GUI/View/Widget/ItemViewOverlayButtons.cpp
+++ b/GUI/View/Widget/ItemViewOverlayButtons.cpp
@@ -135,7 +135,6 @@ void ItemViewOverlayButtons::install(QAbstractItemView* view, FnGetActions fnGet
 {
     auto* h = new ItemViewOverlayButtons(view);
     h->m_get_actions = fnGetActions;
-    h->m_view = view;
     view->installEventFilter(h);
     h->update();
 
-- 
GitLab


From 7efe48e959bf4c94550c532b8eb87741f636f557 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 10:03:36 +0100
Subject: [PATCH 061/108] rm overlay buttons

---
 GUI/View/Data/DatafilesSelector.cpp        |  30 ---
 GUI/View/Data/DatafilesSelector.h          |   2 -
 GUI/View/List/InstrumentsQListView.cpp     |   1 -
 GUI/View/List/SamplesQListView.cpp         |  15 --
 GUI/View/List/SamplesQListView.h           |   1 -
 GUI/View/Widget/ItemViewOverlayButtons.cpp | 216 ---------------------
 GUI/View/Widget/ItemViewOverlayButtons.h   |  44 -----
 7 files changed, 309 deletions(-)
 delete mode 100644 GUI/View/Widget/ItemViewOverlayButtons.cpp
 delete mode 100644 GUI/View/Widget/ItemViewOverlayButtons.h

diff --git a/GUI/View/Data/DatafilesSelector.cpp b/GUI/View/Data/DatafilesSelector.cpp
index 5e36e55922a..8dc6f0b9544 100644
--- a/GUI/View/Data/DatafilesSelector.cpp
+++ b/GUI/View/Data/DatafilesSelector.cpp
@@ -27,7 +27,6 @@
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Loader/Legacy1dDialog.h"
 #include "GUI/View/Manager/ProjectManager.h"
-#include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include "GUI/View/Widget/StyledToolbar.h"
 #include <QBoxLayout>
@@ -142,8 +141,6 @@ DatafilesSelector::DatafilesSelector(StackedDataFrames* data_frames)
 
     restoreSelection();
 
-    ItemViewOverlayButtons::install(
-        m_qview, [this](const QModelIndex& i, bool h) { return getOverlayActions(i, h); });
     m_qview->setItemDelegate(new ListItemDelegate(this));
 }
 
@@ -188,33 +185,6 @@ void DatafilesSelector::restoreSelection()
         m_data_frames->setStackedItem(currentDatafileItem()->dataItem());
 }
 
-QVector<QAction*> DatafilesSelector::getOverlayActions(const QModelIndex& index, bool asHover)
-{
-    if (m_qmodel->isHeadline(index))
-        return {};
-
-    // -- index belongs to item
-    if (!asHover)
-        return {};
-
-    const DatafileItem* item = m_qmodel->itemForIndex(index);
-    if (item == nullptr)
-        return {};
-
-    auto* removeAction = new QAction(this);
-    removeAction->setText("Remove");
-    removeAction->setIcon(QIcon(":/images/delete.svg"));
-    removeAction->setIconText("Remove");
-    removeAction->setToolTip("Remove this data");
-    connect(removeAction, &QAction::triggered, [this, item] {
-        int row = m_qmodel->indexForItem(item).row();
-        m_qmodel->removeDatafileItemAt(row);
-        gDoc->setModified();
-    });
-
-    return {removeAction};
-}
-
 void DatafilesSelector::onSelectionChanged()
 {
     updateActionEnabling();
diff --git a/GUI/View/Data/DatafilesSelector.h b/GUI/View/Data/DatafilesSelector.h
index 8ac99c0db7b..40072d9ee26 100644
--- a/GUI/View/Data/DatafilesSelector.h
+++ b/GUI/View/Data/DatafilesSelector.h
@@ -55,8 +55,6 @@ private:
     void importData2D();
     QModelIndex currentDatafileIndex() const;
 
-    QVector<QAction*> getOverlayActions(const QModelIndex& index, bool asHover);
-
     QAction* m_import1dData_action;
     QAction* m_import2dData_action;
     QAction* m_rename_data_action;
diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index d129035608f..fab1fbc2bd4 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -16,7 +16,6 @@
 #include "GUI/Model/Device/InstrumentsSet.h"
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/View/List/InstrumentsQModel.h"
-#include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 
 InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index bcf8da13234..81f9dac2783 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -20,7 +20,6 @@
 #include "GUI/Model/Sample/SamplesSet.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/SamplesQModel.h"
-#include "GUI/View/Widget/ItemViewOverlayButtons.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QAction>
 #include <QMenu>
@@ -40,8 +39,6 @@ SamplesQListView::SamplesQListView()
 
     setContextMenuPolicy(Qt::CustomContextMenu);
 
-    ItemViewOverlayButtons::install(
-        this, [this](const QModelIndex& i, bool h) { return getOverlayActions(i, h); });
     setItemDelegate(new ListItemDelegate(this));
 
     connect(selectionModel(), &QItemSelectionModel::currentChanged, this,
@@ -117,18 +114,6 @@ void SamplesQListView::importSampleFromPython()
 #endif
 }
 
-QVector<QAction*> SamplesQListView::getOverlayActions(const QModelIndex& index, bool asHover)
-{
-    if (!asHover)
-        return {};
-
-    auto* item = m_model->itemForIndex(index);
-    if (item == nullptr)
-        return {};
-
-    return {createRemoveAction(this, item)};
-}
-
 void SamplesQListView::onCurrentChanged(const QModelIndex& index)
 {
     gDoc->samplesModifier()->setCurrentIndex(index.row());
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index faf8f577fa2..a55b4bdf2f1 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -38,7 +38,6 @@ private:
     void createSampleFromLibrary(const QString& classname, const QString& title,
                                  const QString& description);
     void importSampleFromPython();
-    QVector<QAction*> getOverlayActions(const QModelIndex& index, bool asHover);
     void onCurrentChanged(const QModelIndex& index);
     void removeSample(SampleItem* item);
     void copySample(SampleItem* item);
diff --git a/GUI/View/Widget/ItemViewOverlayButtons.cpp b/GUI/View/Widget/ItemViewOverlayButtons.cpp
deleted file mode 100644
index b73810d8e0a..00000000000
--- a/GUI/View/Widget/ItemViewOverlayButtons.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit reflection and scattering
-//
-//! @file      GUI/View/Widget/ItemViewOverlayButtons.cpp
-//! @brief     Implements class ItemViewOverlayButtons.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2021
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#include "GUI/View/Widget/ItemViewOverlayButtons.h"
-#include <QApplication>
-#include <QBoxLayout>
-#include <QKeyEvent>
-#include <QMenu>
-#include <QToolButton>
-
-namespace {
-
-class ItemViewOverlayWidget : public QWidget {
-public:
-    ItemViewOverlayWidget(QAbstractItemView* view, const QModelIndex& index);
-
-    void setHover(bool b);
-    void create();
-    void hover(bool h);
-    void setHorizontalAlignment(Qt::Alignment a);
-
-protected:
-    void enterEvent(QEnterEvent* event) override;
-    void leaveEvent(QEvent* event) override;
-    void mouseDoubleClickEvent(QMouseEvent* event) override;
-
-private:
-    bool m_hover{false};
-    QAbstractItemView* m_view;
-    QModelIndex m_index;
-    Qt::Alignment m_horizontal_alignment;
-};
-
-
-ItemViewOverlayWidget::ItemViewOverlayWidget(QAbstractItemView* view, const QModelIndex& index)
-    : QWidget(view)
-    , m_view(view)
-    , m_index(index)
-    , m_horizontal_alignment(Qt::AlignRight)
-{
-    setMouseTracking(true);
-    setFocusPolicy(Qt::NoFocus); // do not receive keypress!
-}
-
-void ItemViewOverlayWidget::setHover(bool b)
-{
-    m_hover = b;
-}
-
-void ItemViewOverlayWidget::enterEvent(QEnterEvent*)
-{
-    hover(true);
-}
-
-void ItemViewOverlayWidget::leaveEvent(QEvent*)
-{
-    hover(false);
-}
-
-void ItemViewOverlayWidget::mouseDoubleClickEvent(QMouseEvent* ev)
-{
-    if (m_view->editTriggers().testFlag(QAbstractItemView::DoubleClicked)
-        && m_index.flags().testFlag(Qt::ItemIsEditable)) {
-        m_view->setIndexWidget(m_index, nullptr);
-        m_view->edit(m_index);
-        ev->accept();
-        return;
-    }
-    ev->ignore();
-}
-
-void ItemViewOverlayWidget::create()
-{
-    auto* h1 = new QHBoxLayout;
-    h1->setContentsMargins(0, 3, 5, 3);
-    h1->setAlignment(m_horizontal_alignment | Qt::AlignTop);
-    setLayout(h1);
-
-    for (auto* a : actions()) {
-        auto* btn = new QToolButton(this);
-        btn->setDefaultAction(a);
-        Qt::ToolButtonStyle btnStyle = (Qt::ToolButtonStyle)a->data().toInt();
-        btn->setToolButtonStyle(btnStyle);
-
-        const int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
-        btn->setIconSize(QSize(size, size));
-
-        if (a->menu() != nullptr)
-            btn->setPopupMode(QToolButton::InstantPopup);
-
-        h1->addWidget(btn);
-
-        if (m_hover)
-            btn->hide();
-    }
-}
-
-void ItemViewOverlayWidget::hover(bool h)
-{
-    if (!m_hover)
-        return;
-
-    if (h) {
-        if (actions().size() != findChildren<QToolButton*>().size())
-            create();
-        for (auto* w : findChildren<QToolButton*>())
-            w->show();
-    } else {
-        for (auto* w : findChildren<QToolButton*>())
-            w->hide();
-    }
-}
-
-void ItemViewOverlayWidget::setHorizontalAlignment(Qt::Alignment a)
-{
-    m_horizontal_alignment = a;
-}
-
-
-} // namespace
-
-
-void ItemViewOverlayButtons::install(QAbstractItemView* view, FnGetActions fnGetActions)
-{
-    auto* h = new ItemViewOverlayButtons(view);
-    h->m_get_actions = fnGetActions;
-    view->installEventFilter(h);
-    h->update();
-
-    connect(view->model(), &QAbstractItemModel::modelReset, h, &ItemViewOverlayButtons::update,
-            Qt::QueuedConnection);
-    connect(view->model(), &QAbstractItemModel::rowsInserted, h, &ItemViewOverlayButtons::update,
-            Qt::QueuedConnection); // Queued: important!
-    connect(view->model(), &QAbstractItemModel::rowsRemoved, h, &ItemViewOverlayButtons::update,
-            Qt::QueuedConnection); // Queued: important!
-}
-
-bool ItemViewOverlayButtons::eventFilter(QObject* obj, QEvent* event)
-{
-    // F2 would start the editing. Since OverlayWidgets are an editor already (indexWidget uses the
-    // editor internals), we remove the overlay at this place, so the view will properly open the
-    // editor
-    if (event->type() == QEvent::KeyPress) {
-        auto* keyEvent = dynamic_cast<QKeyEvent*>(event);
-        if (keyEvent->key() == Qt::Key_F2) {
-            QModelIndex ci = m_view->currentIndex();
-            if (ci.isValid() && ci.flags().testFlag(Qt::ItemIsEditable))
-                m_view->setIndexWidget(ci, nullptr);
-        }
-    }
-    return QObject::eventFilter(obj, event);
-}
-
-ItemViewOverlayButtons::ItemViewOverlayButtons(QObject* parent)
-    : QObject(parent)
-{
-}
-
-void ItemViewOverlayButtons::update()
-{
-    if (m_view->model() == nullptr)
-        return;
-    auto* m = m_view->model();
-    for (int row = 0; row < m->rowCount(); row++) {
-        const QModelIndex index = m->index(row, 0);
-        if (m_view->indexWidget(index) == nullptr)
-            installOverlay(index);
-        QPoint viewPortMousePos = m_view->mapFromGlobal(QCursor::pos());
-        if (m_view->indexAt(viewPortMousePos) == index)
-            if (auto* w = dynamic_cast<ItemViewOverlayWidget*>(m_view->indexWidget(index)))
-                w->hover(true);
-    }
-}
-
-void ItemViewOverlayButtons::installOverlay(const QModelIndex& index)
-{
-    const auto permanentActions = m_get_actions(index, false);
-    const auto hoverActions = m_get_actions(index, true);
-
-    if (permanentActions.isEmpty() && hoverActions.isEmpty())
-        return;
-
-    auto* w = new ItemViewOverlayWidget(m_view, index);
-
-    const auto setAlignment = [&](const QVector<QAction*> actions) {
-        w->setHorizontalAlignment(Qt::AlignRight);
-        if (actions.first() == nullptr && actions.last() == nullptr)
-            w->setHorizontalAlignment(Qt::AlignCenter);
-        else if (actions.first() != nullptr && actions.last() == nullptr)
-            w->setHorizontalAlignment(Qt::AlignLeft);
-    };
-
-    if (!permanentActions.isEmpty()) {
-        setAlignment(permanentActions);
-        w->addActions(permanentActions);
-        w->setHover(false);
-    } else if (!hoverActions.isEmpty()) {
-        setAlignment(hoverActions);
-        w->addActions(hoverActions);
-        w->setHover(true);
-    }
-
-    w->create();
-    m_view->setIndexWidget(index, w);
-}
diff --git a/GUI/View/Widget/ItemViewOverlayButtons.h b/GUI/View/Widget/ItemViewOverlayButtons.h
deleted file mode 100644
index 3fa8b710b23..00000000000
--- a/GUI/View/Widget/ItemViewOverlayButtons.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit reflection and scattering
-//
-//! @file      GUI/View/Widget/ItemViewOverlayButtons.h
-//! @brief     Defines class ItemViewOverlayButtons.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2021
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#ifndef BORNAGAIN_GUI_VIEW_WIDGET_ITEMVIEWOVERLAYBUTTONS_H
-#define BORNAGAIN_GUI_VIEW_WIDGET_ITEMVIEWOVERLAYBUTTONS_H
-
-#include <QAbstractItemView>
-#include <QAction>
-#include <QObject>
-#include <functional>
-
-//! Supports action buttons in the single rows of a list view.
-//! Buttons may be permanent or only show up when hovered over.
-
-class ItemViewOverlayButtons : public QObject {
-    Q_OBJECT
-public:
-    using FnGetActions = std::function<QVector<QAction*>(const QModelIndex&, bool)>;
-
-    static void install(QAbstractItemView* view, FnGetActions fnGetActions);
-
-private:
-    bool eventFilter(QObject* obj, QEvent* event) override;
-
-    ItemViewOverlayButtons(QObject* parent);
-    void update();
-    void installOverlay(const QModelIndex& index);
-
-    FnGetActions m_get_actions;
-    QAbstractItemView* m_view;
-};
-
-#endif // BORNAGAIN_GUI_VIEW_WIDGET_ITEMVIEWOVERLAYBUTTONS_H
-- 
GitLab


From 2af9b2b299cb82f366204e89c30ce3c2a29569b5 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 10:32:44 +0100
Subject: [PATCH 062/108] mv action to SampleView

---
 GUI/View/List/SamplesQListView.cpp |  6 ------
 GUI/View/List/SamplesQListView.h   | 11 +++++------
 GUI/View/Sample/SampleEditor.h     |  1 -
 GUI/View/Views/SampleView.cpp      | 14 ++++++++++----
 4 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 81f9dac2783..3ea595ed862 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -27,7 +27,6 @@
 
 SamplesQListView::SamplesQListView()
     : m_model(new SamplesQModel(this))
-    , m_new_sample_action(new QAction(this))
     , m_import_sample_action(new QAction(this))
     , m_choose_from_library_action(new QAction(this))
 {
@@ -46,11 +45,6 @@ SamplesQListView::SamplesQListView()
 
     connect(this, &QWidget::customContextMenuRequested, this, &SamplesQListView::showContextMenu);
 
-    m_new_sample_action->setText("Create new sample");
-    m_new_sample_action->setIcon(QIcon(":/images/shape-square-plus.svg"));
-    m_new_sample_action->setIconText("New");
-    m_new_sample_action->setToolTip("Create new sample");
-    connect(m_new_sample_action, &QAction::triggered, this, &SamplesQListView::createNewSample);
 
     m_import_sample_action->setText("Import sample from python script (experimental)");
     m_import_sample_action->setIcon(QIcon(":/images/import.svg"));
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index a55b4bdf2f1..e916d19d8e2 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,14 +26,9 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView();
 
-    QAction* newSampleAction() { return m_new_sample_action; }
     QAction* importSampleAction() { return m_import_sample_action; }
     QAction* chooseFromLibraryAction() { return m_choose_from_library_action; }
 
-signals:
-    void currentSampleChanged(SampleItem* current);
-
-private:
     void createNewSample();
     void createSampleFromLibrary(const QString& classname, const QString& title,
                                  const QString& description);
@@ -42,13 +37,17 @@ private:
     void removeSample(SampleItem* item);
     void copySample(SampleItem* item);
 
+signals:
+    void currentSampleChanged(SampleItem* current);
+
+private:
+
     QAction* createRemoveAction(QObject* parent, SampleItem* item);
     QAction* createCopyAction(QObject* parent, SampleItem* item);
 
     void showContextMenu(const QPoint& pos);
 
     SamplesQModel* m_model;
-    QAction* m_new_sample_action;
     QAction* m_import_sample_action;
     QAction* m_choose_from_library_action;
 };
diff --git a/GUI/View/Sample/SampleEditor.h b/GUI/View/Sample/SampleEditor.h
index 12aef28f36d..e4786ab810a 100644
--- a/GUI/View/Sample/SampleEditor.h
+++ b/GUI/View/Sample/SampleEditor.h
@@ -34,7 +34,6 @@ public:
 
 signals:
     void requestViewInRealspace(Item3D* itemToShow);
-    void requestCreateNewSample();
     void aboutToRemoveItem(Item3D* item);
     void modified();
 
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index b7ed441ea19..f60614b3422 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -90,9 +90,18 @@ SampleView::SampleView()
         m_realspace_panel->setMaximumHeight(QWIDGETSIZE_MAX);
     });
 
+    //... Toolbar actions
+
+    auto* new_sample_action = new QAction("New", this);
+    new_sample_action->setIcon(QIcon(":/images/shape-square-plus.svg"));
+    new_sample_action->setToolTip("Create new sample");
+    toolbar->addAction(new_sample_action);
+
+    connect(new_sample_action, &QAction::triggered,
+	    m_listing, &SamplesQListView::createNewSample);
+
     //... Finish
 
-    toolbar->addAction(m_listing->newSampleAction());
 #ifdef BORNAGAIN_PYTHON
     toolbar->addAction(m_listing->importSampleAction());
 #endif
@@ -117,9 +126,6 @@ SampleView::SampleView()
 
     connect(editor, &SampleEditor::aboutToRemoveItem, this, &SampleView::onAboutToRemoveItem);
 
-    connect(editor, &SampleEditor::requestCreateNewSample, m_listing->newSampleAction(),
-            &QAction::trigger, Qt::QueuedConnection);
-
     connect(editor, &SampleEditor::modified, m_realspace_panel->widget(),
             &RealspaceWidget::updateScene);
 
-- 
GitLab


From d7100fa64f0898a3e1470bb272c882f65d4f83c6 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 10:36:34 +0100
Subject: [PATCH 063/108] + 1

---
 GUI/View/List/SamplesQListView.cpp | 16 ----------------
 GUI/View/List/SamplesQListView.h   |  2 --
 GUI/View/Views/SampleView.cpp      | 14 +++++++++++---
 3 files changed, 11 insertions(+), 21 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 3ea595ed862..1ca1fb7352b 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -27,7 +27,6 @@
 
 SamplesQListView::SamplesQListView()
     : m_model(new SamplesQModel(this))
-    , m_import_sample_action(new QAction(this))
     , m_choose_from_library_action(new QAction(this))
 {
     setMaximumWidth(200);
@@ -45,21 +44,6 @@ SamplesQListView::SamplesQListView()
 
     connect(this, &QWidget::customContextMenuRequested, this, &SamplesQListView::showContextMenu);
 
-
-    m_import_sample_action->setText("Import sample from python script (experimental)");
-    m_import_sample_action->setIcon(QIcon(":/images/import.svg"));
-    m_import_sample_action->setIconText("Import");
-    m_import_sample_action->setToolTip(
-        "Import sample from Python script.\n The script should contain a function "
-        "returning a valid multi-layer.");
-
-#ifdef BORNAGAIN_PYTHON
-    connect(m_import_sample_action, &QAction::triggered, this,
-            &SamplesQListView::importSampleFromPython);
-#else
-    m_import_sample_action->setVisible(false);
-#endif
-
     m_choose_from_library_action->setText("Choose from sample examples");
     m_choose_from_library_action->setIcon(QIcon(":/images/library.svg"));
     m_choose_from_library_action->setIconText("Examples");
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index e916d19d8e2..8ad5c179b2f 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,7 +26,6 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView();
 
-    QAction* importSampleAction() { return m_import_sample_action; }
     QAction* chooseFromLibraryAction() { return m_choose_from_library_action; }
 
     void createNewSample();
@@ -41,7 +40,6 @@ signals:
     void currentSampleChanged(SampleItem* current);
 
 private:
-
     QAction* createRemoveAction(QObject* parent, SampleItem* item);
     QAction* createCopyAction(QObject* parent, SampleItem* item);
 
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index f60614b3422..dd5d3253061 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -100,11 +100,19 @@ SampleView::SampleView()
     connect(new_sample_action, &QAction::triggered,
 	    m_listing, &SamplesQListView::createNewSample);
 
-    //... Finish
-
 #ifdef BORNAGAIN_PYTHON
-    toolbar->addAction(m_listing->importSampleAction());
+    auto* import_sample_action = new QAction("Import", this);
+    import_sample_action->setIcon(QIcon(":/images/import.svg"));
+    import_sample_action->setToolTip(
+        "Import sample from a Python script that contains a function that returns a multi-layer");
+    toolbar->addAction(import_sample_action);
+
+    connect(import_sample_action, &QAction::triggered, m_listing,
+            &SamplesQListView::importSampleFromPython);
 #endif
+
+    //... Finish
+
     toolbar->addAction(m_listing->chooseFromLibraryAction());
     if (auto* btn = dynamic_cast<QToolButton*>(
             toolbar->widgetForAction(m_listing->chooseFromLibraryAction())))
-- 
GitLab


From 0e6b6c39fd5bd087b19b9898b4305a82dcf9a656 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 10:49:28 +0100
Subject: [PATCH 064/108] rm remaining action to toolbar

---
 GUI/View/List/SamplesQListView.cpp | 20 --------------------
 GUI/View/List/SamplesQListView.h   |  5 -----
 GUI/View/Views/SampleView.cpp      | 25 +++++++++++++++++++++----
 3 files changed, 21 insertions(+), 29 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 1ca1fb7352b..6cbf2d8fd20 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -14,7 +14,6 @@
 
 #include "GUI/View/List/SamplesQListView.h"
 #include "Base/Util/SysUtil.h"
-#include "GUI/Model/FromCore/GUIExamplesFactory.h"
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Model/Sample/SamplesSet.h"
@@ -27,7 +26,6 @@
 
 SamplesQListView::SamplesQListView()
     : m_model(new SamplesQModel(this))
-    , m_choose_from_library_action(new QAction(this))
 {
     setMaximumWidth(200);
     setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
@@ -44,24 +42,6 @@ SamplesQListView::SamplesQListView()
 
     connect(this, &QWidget::customContextMenuRequested, this, &SamplesQListView::showContextMenu);
 
-    m_choose_from_library_action->setText("Choose from sample examples");
-    m_choose_from_library_action->setIcon(QIcon(":/images/library.svg"));
-    m_choose_from_library_action->setIconText("Examples");
-    m_choose_from_library_action->setToolTip("Choose from sample examples");
-
-    auto* menu = new QMenu(this);
-    m_choose_from_library_action->setMenu(menu);
-
-    for (const auto& exampleName : GUI::ExamplesFactory::exampleNames()) {
-        QString title, description;
-        std::tie(title, description) = GUI::ExamplesFactory::exampleInfo(exampleName);
-        auto icon = QIcon(":/images/sample_layers2.png");
-        auto* action = menu->addAction(icon, title);
-        action->setToolTip(description);
-        connect(action, &QAction::triggered, [this, exampleName, title, description] {
-            createSampleFromLibrary(exampleName, title, description);
-        });
-    }
 }
 
 void SamplesQListView::createNewSample()
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index 8ad5c179b2f..61beb0196e8 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,8 +26,6 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView();
 
-    QAction* chooseFromLibraryAction() { return m_choose_from_library_action; }
-
     void createNewSample();
     void createSampleFromLibrary(const QString& classname, const QString& title,
                                  const QString& description);
@@ -35,7 +33,6 @@ public:
     void onCurrentChanged(const QModelIndex& index);
     void removeSample(SampleItem* item);
     void copySample(SampleItem* item);
-
 signals:
     void currentSampleChanged(SampleItem* current);
 
@@ -46,8 +43,6 @@ private:
     void showContextMenu(const QPoint& pos);
 
     SamplesQModel* m_model;
-    QAction* m_import_sample_action;
-    QAction* m_choose_from_library_action;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_SAMPLESQLISTVIEW_H
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index dd5d3253061..b04d4431f15 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -14,6 +14,7 @@
 
 #include "GUI/View/Views/SampleView.h"
 #include "Base/Util/Vec.h"
+#include "GUI/Model/FromCore/GUIExamplesFactory.h"
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/Model/Sample/ItemWithParticles.h"
 #include "GUI/Model/Sample/LayerItem.h"
@@ -31,6 +32,7 @@
 #include <QBoxLayout>
 #include <QCheckBox>
 #include <QDockWidget>
+#include <QMenu>
 #include <QMessageBox>
 #include <QSettings>
 #include <QSplitter>
@@ -111,12 +113,27 @@ SampleView::SampleView()
             &SamplesQListView::importSampleFromPython);
 #endif
 
-    //... Finish
-
-    toolbar->addAction(m_listing->chooseFromLibraryAction());
+    auto* choose_from_library_action = new QAction("Examples", this);
+    toolbar->addAction(choose_from_library_action);
     if (auto* btn = dynamic_cast<QToolButton*>(
-            toolbar->widgetForAction(m_listing->chooseFromLibraryAction())))
+            toolbar->widgetForAction(choose_from_library_action)))
         btn->setPopupMode(QToolButton::InstantPopup);
+    choose_from_library_action->setIcon(QIcon(":/images/library.svg"));
+    choose_from_library_action->setToolTip("Choose from sample examples");
+    auto* import_menu = new QMenu(this);
+    choose_from_library_action->setMenu(import_menu);
+    for (const auto& exampleName : GUI::ExamplesFactory::exampleNames()) {
+        QString title, description;
+        std::tie(title, description) = GUI::ExamplesFactory::exampleInfo(exampleName);
+        auto icon = QIcon(":/images/sample_layers2.png");
+        auto* action = import_menu->addAction(icon, title);
+        action->setToolTip(description);
+        connect(action, &QAction::triggered, [this, exampleName, title, description] {
+            m_listing->createSampleFromLibrary(exampleName, title, description);
+        });
+    }
+
+    //... Finish
 
     connect(m_listing, &SamplesQListView::currentSampleChanged, editor,
             &SampleEditor::setCurrentSample);
-- 
GitLab


From 45534f8592eaa37a67601e008543f20be9d7648b Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 11:10:29 +0100
Subject: [PATCH 065/108] format

---
 GUI/View/List/SamplesQListView.cpp | 1 -
 GUI/View/Views/SampleView.cpp      | 7 +++----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 6cbf2d8fd20..f24186e7537 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -41,7 +41,6 @@ SamplesQListView::SamplesQListView()
             &SamplesQListView::onCurrentChanged);
 
     connect(this, &QWidget::customContextMenuRequested, this, &SamplesQListView::showContextMenu);
-
 }
 
 void SamplesQListView::createNewSample()
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index b04d4431f15..19d73c9fa48 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -99,8 +99,7 @@ SampleView::SampleView()
     new_sample_action->setToolTip("Create new sample");
     toolbar->addAction(new_sample_action);
 
-    connect(new_sample_action, &QAction::triggered,
-	    m_listing, &SamplesQListView::createNewSample);
+    connect(new_sample_action, &QAction::triggered, m_listing, &SamplesQListView::createNewSample);
 
 #ifdef BORNAGAIN_PYTHON
     auto* import_sample_action = new QAction("Import", this);
@@ -115,8 +114,8 @@ SampleView::SampleView()
 
     auto* choose_from_library_action = new QAction("Examples", this);
     toolbar->addAction(choose_from_library_action);
-    if (auto* btn = dynamic_cast<QToolButton*>(
-            toolbar->widgetForAction(choose_from_library_action)))
+    if (auto* btn =
+            dynamic_cast<QToolButton*>(toolbar->widgetForAction(choose_from_library_action)))
         btn->setPopupMode(QToolButton::InstantPopup);
     choose_from_library_action->setIcon(QIcon(":/images/library.svg"));
     choose_from_library_action->setToolTip("Choose from sample examples");
-- 
GitLab


From c1dd0e3725b53ca90c50d6103d7ded3d29a51c97 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 11:13:22 +0100
Subject: [PATCH 066/108] merge statements

---
 GUI/View/List/SamplesQListView.cpp | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index f24186e7537..d5970f22b1a 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -91,10 +91,8 @@ void SamplesQListView::copySample(SampleItem* item)
 
 QAction* SamplesQListView::createRemoveAction(QObject* parent, SampleItem* item)
 {
-    auto* removeAction = new QAction(parent);
-    removeAction->setText("Remove");
+    auto* removeAction = new QAction("Remove", parent);
     removeAction->setIcon(QIcon(":/images/delete.svg"));
-    removeAction->setIconText("Remove");
     removeAction->setToolTip("Remove this sample");
     connect(removeAction, &QAction::triggered, [this, item] { removeSample(item); });
 
@@ -103,10 +101,8 @@ QAction* SamplesQListView::createRemoveAction(QObject* parent, SampleItem* item)
 
 QAction* SamplesQListView::createCopyAction(QObject* parent, SampleItem* item)
 {
-    auto* copyAction = new QAction(parent);
-    copyAction->setText("Clone");
+    auto* copyAction = new QAction("Clone", parent);
     copyAction->setIcon(QIcon(":/images/content-copy.svg"));
-    copyAction->setIconText("Clone");
     copyAction->setToolTip("Clone this sample");
     connect(copyAction, &QAction::triggered, [this, item] { copySample(item); });
 
-- 
GitLab


From 2c18ab313cf4b032ae9b58eb0ccc8745d29f9c6c Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 12:36:34 +0100
Subject: [PATCH 067/108] + ActionFactory::createRemoveAction etc

---
 GUI/View/Data/DatafilesSelector.cpp        |  6 ++---
 GUI/View/Job/JobsListing.cpp               |  5 ++---
 GUI/View/List/SamplesQListView.cpp         |  9 +++-----
 GUI/View/Material/MaterialEditorDialog.cpp |  5 ++---
 GUI/View/Setup/FrameActions.cpp            | 26 ++++++++++++++++------
 GUI/View/Setup/FrameActions.h              |  8 +++++++
 6 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/GUI/View/Data/DatafilesSelector.cpp b/GUI/View/Data/DatafilesSelector.cpp
index 8dc6f0b9544..cd678ed14ca 100644
--- a/GUI/View/Data/DatafilesSelector.cpp
+++ b/GUI/View/Data/DatafilesSelector.cpp
@@ -27,6 +27,7 @@
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Loader/Legacy1dDialog.h"
 #include "GUI/View/Manager/ProjectManager.h"
+#include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include "GUI/View/Widget/StyledToolbar.h"
 #include <QBoxLayout>
@@ -107,10 +108,7 @@ DatafilesSelector::DatafilesSelector(StackedDataFrames* data_frames)
     m_rename_data_action->setToolTip("Rename data");
     connect(m_rename_data_action, &QAction::triggered, this, &DatafilesSelector::renameCurrentItem);
 
-    m_remove_data_action->setText("Remove");
-    m_remove_data_action->setIcon(QIcon(":/images/delete.svg"));
-    m_remove_data_action->setIconText("Remove");
-    m_remove_data_action->setToolTip("Remove selected data");
+    m_remove_data_action = ActionFactory::createRemoveAction("data file");
     connect(m_remove_data_action, &QAction::triggered, this, &DatafilesSelector::removeCurrentItem);
 
     // m_qview->setAttribute(Qt::WA_MacShowFocusRect, false); // TODO/Mac: needed?
diff --git a/GUI/View/Job/JobsListing.cpp b/GUI/View/Job/JobsListing.cpp
index 81d2d2a697b..5733cfbc78a 100644
--- a/GUI/View/Job/JobsListing.cpp
+++ b/GUI/View/Job/JobsListing.cpp
@@ -21,6 +21,7 @@
 #include "GUI/Support/Data/JobStatus.h"
 #include "GUI/View/Job/JobProgressDelegate.h"
 #include "GUI/View/Job/JobsQModel.h"
+#include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/StyledToolbar.h"
 #include <QVBoxLayout>
 
@@ -65,9 +66,7 @@ JobsListing::JobsListing(QWidget* parent, Qt::WindowFlags f)
     connect(m_cancel_action, &QAction::triggered, this, &JobsListing::onCancel);
     addAction(m_cancel_action);
 
-    m_remove_action = new QAction("Remove", this);
-    m_remove_action->setIcon(QIcon(":/images/delete.svg"));
-    m_remove_action->setToolTip("Remove currently selected jobs");
+    m_remove_action = ActionFactory::createRemoveAction("job");
     connect(m_remove_action, &QAction::triggered, this, &JobsListing::onRemove);
     addAction(m_remove_action);
 
diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index d5970f22b1a..1f8b5f8e74f 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -19,6 +19,7 @@
 #include "GUI/Model/Sample/SamplesSet.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/SamplesQModel.h"
+#include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QAction>
 #include <QMenu>
@@ -91,9 +92,7 @@ void SamplesQListView::copySample(SampleItem* item)
 
 QAction* SamplesQListView::createRemoveAction(QObject* parent, SampleItem* item)
 {
-    auto* removeAction = new QAction("Remove", parent);
-    removeAction->setIcon(QIcon(":/images/delete.svg"));
-    removeAction->setToolTip("Remove this sample");
+    QAction* removeAction = ActionFactory::createRemoveAction("sample", parent);
     connect(removeAction, &QAction::triggered, [this, item] { removeSample(item); });
 
     return removeAction;
@@ -101,9 +100,7 @@ QAction* SamplesQListView::createRemoveAction(QObject* parent, SampleItem* item)
 
 QAction* SamplesQListView::createCopyAction(QObject* parent, SampleItem* item)
 {
-    auto* copyAction = new QAction("Clone", parent);
-    copyAction->setIcon(QIcon(":/images/content-copy.svg"));
-    copyAction->setToolTip("Clone this sample");
+    auto* copyAction = ActionFactory::createCopyAction("sample", parent);
     connect(copyAction, &QAction::triggered, [this, item] { copySample(item); });
 
     return copyAction;
diff --git a/GUI/View/Material/MaterialEditorDialog.cpp b/GUI/View/Material/MaterialEditorDialog.cpp
index 7998702279c..6a67fcaa214 100644
--- a/GUI/View/Material/MaterialEditorDialog.cpp
+++ b/GUI/View/Material/MaterialEditorDialog.cpp
@@ -21,6 +21,7 @@
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Material/MaterialsQModel.h"
 #include "GUI/View/Numeric/DoubleSpinBox.h"
+#include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/StyledToolbar.h"
 #include <QAction>
 #include <QColorDialog>
@@ -213,9 +214,7 @@ MaterialEditorDialog::MaterialEditorDialog(SampleItem* sample, const QString& id
     addSldMaterialAction->setToolTip("Add new material");
     connect(addSldMaterialAction, &QAction::triggered, this, &MaterialEditorDialog::addSldMaterial);
 
-    m_remove_material_action = new QAction("Remove");
-    m_remove_material_action->setIcon(QIcon(":/images/delete.svg"));
-    m_remove_material_action->setToolTip("Remove selected material");
+    m_remove_material_action = ActionFactory::createRemoveAction("material");
     connect(m_remove_material_action, &QAction::triggered, this,
             &MaterialEditorDialog::removeCurrentMaterial);
 
diff --git a/GUI/View/Setup/FrameActions.cpp b/GUI/View/Setup/FrameActions.cpp
index 6b71a1ce6bc..a08225d2ab7 100644
--- a/GUI/View/Setup/FrameActions.cpp
+++ b/GUI/View/Setup/FrameActions.cpp
@@ -14,6 +14,23 @@
 
 #include "GUI/View/Setup/FrameActions.h"
 
+QAction* ActionFactory::createCopyAction(const QString& type, QObject* parent)
+{
+    auto* result = new QAction("Copy", parent);
+    result->setIcon(QIcon(":/images/content-copy.svg"));
+    result->setToolTip("Clone current " + type);
+    return result;
+}
+
+QAction* ActionFactory::createRemoveAction(const QString& type, QObject* parent)
+{
+    auto* result = new QAction("Remove", parent);
+    result->setIcon(QIcon(":/images/delete.svg"));
+    result->setToolTip("Remove current " + type);
+    return result;
+}
+
+
 FrameActions* gActions; //<! Global pointer to single instance.
 
 FrameActions::FrameActions()
@@ -75,13 +92,8 @@ FrameActions::FrameActions()
     new_depthprobe_instrument->setIcon(QIcon(":/images/shape-square-plus.svg"));
     new_depthprobe_instrument->setToolTip("Add new depth probe instrument with default settings");
 
-    remove_instrument = new QAction("Remove");
-    remove_instrument->setIcon(QIcon(":/images/delete.svg"));
-    remove_instrument->setToolTip("Remove selected instrument");
-
-    copy_instrument = new QAction("Copy");
-    copy_instrument->setIcon(QIcon(":/images/content-copy.svg"));
-    copy_instrument->setToolTip("Make a copy of the selected instrument");
+    remove_instrument = ActionFactory::createRemoveAction("instrument");
+    copy_instrument = ActionFactory::createCopyAction("instrument");
 
     store_in_library_instrument = new QAction("Store in library");
     store_in_library_instrument->setIcon(QIcon(":/images/library.svg"));
diff --git a/GUI/View/Setup/FrameActions.h b/GUI/View/Setup/FrameActions.h
index e3f7f90579a..e2cf29951fb 100644
--- a/GUI/View/Setup/FrameActions.h
+++ b/GUI/View/Setup/FrameActions.h
@@ -16,6 +16,14 @@
 #define BORNAGAIN_GUI_VIEW_SETUP_FRAMEACTIONS_H
 
 #include <QAction>
+#include <QString>
+
+namespace ActionFactory {
+
+QAction* createCopyAction(const QString& type, QObject* parent = nullptr);
+QAction* createRemoveAction(const QString& type, QObject* parent = nullptr);
+
+} // namespace ActionFactory
 
 //! Actions for use in GUI top-level frames. Accessible through global gActions.
 
-- 
GitLab


From 3af0d8db8388bca329b996290a00a12c1ad034a5 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 12:55:03 +0100
Subject: [PATCH 068/108] rm include

---
 GUI/View/List/SamplesQListView.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 1f8b5f8e74f..78a83ba5637 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -23,7 +23,6 @@
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QAction>
 #include <QMenu>
-#include <QPainter>
 
 SamplesQListView::SamplesQListView()
     : m_model(new SamplesQModel(this))
-- 
GitLab


From 6df2abd9906d2293fe17746f85cc3cda6e242efa Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 13:43:57 +0100
Subject: [PATCH 069/108] ListItemDelegate + comment on Qt bug

---
 GUI/View/Widget/ListItemDelegate.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/GUI/View/Widget/ListItemDelegate.h b/GUI/View/Widget/ListItemDelegate.h
index c80e68e1517..b468dec3cc4 100644
--- a/GUI/View/Widget/ListItemDelegate.h
+++ b/GUI/View/Widget/ListItemDelegate.h
@@ -18,6 +18,13 @@
 #include <QStyledItemDelegate>
 
 //! Styling for items in list.
+//!
+//! We need this not least because a long-standing bug in Qt prevents us from
+//! using the style sheet to fine-tune the item layout.
+//! Specifically, in a style sheet stance like QAbstractItemView::item,
+//! the padding-left property is ignored unless there is also a border property.
+//! However, as soon as there is a border, the style sheet takes control over colors
+//! so that the BackgroundRole in the model's data() function is ignored.
 
 class ListItemDelegate : public QStyledItemDelegate {
     Q_OBJECT
-- 
GitLab


From e6615571dc4c763a66a1a15e672fac397876c461 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 14:06:37 +0100
Subject: [PATCH 070/108] link to bug report

---
 GUI/View/Widget/ListItemDelegate.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/GUI/View/Widget/ListItemDelegate.h b/GUI/View/Widget/ListItemDelegate.h
index b468dec3cc4..644e49458d2 100644
--- a/GUI/View/Widget/ListItemDelegate.h
+++ b/GUI/View/Widget/ListItemDelegate.h
@@ -19,12 +19,14 @@
 
 //! Styling for items in list.
 //!
-//! We need this not least because a long-standing bug in Qt prevents us from
+//! We need this not least because a long-standing bug [1] in Qt prevents us from
 //! using the style sheet to fine-tune the item layout.
 //! Specifically, in a style sheet stance like QAbstractItemView::item,
 //! the padding-left property is ignored unless there is also a border property.
 //! However, as soon as there is a border, the style sheet takes control over colors
 //! so that the BackgroundRole in the model's data() function is ignored.
+//!
+//! [1] reported anew as https://bugreports.qt.io/browse/QTBUG-122698
 
 class ListItemDelegate : public QStyledItemDelegate {
     Q_OBJECT
-- 
GitLab


From 6802c0d2c37ee6b80e70f54d510c2d877d5d1e6b Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:11:53 +0100
Subject: [PATCH 071/108] rm context menu from samples list

---
 GUI/View/List/SamplesQListView.cpp | 19 -------------------
 GUI/View/List/SamplesQListView.h   |  2 --
 2 files changed, 21 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 78a83ba5637..44369830e08 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -33,14 +33,10 @@ SamplesQListView::SamplesQListView()
     setModel(m_model);
     setSelectionMode(QAbstractItemView::SingleSelection);
 
-    setContextMenuPolicy(Qt::CustomContextMenu);
-
     setItemDelegate(new ListItemDelegate(this));
 
     connect(selectionModel(), &QItemSelectionModel::currentChanged, this,
             &SamplesQListView::onCurrentChanged);
-
-    connect(this, &QWidget::customContextMenuRequested, this, &SamplesQListView::showContextMenu);
 }
 
 void SamplesQListView::createNewSample()
@@ -104,18 +100,3 @@ QAction* SamplesQListView::createCopyAction(QObject* parent, SampleItem* item)
 
     return copyAction;
 }
-
-void SamplesQListView::showContextMenu(const QPoint& pos)
-{
-    auto* sampleAtPoint = m_model->itemForIndex(indexAt(pos));
-
-    QMenu menu;
-    menu.setToolTipsVisible(true);
-
-    if (sampleAtPoint != nullptr) {
-        menu.addAction(createCopyAction(&menu, sampleAtPoint));
-        menu.addAction(createRemoveAction(&menu, sampleAtPoint));
-        menu.addSeparator();
-    }
-    menu.exec(mapToGlobal(pos));
-}
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index 61beb0196e8..b1e8f14d31d 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -40,8 +40,6 @@ private:
     QAction* createRemoveAction(QObject* parent, SampleItem* item);
     QAction* createCopyAction(QObject* parent, SampleItem* item);
 
-    void showContextMenu(const QPoint& pos);
-
     SamplesQModel* m_model;
 };
 
-- 
GitLab


From 37ca25528aa8c64cd7538e814141db57fe4a471a Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:12:00 +0100
Subject: [PATCH 072/108] .

---
 GUI/View/List/InstrumentsQModel.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index 424cbe5ffc6..ad286b2d551 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -89,6 +89,7 @@ QModelIndex InstrumentsQModel::pushInstrument(InstrumentItem* t)
     beginInsertRows({}, row, row);
     set()->push_back(t);
     endInsertRows();
+
     emit set()->setChanged();
 
     return createIndex(row, 0);
-- 
GitLab


From c97e8022c292e25c3119a08e2f784c8a95692a1a Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:14:12 +0100
Subject: [PATCH 073/108] rm fcts

---
 GUI/View/List/SamplesQListView.cpp | 16 ----------------
 GUI/View/List/SamplesQListView.h   |  3 ---
 2 files changed, 19 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 44369830e08..4c06900844a 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -84,19 +84,3 @@ void SamplesQListView::copySample(SampleItem* item)
     m_model->copySample(item);
     gDoc->setModified();
 }
-
-QAction* SamplesQListView::createRemoveAction(QObject* parent, SampleItem* item)
-{
-    QAction* removeAction = ActionFactory::createRemoveAction("sample", parent);
-    connect(removeAction, &QAction::triggered, [this, item] { removeSample(item); });
-
-    return removeAction;
-}
-
-QAction* SamplesQListView::createCopyAction(QObject* parent, SampleItem* item)
-{
-    auto* copyAction = ActionFactory::createCopyAction("sample", parent);
-    connect(copyAction, &QAction::triggered, [this, item] { copySample(item); });
-
-    return copyAction;
-}
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index b1e8f14d31d..a06d5e46d14 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -37,9 +37,6 @@ signals:
     void currentSampleChanged(SampleItem* current);
 
 private:
-    QAction* createRemoveAction(QObject* parent, SampleItem* item);
-    QAction* createCopyAction(QObject* parent, SampleItem* item);
-
     SamplesQModel* m_model;
 };
 
-- 
GitLab


From 2303765ec6d7d0c06f16f1188ab0ededee486b11 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:15:48 +0100
Subject: [PATCH 074/108] rm

---
 GUI/View/List/SamplesQListView.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 4c06900844a..c7dbe645c2b 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -22,7 +22,6 @@
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QAction>
-#include <QMenu>
 
 SamplesQListView::SamplesQListView()
     : m_model(new SamplesQModel(this))
-- 
GitLab


From c32be0064755aa5e15c09b36f082add7322acbf5 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:24:28 +0100
Subject: [PATCH 075/108] SampleView own list model

---
 GUI/View/List/SamplesQListView.cpp |  4 ++--
 GUI/View/List/SamplesQListView.h   |  2 +-
 GUI/View/Views/SampleView.cpp      | 23 +++++++++++++----------
 GUI/View/Views/SampleView.h        |  4 +++-
 4 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index c7dbe645c2b..8aa69cf341e 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -23,8 +23,8 @@
 #include "GUI/View/Widget/ListItemDelegate.h"
 #include <QAction>
 
-SamplesQListView::SamplesQListView()
-    : m_model(new SamplesQModel(this))
+SamplesQListView::SamplesQListView(SamplesQModel* model)
+    : m_model(model)
 {
     setMaximumWidth(200);
     setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index a06d5e46d14..fd583679e0b 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -24,7 +24,7 @@ class SamplesQModel;
 class SamplesQListView : public QListView {
     Q_OBJECT
 public:
-    SamplesQListView();
+    SamplesQListView(SamplesQModel*);
 
     void createNewSample();
     void createSampleFromLibrary(const QString& classname, const QString& title,
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 19d73c9fa48..739c45026f0 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -24,6 +24,7 @@
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Layout/mainwindow_constants.h"
 #include "GUI/View/List/SamplesQListView.h"
+#include "GUI/View/List/SamplesQModel.h"
 #include "GUI/View/Realspace/RealspacePanel.h"
 #include "GUI/View/Realspace/RealspaceWidget.h"
 #include "GUI/View/Sample/SampleEditor.h"
@@ -40,8 +41,9 @@
 #include <QWidgetAction>
 
 SampleView::SampleView()
-    : m_realspace_panel(new RealspacePanel(this))
-    , m_listing(new SamplesQListView)
+    : m_qlistmodel(new SamplesQModel(this))
+    , m_qlistview(new SamplesQListView(m_qlistmodel))
+    , m_realspace_panel(new RealspacePanel(this))
 {
     auto* layout = new QVBoxLayout(this);
     layout->setContentsMargins(0, 0, 0, 0);
@@ -57,8 +59,8 @@ SampleView::SampleView()
 
     //... Left margin: sample listing
 
-    hLayout->addWidget(m_listing);
-    m_listing->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+    hLayout->addWidget(m_qlistview);
+    m_qlistview->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
 
     //... Right block: sample editor and bottom panels
 
@@ -99,7 +101,8 @@ SampleView::SampleView()
     new_sample_action->setToolTip("Create new sample");
     toolbar->addAction(new_sample_action);
 
-    connect(new_sample_action, &QAction::triggered, m_listing, &SamplesQListView::createNewSample);
+    connect(new_sample_action, &QAction::triggered, m_qlistview,
+            &SamplesQListView::createNewSample);
 
 #ifdef BORNAGAIN_PYTHON
     auto* import_sample_action = new QAction("Import", this);
@@ -108,7 +111,7 @@ SampleView::SampleView()
         "Import sample from a Python script that contains a function that returns a multi-layer");
     toolbar->addAction(import_sample_action);
 
-    connect(import_sample_action, &QAction::triggered, m_listing,
+    connect(import_sample_action, &QAction::triggered, m_qlistview,
             &SamplesQListView::importSampleFromPython);
 #endif
 
@@ -128,19 +131,19 @@ SampleView::SampleView()
         auto* action = import_menu->addAction(icon, title);
         action->setToolTip(description);
         connect(action, &QAction::triggered, [this, exampleName, title, description] {
-            m_listing->createSampleFromLibrary(exampleName, title, description);
+            m_qlistview->createSampleFromLibrary(exampleName, title, description);
         });
     }
 
     //... Finish
 
-    connect(m_listing, &SamplesQListView::currentSampleChanged, editor,
+    connect(m_qlistview, &SamplesQListView::currentSampleChanged, editor,
             &SampleEditor::setCurrentSample);
 
-    connect(m_listing, &SamplesQListView::currentSampleChanged,
+    connect(m_qlistview, &SamplesQListView::currentSampleChanged,
             [&](SampleItem* m) { onRequestViewInRealspace(m); });
 
-    connect(m_listing, &SamplesQListView::currentSampleChanged, scriptPanel,
+    connect(m_qlistview, &SamplesQListView::currentSampleChanged, scriptPanel,
             &ScriptPanel::setCurrentSample);
 
     connect(editor, &SampleEditor::modified, scriptPanel, &ScriptPanel::onSampleModified);
diff --git a/GUI/View/Views/SampleView.h b/GUI/View/Views/SampleView.h
index 448feabda0f..16db6081e34 100644
--- a/GUI/View/Views/SampleView.h
+++ b/GUI/View/Views/SampleView.h
@@ -21,6 +21,7 @@
 class Item3D;
 class RealspacePanel;
 class SamplesQListView;
+class SamplesQModel;
 
 class SampleView : public QWidget {
     Q_OBJECT
@@ -39,8 +40,9 @@ private:
     void applySplitterPos();
     void saveSplitterPos();
 
+    SamplesQModel* m_qlistmodel;
+    SamplesQListView* m_qlistview;
     RealspacePanel* m_realspace_panel;
-    SamplesQListView* m_listing;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_VIEWS_SAMPLEVIEW_H
-- 
GitLab


From 0c11aa868780451e875a00c699c153071ea2865d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:32:07 +0100
Subject: [PATCH 076/108] save/load fcts specify format in fct name

---
 GUI/View/Loader/ComponentRW.cpp   | 28 ++++++++++++++--------------
 GUI/View/Loader/ComponentRW.h     |  4 ++--
 GUI/View/Views/InstrumentView.cpp |  4 ++--
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/GUI/View/Loader/ComponentRW.cpp b/GUI/View/Loader/ComponentRW.cpp
index f5db8e1027f..58e616bc495 100644
--- a/GUI/View/Loader/ComponentRW.cpp
+++ b/GUI/View/Loader/ComponentRW.cpp
@@ -21,37 +21,37 @@
 
 namespace {
 
-template <class T> void save(const QString& fname, const T* t);
-template <class T> T* load(const QString& fname);
+template <class T> void saveToXML(const QString& fname, const T* t);
+template <class T> T* loadFromXML(const QString& fname);
 
-template <> void save<InstrumentItem>(const QString& fname, const InstrumentItem* t)
+template <> void saveToXML<InstrumentItem>(const QString& fname, const InstrumentItem* t)
 {
     InstrumentXML::save(fname, t);
 }
-template <> InstrumentItem* load<InstrumentItem>(const QString& fname)
+template <> InstrumentItem* loadFromXML<InstrumentItem>(const QString& fname)
 {
     return InstrumentXML::load(fname);
 }
 
-} // namespace
+// Force instantiation by assigning the function to a global variable that will never be used:
+auto dummy_saveXML_InstrumentItem = &RW::saveComponentToXML<class InstrumentItem>;
+auto dummy_loadXML_InstrumentItem = &RW::loadComponentFromXML<class InstrumentItem>;
 
+} // namespace
 
-// Force instantiation by assigning the function to a global variable that will never be used:
-auto dummy_saveComponent_InstrumentItem = &RW::saveComponent<class InstrumentItem>;
-auto dummy_loadComponent_InstrumentItem = &RW::loadComponent<class InstrumentItem>;
 
-template <class T> void RW::saveComponent(const QString& type, const T* t)
+template <class T> void RW::saveComponentToXML(const QString& type, const T* t)
 {
     if (!t)
         return;
 
     QString fname = GUI::Dialog::fileSaveDialog("Save " + type, appSettings->xml_dir,
-                                                "XML Files (*.xml)", t->name() + ".xml");
+                                                "XML files (*.xml)", t->name() + ".xml");
     if (fname.isEmpty())
         return;
 
     try {
-        ::save<T>(fname, t);
+        ::saveToXML<T>(fname, t);
     } catch (const std::exception& ex) {
         QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", ex.what(), QMessageBox::Ok,
                     nullptr)
@@ -59,15 +59,15 @@ template <class T> void RW::saveComponent(const QString& type, const T* t)
     }
 }
 
-template <class T> T* RW::loadComponent(const QString& type)
+template <class T> T* RW::loadComponentFromXML(const QString& type)
 {
     QString fname =
-        GUI::Dialog::fileOpenDialog("Load " + type, appSettings->xml_dir, "XML Files (*.xml)");
+        GUI::Dialog::fileOpenDialog("Load " + type, appSettings->xml_dir, "XML files (*.xml)");
     if (fname.isEmpty())
         return nullptr;
 
     try {
-        return ::load<T>(fname);
+        return ::loadFromXML<T>(fname);
     } catch (const std::exception& ex) {
         QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", ex.what(), QMessageBox::Ok,
                     nullptr)
diff --git a/GUI/View/Loader/ComponentRW.h b/GUI/View/Loader/ComponentRW.h
index a191249df71..e15a166c333 100644
--- a/GUI/View/Loader/ComponentRW.h
+++ b/GUI/View/Loader/ComponentRW.h
@@ -19,8 +19,8 @@
 
 namespace RW {
 
-template <class T> void saveComponent(const QString& type, const T* t);
-template <class T> T* loadComponent(const QString& type);
+template <class T> void saveComponentToXML(const QString& type, const T* t);
+template <class T> T* loadComponentFromXML(const QString& type);
 
 } // namespace RW
 
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 1d2d61ba876..0ea19abff94 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -96,10 +96,10 @@ InstrumentView::InstrumentView()
             &InstrumentView::createWidgetsForCurrentInstrument);
 
     connect(gActions->store_in_library_instrument, &QAction::triggered,
-            [] { RW::saveComponent("instrument", gDoc->instruments()->currentItem()); });
+            [] { RW::saveComponentToXML("instrument", gDoc->instruments()->currentItem()); });
 
     connect(gActions->load_from_library_instrument, &QAction::triggered, [this] {
-        m_qlistmodel->pushInstrument(RW::loadComponent<InstrumentItem>("instrument"));
+        m_qlistmodel->pushInstrument(RW::loadComponentFromXML<InstrumentItem>("instrument"));
     });
 
     updateActions();
-- 
GitLab


From 2c695b1e4cec0fc8792582fa4433ce9d1bac9f7f Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:51:13 +0100
Subject: [PATCH 077/108] import Py in one go

---
 GUI/View/List/SamplesQModel.cpp        |  6 +---
 GUI/View/Manager/PyImportAssistant.cpp | 45 +++++++++++++-------------
 GUI/View/Manager/PyImportAssistant.h   |  8 +----
 3 files changed, 25 insertions(+), 34 deletions(-)

diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 5e9d589d918..bbc89e33cc8 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -149,11 +149,7 @@ QModelIndex SamplesQModel::createSampleFromExamples(const QString& className, co
 #ifdef BORNAGAIN_PYTHON
 QModelIndex SamplesQModel::createSampleFromPython()
 {
-    std::unique_ptr<MultiLayer> sample = PyImportAssistant::importMultiLayer();
-    if (!sample)
-        return {}; // any messages already shown to user
-
-    SampleItem* t = PyImportAssistant::itemizeSample(*sample);
+    SampleItem* t = PyImportAssistant::importMultiLayer();
     if (!t)
         return {}; // any messages already shown to user
     t->setDescription("Imported from python code");
diff --git a/GUI/View/Manager/PyImportAssistant.cpp b/GUI/View/Manager/PyImportAssistant.cpp
index 35e124065ad..a3def5f5639 100644
--- a/GUI/View/Manager/PyImportAssistant.cpp
+++ b/GUI/View/Manager/PyImportAssistant.cpp
@@ -158,10 +158,29 @@ QString getPySampleFunctionName(const QString& snippet)
     return selectPySampleFunction(funcList);
 }
 
+SampleItem* itemizeSample(const MultiLayer& sample)
+{
+    try {
+        auto* newItem = GUI::FromCore::itemizeSample(sample);
+
+        QString message("Seems that import was successful.\n\n"
+                        "Check SampleView for new sample and material editor for new materials.");
+        GUI::Message::information(GUI::Global::mainWindow, "Python import", message);
+        return newItem;
+    } catch (const std::exception& ex) {
+        QString message("Exception thrown while trying to build GUI models.\n"
+                        "GUI models might be in inconsistent state.\n\n");
+        QString details = QString::fromStdString(std::string(ex.what()));
+        DetailedMessageBox(GUI::Global::mainWindow, "GUI::ObjectBuilder failure", message, details)
+            .exec();
+        return nullptr;
+    }
+}
+
 } // namespace
 
 
-std::unique_ptr<MultiLayer> PyImportAssistant::importMultiLayer()
+SampleItem* PyImportAssistant::importMultiLayer()
 {
     auto fname = fnameToOpen();
 
@@ -176,15 +195,15 @@ std::unique_ptr<MultiLayer> PyImportAssistant::importMultiLayer()
     if (funcName.isEmpty())
         return {};
 
+    std::unique_ptr<MultiLayer> sample;
     try {
-        std::unique_ptr<MultiLayer> sample = code2sample(snippet, funcName);
+        sample.reset(code2sample(snippet, funcName));
         if (!sample)
             throw std::runtime_error("Import did not yield MultiLayer object");
 
         if (sample->name() == "Unnamed")
             sample->setName(GUI::Path::baseName(fname).toStdString());
 
-        return sample;
     } catch (const std::exception& ex) {
         QApplication::restoreOverrideCursor();
         QMessageBox msgbox(QMessageBox::Warning, "BornAgain: failed import", QString(ex.what()),
@@ -192,26 +211,8 @@ std::unique_ptr<MultiLayer> PyImportAssistant::importMultiLayer()
         msgbox.exec();
         return {};
     }
-    return {};
-}
 
-SampleItem* PyImportAssistant::itemizeSample(const MultiLayer& sample)
-{
-    try {
-        auto* newItem = GUI::FromCore::itemizeSample(sample);
-
-        QString message("Seems that import was successful.\n\n"
-                        "Check SampleView for new sample and material editor for new materials.");
-        GUI::Message::information(GUI::Global::mainWindow, "Python import", message);
-        return newItem;
-    } catch (const std::exception& ex) {
-        QString message("Exception thrown while trying to build GUI models.\n"
-                        "GUI models might be in inconsistent state.\n\n");
-        QString details = QString::fromStdString(std::string(ex.what()));
-        DetailedMessageBox(GUI::Global::mainWindow, "GUI::ObjectBuilder failure", message, details)
-            .exec();
-        return nullptr;
-    }
+    return ::itemizeSample(*sample);
 }
 
 #endif // BORNAGAIN_PYTHON
diff --git a/GUI/View/Manager/PyImportAssistant.h b/GUI/View/Manager/PyImportAssistant.h
index 1d875e79467..7918bbdc438 100644
--- a/GUI/View/Manager/PyImportAssistant.h
+++ b/GUI/View/Manager/PyImportAssistant.h
@@ -17,9 +17,6 @@
 
 #ifdef BORNAGAIN_PYTHON
 
-#include <memory>
-
-class MultiLayer;
 class SampleItem;
 
 //! Assists in importing Python object to GUI models.
@@ -29,10 +26,7 @@ namespace PyImportAssistant {
 //! Show select-file dialog, try to import via python, return created sample.
 //!
 //! If sth. went wrong, a dialog has presented already and nullptr is returned.
-std::unique_ptr<MultiLayer> importMultiLayer();
-
-//! Populates GUI sample with domain sample.
-SampleItem* itemizeSample(const MultiLayer& sample);
+SampleItem* importMultiLayer();
 
 } // namespace PyImportAssistant
 
-- 
GitLab


From f2fbe4b075fc796f5c94ccf93541517eefe75e4d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 15:51:31 +0100
Subject: [PATCH 078/108] repair previous

---
 GUI/View/Loader/ComponentRW.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/GUI/View/Loader/ComponentRW.cpp b/GUI/View/Loader/ComponentRW.cpp
index 58e616bc495..de10b49514d 100644
--- a/GUI/View/Loader/ComponentRW.cpp
+++ b/GUI/View/Loader/ComponentRW.cpp
@@ -33,12 +33,12 @@ template <> InstrumentItem* loadFromXML<InstrumentItem>(const QString& fname)
     return InstrumentXML::load(fname);
 }
 
+} // namespace
+
 // Force instantiation by assigning the function to a global variable that will never be used:
 auto dummy_saveXML_InstrumentItem = &RW::saveComponentToXML<class InstrumentItem>;
 auto dummy_loadXML_InstrumentItem = &RW::loadComponentFromXML<class InstrumentItem>;
 
-} // namespace
-
 
 template <class T> void RW::saveComponentToXML(const QString& type, const T* t)
 {
-- 
GitLab


From 625c58150e21e4538e084c106ba9426ad5fdd690 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 23 Feb 2024 16:48:00 +0100
Subject: [PATCH 079/108] repair Py

---
 GUI/View/Manager/PyImportAssistant.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GUI/View/Manager/PyImportAssistant.cpp b/GUI/View/Manager/PyImportAssistant.cpp
index a3def5f5639..bb321792d3a 100644
--- a/GUI/View/Manager/PyImportAssistant.cpp
+++ b/GUI/View/Manager/PyImportAssistant.cpp
@@ -197,7 +197,7 @@ SampleItem* PyImportAssistant::importMultiLayer()
 
     std::unique_ptr<MultiLayer> sample;
     try {
-        sample.reset(code2sample(snippet, funcName));
+        sample = code2sample(snippet, funcName);
         if (!sample)
             throw std::runtime_error("Import did not yield MultiLayer object");
 
-- 
GitLab


From c31cadca04d480239556a83e459bb8f07b3c6cc5 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 08:20:05 +0100
Subject: [PATCH 080/108] new... actions made local

---
 GUI/View/Setup/FrameActions.cpp   | 16 --------------
 GUI/View/Setup/FrameActions.h     |  4 ----
 GUI/View/Views/InstrumentView.cpp | 36 +++++++++++++++++--------------
 3 files changed, 20 insertions(+), 36 deletions(-)

diff --git a/GUI/View/Setup/FrameActions.cpp b/GUI/View/Setup/FrameActions.cpp
index a08225d2ab7..36a35eea151 100644
--- a/GUI/View/Setup/FrameActions.cpp
+++ b/GUI/View/Setup/FrameActions.cpp
@@ -76,22 +76,6 @@ FrameActions::FrameActions()
     cycle_data2d_edit_mode->setIcon(QIcon(":/images/sprocket3.svg"));
     cycle_data2d_edit_mode->setToolTip("Cycle data 2d edit mode: Data, Mask, Projection");
 
-    new_gisas_instrument = new QAction("New GISAS");
-    new_gisas_instrument->setIcon(QIcon(":/images/shape-square-plus.svg"));
-    new_gisas_instrument->setToolTip("Add new GISAS instrument with default settings");
-
-    new_offspec_instrument = new QAction("New off-specular");
-    new_offspec_instrument->setIcon(QIcon(":/images/shape-square-plus.svg"));
-    new_offspec_instrument->setToolTip("Add new off-specular instrument with default settings");
-
-    new_specular_instrument = new QAction("New specular");
-    new_specular_instrument->setIcon(QIcon(":/images/shape-square-plus.svg"));
-    new_specular_instrument->setToolTip("Add new specular instrument with default settings");
-
-    new_depthprobe_instrument = new QAction("New depth probe");
-    new_depthprobe_instrument->setIcon(QIcon(":/images/shape-square-plus.svg"));
-    new_depthprobe_instrument->setToolTip("Add new depth probe instrument with default settings");
-
     remove_instrument = ActionFactory::createRemoveAction("instrument");
     copy_instrument = ActionFactory::createCopyAction("instrument");
 
diff --git a/GUI/View/Setup/FrameActions.h b/GUI/View/Setup/FrameActions.h
index e2cf29951fb..8b738a19960 100644
--- a/GUI/View/Setup/FrameActions.h
+++ b/GUI/View/Setup/FrameActions.h
@@ -46,10 +46,6 @@ public:
 
     QAction* cycle_data2d_edit_mode;
 
-    QAction* new_gisas_instrument;
-    QAction* new_offspec_instrument;
-    QAction* new_specular_instrument;
-    QAction* new_depthprobe_instrument;
     QAction* remove_instrument;
     QAction* copy_instrument;
     QAction* store_in_library_instrument;
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 0ea19abff94..7804888a827 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -45,10 +45,26 @@ InstrumentView::InstrumentView()
     layout->addWidget(toolbar);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
 
-    toolbar->addAction(gActions->new_gisas_instrument);
-    toolbar->addAction(gActions->new_offspec_instrument);
-    toolbar->addAction(gActions->new_specular_instrument);
-    toolbar->addAction(gActions->new_depthprobe_instrument);
+    auto new_action = [toolbar](const QString& name, const QString& description) {
+        QAction* a = new QAction("New " + name);
+        a->setIcon(QIcon(":/images/shape-square-plus.svg"));
+        a->setToolTip("Add new " + description + " instrument with default settings");
+        toolbar->addAction(a);
+        return a;
+    };
+
+    connect(new_action("GISAS", "2D scattering"), &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new Scatter2DInstrumentItem); });
+
+    connect(new_action("offspec", "off-specular"), &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new OffspecInstrumentItem); });
+
+    connect(new_action("specular", "specular reflectivity"), &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new SpecularInstrumentItem); });
+
+    connect(new_action("depthprobe", "depth intensity profile"), &QAction::triggered,
+            [this] { m_qlistmodel->pushInstrument(new DepthprobeInstrumentItem); });
+
     toolbar->addAction(gActions->remove_instrument);
     toolbar->addAction(gActions->copy_instrument);
     toolbar->addAction(gActions->store_in_library_instrument);
@@ -74,18 +90,6 @@ InstrumentView::InstrumentView()
 
     //... Finalize
 
-    connect(gActions->new_gisas_instrument, &QAction::triggered,
-            [this] { m_qlistmodel->pushInstrument(new Scatter2DInstrumentItem); });
-
-    connect(gActions->new_offspec_instrument, &QAction::triggered,
-            [this] { m_qlistmodel->pushInstrument(new OffspecInstrumentItem); });
-
-    connect(gActions->new_specular_instrument, &QAction::triggered,
-            [this] { m_qlistmodel->pushInstrument(new SpecularInstrumentItem); });
-
-    connect(gActions->new_depthprobe_instrument, &QAction::triggered,
-            [this] { m_qlistmodel->pushInstrument(new DepthprobeInstrumentItem); });
-
     connect(gActions->remove_instrument, &QAction::triggered, m_qlistmodel,
             &InstrumentsQModel::removeInstrument);
 
-- 
GitLab


From 5ad56ecfe704aa6f322818912732c6ba2058f41a Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 08:25:28 +0100
Subject: [PATCH 081/108] rm & cp actions made local

---
 GUI/View/Setup/FrameActions.cpp   |  3 ---
 GUI/View/Setup/FrameActions.h     |  2 --
 GUI/View/Views/InstrumentView.cpp | 30 ++++++++++++++++--------------
 GUI/View/Views/InstrumentView.h   |  4 ++++
 4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/GUI/View/Setup/FrameActions.cpp b/GUI/View/Setup/FrameActions.cpp
index 36a35eea151..19e1cfe2f4d 100644
--- a/GUI/View/Setup/FrameActions.cpp
+++ b/GUI/View/Setup/FrameActions.cpp
@@ -76,9 +76,6 @@ FrameActions::FrameActions()
     cycle_data2d_edit_mode->setIcon(QIcon(":/images/sprocket3.svg"));
     cycle_data2d_edit_mode->setToolTip("Cycle data 2d edit mode: Data, Mask, Projection");
 
-    remove_instrument = ActionFactory::createRemoveAction("instrument");
-    copy_instrument = ActionFactory::createCopyAction("instrument");
-
     store_in_library_instrument = new QAction("Store in library");
     store_in_library_instrument->setIcon(QIcon(":/images/library.svg"));
     store_in_library_instrument->setToolTip("Store instrument in library");
diff --git a/GUI/View/Setup/FrameActions.h b/GUI/View/Setup/FrameActions.h
index 8b738a19960..d4802f836d9 100644
--- a/GUI/View/Setup/FrameActions.h
+++ b/GUI/View/Setup/FrameActions.h
@@ -46,8 +46,6 @@ public:
 
     QAction* cycle_data2d_edit_mode;
 
-    QAction* remove_instrument;
-    QAction* copy_instrument;
     QAction* store_in_library_instrument;
     QAction* load_from_library_instrument;
 };
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 7804888a827..7b21fa49c18 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -40,13 +40,14 @@ InstrumentView::InstrumentView()
 {
     auto* layout = new QVBoxLayout(this);
 
-    // Top toolbar with action buttons "new ...instrument" etc
+    //... Top toolbar with action buttons "new ...instrument" etc
+
     auto* toolbar = new StyledToolbar;
     layout->addWidget(toolbar);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
 
-    auto new_action = [toolbar](const QString& name, const QString& description) {
-        QAction* a = new QAction("New " + name);
+    auto new_action = [this, toolbar](const QString& name, const QString& description) {
+        QAction* a = new QAction("New " + name, this);
         a->setIcon(QIcon(":/images/shape-square-plus.svg"));
         a->setToolTip("Add new " + description + " instrument with default settings");
         toolbar->addAction(a);
@@ -65,12 +66,19 @@ InstrumentView::InstrumentView()
     connect(new_action("depthprobe", "depth intensity profile"), &QAction::triggered,
             [this] { m_qlistmodel->pushInstrument(new DepthprobeInstrumentItem); });
 
-    toolbar->addAction(gActions->remove_instrument);
-    toolbar->addAction(gActions->copy_instrument);
+    m_rm_action = ActionFactory::createRemoveAction("instrument", this);
+    toolbar->addAction(m_rm_action);
+    connect(m_rm_action, &QAction::triggered, m_qlistmodel, &InstrumentsQModel::removeInstrument);
+
+    m_cp_action = ActionFactory::createCopyAction("instrument", this);
+    toolbar->addAction(m_cp_action);
+    connect(m_cp_action, &QAction::triggered, m_qlistmodel, &InstrumentsQModel::copyInstrument);
+
     toolbar->addAction(gActions->store_in_library_instrument);
     toolbar->addAction(gActions->load_from_library_instrument);
 
-    // Everything below
+    //... Everything below top toolbar
+
     auto* hLayout = new QHBoxLayout;
     layout->addLayout(hLayout);
 
@@ -90,12 +98,6 @@ InstrumentView::InstrumentView()
 
     //... Finalize
 
-    connect(gActions->remove_instrument, &QAction::triggered, m_qlistmodel,
-            &InstrumentsQModel::removeInstrument);
-
-    connect(gActions->copy_instrument, &QAction::triggered, m_qlistmodel,
-            &InstrumentsQModel::copyInstrument);
-
     connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
@@ -166,7 +168,7 @@ void InstrumentView::createWidgetsForCurrentInstrument()
 void InstrumentView::updateActions()
 {
     bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
-    gActions->remove_instrument->setEnabled(enabled);
-    gActions->copy_instrument->setEnabled(enabled);
+    m_rm_action->setEnabled(enabled);
+    m_cp_action->setEnabled(enabled);
     gActions->store_in_library_instrument->setEnabled(enabled);
 }
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index ad76a451848..268df3e0bd0 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -15,6 +15,7 @@
 #ifndef BORNAGAIN_GUI_VIEW_VIEWS_INSTRUMENTVIEW_H
 #define BORNAGAIN_GUI_VIEW_VIEWS_INSTRUMENTVIEW_H
 
+#include <QAction>
 #include <QCheckBox>
 #include <QScrollArea>
 #include <QWidget>
@@ -37,6 +38,9 @@ private:
     InstrumentsQModel* m_qlistmodel;
     InstrumentsQListView* m_qlistview;
     QScrollArea* m_scroll_area;
+
+    QAction* m_rm_action;
+    QAction* m_cp_action;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_VIEWS_INSTRUMENTVIEW_H
-- 
GitLab


From 110efb6da57d604bb48f0cef68ce8476b0ae622f Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 08:34:40 +0100
Subject: [PATCH 082/108] remaining instruments actions made local

---
 GUI/View/Setup/FrameActions.cpp   |  8 --------
 GUI/View/Setup/FrameActions.h     |  3 ---
 GUI/View/Views/InstrumentView.cpp | 25 +++++++++++++++----------
 GUI/View/Views/InstrumentView.h   |  2 ++
 4 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/GUI/View/Setup/FrameActions.cpp b/GUI/View/Setup/FrameActions.cpp
index 19e1cfe2f4d..33dfc478527 100644
--- a/GUI/View/Setup/FrameActions.cpp
+++ b/GUI/View/Setup/FrameActions.cpp
@@ -75,12 +75,4 @@ FrameActions::FrameActions()
     cycle_data2d_edit_mode = new QAction("Cycle mode");
     cycle_data2d_edit_mode->setIcon(QIcon(":/images/sprocket3.svg"));
     cycle_data2d_edit_mode->setToolTip("Cycle data 2d edit mode: Data, Mask, Projection");
-
-    store_in_library_instrument = new QAction("Store in library");
-    store_in_library_instrument->setIcon(QIcon(":/images/library.svg"));
-    store_in_library_instrument->setToolTip("Store instrument in library");
-
-    load_from_library_instrument = new QAction("Choose from library");
-    load_from_library_instrument->setIcon(QIcon(":/images/library.svg"));
-    load_from_library_instrument->setToolTip("Load an instrument from the instrument library");
 }
diff --git a/GUI/View/Setup/FrameActions.h b/GUI/View/Setup/FrameActions.h
index d4802f836d9..702a3392565 100644
--- a/GUI/View/Setup/FrameActions.h
+++ b/GUI/View/Setup/FrameActions.h
@@ -45,9 +45,6 @@ public:
     QAction* toggle_properties_panel;
 
     QAction* cycle_data2d_edit_mode;
-
-    QAction* store_in_library_instrument;
-    QAction* load_from_library_instrument;
 };
 
 extern FrameActions* gActions;
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 7b21fa49c18..7152dd0e57c 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -74,8 +74,20 @@ InstrumentView::InstrumentView()
     toolbar->addAction(m_cp_action);
     connect(m_cp_action, &QAction::triggered, m_qlistmodel, &InstrumentsQModel::copyInstrument);
 
-    toolbar->addAction(gActions->store_in_library_instrument);
-    toolbar->addAction(gActions->load_from_library_instrument);
+    m_save_action = new QAction("Store in library", this);
+    m_save_action->setIcon(QIcon(":/images/library.svg"));
+    m_save_action->setToolTip("Store instrument in library");
+    toolbar->addAction(m_save_action);
+    connect(m_save_action, &QAction::triggered,
+            [] { RW::saveComponentToXML("instrument", gDoc->instruments()->currentItem()); });
+
+    m_load_action = new QAction("Choose from library", this);
+    m_load_action->setIcon(QIcon(":/images/library.svg"));
+    m_load_action->setToolTip("Load an instrument from the instrument library");
+    toolbar->addAction(m_load_action);
+    connect(m_load_action, &QAction::triggered, [this] {
+        m_qlistmodel->pushInstrument(RW::loadComponentFromXML<InstrumentItem>("instrument"));
+    });
 
     //... Everything below top toolbar
 
@@ -101,13 +113,6 @@ InstrumentView::InstrumentView()
     connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
             &InstrumentView::createWidgetsForCurrentInstrument);
 
-    connect(gActions->store_in_library_instrument, &QAction::triggered,
-            [] { RW::saveComponentToXML("instrument", gDoc->instruments()->currentItem()); });
-
-    connect(gActions->load_from_library_instrument, &QAction::triggered, [this] {
-        m_qlistmodel->pushInstrument(RW::loadComponentFromXML<InstrumentItem>("instrument"));
-    });
-
     updateActions();
 }
 
@@ -170,5 +175,5 @@ void InstrumentView::updateActions()
     bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
     m_rm_action->setEnabled(enabled);
     m_cp_action->setEnabled(enabled);
-    gActions->store_in_library_instrument->setEnabled(enabled);
+    m_save_action->setEnabled(enabled);
 }
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index 268df3e0bd0..339dfe0c7c2 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -41,6 +41,8 @@ private:
 
     QAction* m_rm_action;
     QAction* m_cp_action;
+    QAction* m_load_action;
+    QAction* m_save_action;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_VIEWS_INSTRUMENTVIEW_H
-- 
GitLab


From acdad288b37e29e414f811bdb6ccb54686d86470 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 09:07:42 +0100
Subject: [PATCH 083/108] extract method InstrumentView::setToolbarActions

---
 GUI/View/Views/InstrumentView.cpp | 63 ++++++++++++++++++-------------
 GUI/View/Views/InstrumentView.h   |  2 +
 2 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 7152dd0e57c..fd8e0cddf00 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -46,6 +46,39 @@ InstrumentView::InstrumentView()
     layout->addWidget(toolbar);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
 
+    setToolbarActions(toolbar);
+
+    //... Everything below top toolbar
+
+    auto* hLayout = new QHBoxLayout;
+    layout->addLayout(hLayout);
+
+    // Left margin: instrument list
+
+    hLayout->addWidget(m_qlistview);
+    m_qlistview->setMinimumWidth(200);
+
+    // Large widget: current instrument
+
+    hLayout->addWidget(m_scroll_area);
+    m_scroll_area->setWidgetResizable(true);
+    m_scroll_area->setMinimumWidth(1000);
+    m_scroll_area->setWidget(new QWidget(m_scroll_area)); // initial state: blank widget
+
+    hLayout->addStretch(1);
+
+    //... Finalize
+
+    connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
+            &InstrumentView::createWidgetsForCurrentInstrument);
+
+    updateActions();
+}
+
+void InstrumentView::setToolbarActions(QToolBar* toolbar)
+{
+    //... New-instrument actions
+
     auto new_action = [this, toolbar](const QString& name, const QString& description) {
         QAction* a = new QAction("New " + name, this);
         a->setIcon(QIcon(":/images/shape-square-plus.svg"));
@@ -66,6 +99,8 @@ InstrumentView::InstrumentView()
     connect(new_action("depthprobe", "depth intensity profile"), &QAction::triggered,
             [this] { m_qlistmodel->pushInstrument(new DepthprobeInstrumentItem); });
 
+    //... Copy and remove actions
+
     m_rm_action = ActionFactory::createRemoveAction("instrument", this);
     toolbar->addAction(m_rm_action);
     connect(m_rm_action, &QAction::triggered, m_qlistmodel, &InstrumentsQModel::removeInstrument);
@@ -74,6 +109,8 @@ InstrumentView::InstrumentView()
     toolbar->addAction(m_cp_action);
     connect(m_cp_action, &QAction::triggered, m_qlistmodel, &InstrumentsQModel::copyInstrument);
 
+    //... Save and load actions
+
     m_save_action = new QAction("Store in library", this);
     m_save_action->setIcon(QIcon(":/images/library.svg"));
     m_save_action->setToolTip("Store instrument in library");
@@ -88,32 +125,6 @@ InstrumentView::InstrumentView()
     connect(m_load_action, &QAction::triggered, [this] {
         m_qlistmodel->pushInstrument(RW::loadComponentFromXML<InstrumentItem>("instrument"));
     });
-
-    //... Everything below top toolbar
-
-    auto* hLayout = new QHBoxLayout;
-    layout->addLayout(hLayout);
-
-    // Left margin: instrument list
-
-    hLayout->addWidget(m_qlistview);
-    m_qlistview->setMinimumWidth(200);
-
-    // Large widget: current instrument
-
-    hLayout->addWidget(m_scroll_area);
-    m_scroll_area->setWidgetResizable(true);
-    m_scroll_area->setMinimumWidth(1000);
-    m_scroll_area->setWidget(new QWidget(m_scroll_area)); // initial state: blank widget
-
-    hLayout->addStretch(1);
-
-    //... Finalize
-
-    connect(gDoc->instruments(), &InstrumentsSet::setChanged, this,
-            &InstrumentView::createWidgetsForCurrentInstrument);
-
-    updateActions();
 }
 
 void InstrumentView::createWidgetsForCurrentInstrument()
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index 339dfe0c7c2..11f3a6e3752 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -23,6 +23,7 @@
 class InstrumentItem;
 class InstrumentsQListView;
 class InstrumentsQModel;
+class QToolBar;
 
 class InstrumentView : public QWidget {
     Q_OBJECT
@@ -33,6 +34,7 @@ private slots:
     void updateActions();
 
 private:
+    void setToolbarActions(QToolBar* toolbar);
     void createWidgetsForCurrentInstrument();
 
     InstrumentsQModel* m_qlistmodel;
-- 
GitLab


From f243b9cff04a413f4a5256d0c6120520c9a1bda3 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 09:08:24 +0100
Subject: [PATCH 084/108] rm unused

---
 GUI/View/Views/InstrumentView.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index 11f3a6e3752..f3fb69bc0ef 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -16,7 +16,6 @@
 #define BORNAGAIN_GUI_VIEW_VIEWS_INSTRUMENTVIEW_H
 
 #include <QAction>
-#include <QCheckBox>
 #include <QScrollArea>
 #include <QWidget>
 
-- 
GitLab


From c9074479246bed4bfbb0dd45837728db97998a2b Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 09:09:45 +0100
Subject: [PATCH 085/108] rm 'slot'

---
 GUI/View/Views/InstrumentView.cpp | 16 ++++++++--------
 GUI/View/Views/InstrumentView.h   |  4 +---
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index fd8e0cddf00..e3560237972 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -127,6 +127,14 @@ void InstrumentView::setToolbarActions(QToolBar* toolbar)
     });
 }
 
+void InstrumentView::updateActions()
+{
+    bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
+    m_rm_action->setEnabled(enabled);
+    m_cp_action->setEnabled(enabled);
+    m_save_action->setEnabled(enabled);
+}
+
 void InstrumentView::createWidgetsForCurrentInstrument()
 {
     updateActions();
@@ -180,11 +188,3 @@ void InstrumentView::createWidgetsForCurrentInstrument()
     layout->addWidget(editor);
     m_scroll_area->setWidget(w);
 }
-
-void InstrumentView::updateActions()
-{
-    bool enabled = gDoc->instruments()->currentIndex() != size_t(-1);
-    m_rm_action->setEnabled(enabled);
-    m_cp_action->setEnabled(enabled);
-    m_save_action->setEnabled(enabled);
-}
diff --git a/GUI/View/Views/InstrumentView.h b/GUI/View/Views/InstrumentView.h
index f3fb69bc0ef..73c4b198fa2 100644
--- a/GUI/View/Views/InstrumentView.h
+++ b/GUI/View/Views/InstrumentView.h
@@ -29,11 +29,9 @@ class InstrumentView : public QWidget {
 public:
     InstrumentView();
 
-private slots:
-    void updateActions();
-
 private:
     void setToolbarActions(QToolBar* toolbar);
+    void updateActions();
     void createWidgetsForCurrentInstrument();
 
     InstrumentsQModel* m_qlistmodel;
-- 
GitLab


From 62e63e8906538621d17dbf8a0b98b3c272cbb605 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 09:22:20 +0100
Subject: [PATCH 086/108] style: rm last entries for ListView

---
 GUI/View/List/InstrumentsQModel.cpp |  2 +-
 GUI/styles/Base.stylesheet          | 11 ++++++-----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index ad286b2d551..b37880a7fe4 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -55,7 +55,7 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     case Qt::ToolTipRole:
         return t->description();
     case Qt::BackgroundRole:
-        return row == set()->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
+        return row == set()->currentIndex() ? QColor(Qt::white) : QColor(Qt::gray);
     default:
         return {};
     }
diff --git a/GUI/styles/Base.stylesheet b/GUI/styles/Base.stylesheet
index 3022c0d393a..8469bada1b6 100644
--- a/GUI/styles/Base.stylesheet
+++ b/GUI/styles/Base.stylesheet
@@ -254,17 +254,19 @@ QMenuBar::item:selected
 }
 
 /* ------------------------------------------------------------------------------- */
-/* Set alternate background color, e.g, for QTableWidgets alternate row coloring. */
+/* Set alternate background color, e.g, for QTableWidgets alternate row coloring.
 QAbstractItemView
 {
     alternate-background-color:palette(alternate-base);
 }
+*/
 
 /* ------------------------------------------------------------------------------- */
-QListView
+/* QListView
 {
-    /* background-color: palette(dark) */
+    background-color: palette(dark)
 }
+*/
 
 /* ------------------------------------------------------------------------------- */
 QDockWidget
@@ -563,13 +565,12 @@ ScientificSpinBox::down-button:pressed
 }
 
 
-
 QWidget{
     color: palette(text);
 }
 
 QTextEdit, QLineEdit, QSpinBox, ScientificSpinBox, QDoubleSpinBox, DoubleSpinBox, QComboBox, QTabWidget,
-QDockWidget, QListView, QTableView, QTableWidget, QHeaderView, QProgressBar, QSlider, QScrollBar,
+QDockWidget, QTableView, QTableWidget, QHeaderView, QProgressBar, QSlider, QScrollBar,
 QToolBar, QPushButton, QScrollArea {
     background-color: white;
 }
-- 
GitLab


From 0c84729930494bcac19549b0698d23281805bc8a Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 09:48:33 +0100
Subject: [PATCH 087/108] list colors: white & cyan

---
 GUI/View/List/InstrumentsQListView.cpp | 2 +-
 GUI/View/List/InstrumentsQModel.cpp    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index fab1fbc2bd4..854ac6d1a7b 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -27,7 +27,7 @@ InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
     setModel(model);
     setItemDelegate(new ListItemDelegate(this));
 
-    connect(this, &QListView::clicked, [](const QModelIndex& qi) {
+    connect(this, &QListView::clicked, [this](const QModelIndex& qi) {
         gDoc->instrumentsModifier()->setCurrentIndex(qi.row());
         emit gDoc->instruments()->setChanged();
     });
diff --git a/GUI/View/List/InstrumentsQModel.cpp b/GUI/View/List/InstrumentsQModel.cpp
index b37880a7fe4..4027ca76f54 100644
--- a/GUI/View/List/InstrumentsQModel.cpp
+++ b/GUI/View/List/InstrumentsQModel.cpp
@@ -55,7 +55,7 @@ QVariant InstrumentsQModel::data(const QModelIndex& index, int role) const
     case Qt::ToolTipRole:
         return t->description();
     case Qt::BackgroundRole:
-        return row == set()->currentIndex() ? QColor(Qt::white) : QColor(Qt::gray);
+        return row == set()->currentIndex() ? QColor(Qt::cyan) : QColor(Qt::white);
     default:
         return {};
     }
-- 
GitLab


From 3ff704a20a1bf8e1379ec9e4d8d30a623874afb0 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 10:18:47 +0100
Subject: [PATCH 088/108] Samples: rm/cp fcts as for instruments

---
 GUI/Model/Sample/SamplesSet.cpp    |  3 ++
 GUI/Model/Sample/SamplesSet.h      | 13 +++++-
 GUI/View/List/SamplesQListView.cpp | 12 -----
 GUI/View/List/SamplesQListView.h   |  2 -
 GUI/View/List/SamplesQModel.cpp    | 44 +++++++++++-------
 GUI/View/List/SamplesQModel.h      |  8 ++--
 GUI/View/Views/SampleView.cpp      | 75 ++++++++++++++++++------------
 GUI/View/Views/SampleView.h        | 11 +++--
 8 files changed, 96 insertions(+), 72 deletions(-)

diff --git a/GUI/Model/Sample/SamplesSet.cpp b/GUI/Model/Sample/SamplesSet.cpp
index 49796667263..8dbfad6678f 100644
--- a/GUI/Model/Sample/SamplesSet.cpp
+++ b/GUI/Model/Sample/SamplesSet.cpp
@@ -27,6 +27,9 @@ const QString CurrentIndex("CurrentIndex");
 } // namespace Tag
 } // namespace
 
+SamplesSet::SamplesSet() = default;
+SamplesSet::~SamplesSet() = default;
+
 QStringList SamplesSet::sampleNames() const
 {
     QStringList existingNames;
diff --git a/GUI/Model/Sample/SamplesSet.h b/GUI/Model/Sample/SamplesSet.h
index 019b6b0ca72..eb71f9e4c5f 100644
--- a/GUI/Model/Sample/SamplesSet.h
+++ b/GUI/Model/Sample/SamplesSet.h
@@ -16,18 +16,27 @@
 #define BORNAGAIN_GUI_MODEL_SAMPLE_SAMPLESSET_H
 
 #include "Base/Types/VectorWC.h"
+#include <QObject>
 #include <QXmlStreamReader>
 
 class SampleItem;
 
 //! Main model to hold sample items.
 
-class SamplesSet : public VectorWC<SampleItem> {
+class SamplesSet : public QObject, public VectorWC<SampleItem> {
+    Q_OBJECT
 public:
-    QStringList sampleNames() const;
+    SamplesSet();
+    ~SamplesSet();
 
     void writeTo(QXmlStreamWriter* w) const;
     void readFrom(QXmlStreamReader* r);
+
+    QStringList sampleNames() const;
+
+signals:
+    void setChanged() const;
+    void currentModified() const;
 };
 
 #endif // BORNAGAIN_GUI_MODEL_SAMPLE_SAMPLESSET_H
diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 8aa69cf341e..fc1d20b9e07 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -71,15 +71,3 @@ void SamplesQListView::onCurrentChanged(const QModelIndex& index)
     gDoc->samplesModifier()->setCurrentIndex(index.row());
     emit currentSampleChanged(m_model->itemForIndex(index));
 }
-
-void SamplesQListView::removeSample(SampleItem* item)
-{
-    m_model->removeSample(item);
-    gDoc->setModified();
-}
-
-void SamplesQListView::copySample(SampleItem* item)
-{
-    m_model->copySample(item);
-    gDoc->setModified();
-}
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index fd583679e0b..e4f62497479 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -31,8 +31,6 @@ public:
                                  const QString& description);
     void importSampleFromPython();
     void onCurrentChanged(const QModelIndex& index);
-    void removeSample(SampleItem* item);
-    void copySample(SampleItem* item);
 signals:
     void currentSampleChanged(SampleItem* current);
 
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index bbc89e33cc8..45c281acd28 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -86,29 +86,23 @@ QModelIndex SamplesQModel::indexForItem(SampleItem* item) const
     return {};
 }
 
-void SamplesQModel::removeSample(SampleItem* item)
+void SamplesQModel::removeSample()
 {
-    QModelIndex index = indexForItem(item);
-    if (!index.isValid())
-        return;
-
-    beginRemoveRows(index.parent(), index.row(), index.row());
-    set()->delete_element(item);
+    const size_t row = set()->currentIndex();
+    ASSERT(row != size_t(-1));
+    beginRemoveRows({}, row, row);
+    set()->delete_current();
     endRemoveRows();
+
+    emit set()->setChanged();
 }
 
-QModelIndex SamplesQModel::copySample(SampleItem* item)
+QModelIndex SamplesQModel::copySample()
 {
-    ASSERT(item);
-    const QStringList existingNames = set()->sampleNames();
-
-    const int row = set()->size();
-    beginInsertRows(QModelIndex(), row, row);
-    SampleItem* copied_item = item->clone();
-    copied_item->setName(GUI::Util::String::suggestName(existingNames, item->name()));
-    set()->push_back(copied_item);
-    endInsertRows();
-    return indexForItem(copied_item);
+    const SampleItem* t = set()->currentItem();
+    ASSERT(t);
+    SampleItem* t2 = t->clone();
+    return pushSample(t2);
 }
 
 QModelIndex SamplesQModel::createSample()
@@ -128,6 +122,20 @@ QModelIndex SamplesQModel::createSample()
     return indexForItem(t);
 }
 
+QModelIndex SamplesQModel::pushSample(SampleItem* t)
+{
+    if (!t)
+        return {};
+    const size_t row = set()->size();
+    beginInsertRows({}, row, row);
+    set()->push_back(t);
+    endInsertRows();
+
+    emit set()->setChanged();
+
+    return createIndex(row, 0);
+}
+
 QModelIndex SamplesQModel::createSampleFromExamples(const QString& className, const QString& title,
                                                     const QString& description)
 {
diff --git a/GUI/View/List/SamplesQModel.h b/GUI/View/List/SamplesQModel.h
index 17dadc98505..54986f0a745 100644
--- a/GUI/View/List/SamplesQModel.h
+++ b/GUI/View/List/SamplesQModel.h
@@ -34,11 +34,9 @@ public:
     const SampleItem* itemForIndex(const QModelIndex& index) const;
     QModelIndex indexForItem(SampleItem* item) const;
 
-    //! Remove the given sample. nullptr is allowed.
-    void removeSample(SampleItem* item);
-
-    //! Copy the given sample.
-    QModelIndex copySample(SampleItem* item);
+    void removeSample();
+    QModelIndex copySample();
+    QModelIndex pushSample(SampleItem*);
 
     //! Create a new sample (sample) and return the index of it.
     QModelIndex createSample();
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 739c45026f0..51e78045471 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -29,6 +29,7 @@
 #include "GUI/View/Realspace/RealspaceWidget.h"
 #include "GUI/View/Sample/SampleEditor.h"
 #include "GUI/View/Sample/ScriptPanel.h"
+#include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/StyledToolbar.h"
 #include <QBoxLayout>
 #include <QCheckBox>
@@ -52,6 +53,7 @@ SampleView::SampleView()
     auto* toolbar = new StyledToolbar;
     layout->addWidget(toolbar);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    setToolbarActions(toolbar);
 
     // Everything below
     auto* hLayout = new QHBoxLayout;
@@ -94,7 +96,38 @@ SampleView::SampleView()
         m_realspace_panel->setMaximumHeight(QWIDGETSIZE_MAX);
     });
 
-    //... Toolbar actions
+    //... Finish
+
+    connect(m_qlistview, &SamplesQListView::currentSampleChanged, editor,
+            &SampleEditor::setCurrentSample);
+
+    connect(m_qlistview, &SamplesQListView::currentSampleChanged,
+            [&](SampleItem* m) { onRequestViewInRealspace(m); });
+
+    connect(m_qlistview, &SamplesQListView::currentSampleChanged, scriptPanel,
+            &ScriptPanel::setCurrentSample);
+
+    connect(editor, &SampleEditor::modified, scriptPanel, &ScriptPanel::onSampleModified);
+
+    connect(editor, &SampleEditor::requestViewInRealspace, this,
+            &SampleView::onRequestViewInRealspace);
+
+    connect(editor, &SampleEditor::aboutToRemoveItem, this, &SampleView::onAboutToRemoveItem);
+
+    connect(editor, &SampleEditor::modified, m_realspace_panel->widget(),
+            &RealspaceWidget::updateScene);
+
+    connect(editor, &SampleEditor::modified, gDoc.get(), &ProjectDocument::setModified);
+}
+
+SampleView::~SampleView()
+{
+    saveSplitterPos();
+}
+
+void SampleView::setToolbarActions(QToolBar* toolbar)
+{
+    //... New sample action
 
     auto* new_sample_action = new QAction("New", this);
     new_sample_action->setIcon(QIcon(":/images/shape-square-plus.svg"));
@@ -104,6 +137,18 @@ SampleView::SampleView()
     connect(new_sample_action, &QAction::triggered, m_qlistview,
             &SamplesQListView::createNewSample);
 
+    //... Copy and remove actions
+
+    m_rm_action = ActionFactory::createRemoveAction("sample", this);
+    toolbar->addAction(m_rm_action);
+    connect(m_rm_action, &QAction::triggered, m_qlistmodel, &SamplesQModel::removeSample);
+
+    m_cp_action = ActionFactory::createCopyAction("sample", this);
+    toolbar->addAction(m_cp_action);
+    connect(m_cp_action, &QAction::triggered, m_qlistmodel, &SamplesQModel::copySample);
+
+    //... Save and load actions
+
 #ifdef BORNAGAIN_PYTHON
     auto* import_sample_action = new QAction("Import", this);
     import_sample_action->setIcon(QIcon(":/images/import.svg"));
@@ -134,34 +179,6 @@ SampleView::SampleView()
             m_qlistview->createSampleFromLibrary(exampleName, title, description);
         });
     }
-
-    //... Finish
-
-    connect(m_qlistview, &SamplesQListView::currentSampleChanged, editor,
-            &SampleEditor::setCurrentSample);
-
-    connect(m_qlistview, &SamplesQListView::currentSampleChanged,
-            [&](SampleItem* m) { onRequestViewInRealspace(m); });
-
-    connect(m_qlistview, &SamplesQListView::currentSampleChanged, scriptPanel,
-            &ScriptPanel::setCurrentSample);
-
-    connect(editor, &SampleEditor::modified, scriptPanel, &ScriptPanel::onSampleModified);
-
-    connect(editor, &SampleEditor::requestViewInRealspace, this,
-            &SampleView::onRequestViewInRealspace);
-
-    connect(editor, &SampleEditor::aboutToRemoveItem, this, &SampleView::onAboutToRemoveItem);
-
-    connect(editor, &SampleEditor::modified, m_realspace_panel->widget(),
-            &RealspaceWidget::updateScene);
-
-    connect(editor, &SampleEditor::modified, gDoc.get(), &ProjectDocument::setModified);
-}
-
-SampleView::~SampleView()
-{
-    saveSplitterPos();
 }
 
 void SampleView::applySplitterPos()
diff --git a/GUI/View/Views/SampleView.h b/GUI/View/Views/SampleView.h
index 16db6081e34..910a0dedabb 100644
--- a/GUI/View/Views/SampleView.h
+++ b/GUI/View/Views/SampleView.h
@@ -15,10 +15,11 @@
 #ifndef BORNAGAIN_GUI_VIEW_VIEWS_SAMPLEVIEW_H
 #define BORNAGAIN_GUI_VIEW_VIEWS_SAMPLEVIEW_H
 
-#include <QShowEvent>
+#include <QAction>
 #include <QWidget>
 
 class Item3D;
+class QToolBar;
 class RealspacePanel;
 class SamplesQListView;
 class SamplesQModel;
@@ -30,9 +31,8 @@ public:
     ~SampleView();
 
 private:
-    //! Show the item in the real space view
-    //!
-    //! If the real space view is not visible at the moment, it will be shown.
+    void setToolbarActions(QToolBar* toolbar);
+    void updateActions();
     void onRequestViewInRealspace(Item3D* item);
 
     void onAboutToRemoveItem(Item3D* item);
@@ -43,6 +43,9 @@ private:
     SamplesQModel* m_qlistmodel;
     SamplesQListView* m_qlistview;
     RealspacePanel* m_realspace_panel;
+
+    QAction* m_rm_action;
+    QAction* m_cp_action;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_VIEWS_SAMPLEVIEW_H
-- 
GitLab


From 98852285a70502562dd10c7f1a9dcbeed915400d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 10:18:59 +0100
Subject: [PATCH 089/108] rm include

---
 GUI/Model/Sample/SamplesSet.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/Model/Sample/SamplesSet.cpp b/GUI/Model/Sample/SamplesSet.cpp
index 8dbfad6678f..e885aa3381e 100644
--- a/GUI/Model/Sample/SamplesSet.cpp
+++ b/GUI/Model/Sample/SamplesSet.cpp
@@ -16,7 +16,6 @@
 #include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Support/XML/Backup.h"
 #include "GUI/Support/XML/UtilXML.h"
-#include <QApplication>
 
 namespace {
 namespace Tag {
-- 
GitLab


From cd2cc9e41dce280cdc359edba5cb9fff08a40b79 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 10:22:21 +0100
Subject: [PATCH 090/108] Samples: colors as for instruments

---
 GUI/View/List/SamplesQListView.cpp | 2 +-
 GUI/View/List/SamplesQModel.cpp    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index fc1d20b9e07..d165977daaa 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -30,7 +30,7 @@ SamplesQListView::SamplesQListView(SamplesQModel* model)
     setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
 
     setModel(m_model);
-    setSelectionMode(QAbstractItemView::SingleSelection);
+    setSelectionMode(QAbstractItemView::NoSelection);
 
     setItemDelegate(new ListItemDelegate(this));
 
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 45c281acd28..6d36a9a6ac9 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -59,7 +59,7 @@ QVariant SamplesQModel::data(const QModelIndex& index, int role) const
     case Qt::ToolTipRole:
         return t->description();
     case Qt::BackgroundRole:
-        return row == set()->currentIndex() ? QColor(Qt::green) : QColor(Qt::magenta);
+        return row == set()->currentIndex() ? QColor(Qt::cyan) : QColor(Qt::white);
     default:
         return {};
     }
-- 
GitLab


From 3fa017e41293f9df85e32a4019eeadd731fb6a16 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 10:35:37 +0100
Subject: [PATCH 091/108] create new sample: now in SampleView

---
 GUI/View/List/SamplesQListView.cpp |  7 -------
 GUI/View/List/SamplesQListView.h   |  1 -
 GUI/View/List/SamplesQModel.cpp    | 17 -----------------
 GUI/View/List/SamplesQModel.h      |  3 ---
 GUI/View/Views/SampleView.cpp      |  6 ++++--
 5 files changed, 4 insertions(+), 30 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index d165977daaa..30bfae0b18e 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -38,13 +38,6 @@ SamplesQListView::SamplesQListView(SamplesQModel* model)
             &SamplesQListView::onCurrentChanged);
 }
 
-void SamplesQListView::createNewSample()
-{
-    const QModelIndex newIndex = m_model->createSample();
-    setCurrentIndex(newIndex);
-    gDoc->setModified();
-}
-
 void SamplesQListView::createSampleFromLibrary(const QString& classname, const QString& title,
                                                const QString& description)
 {
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index e4f62497479..c1897968491 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,7 +26,6 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView(SamplesQModel*);
 
-    void createNewSample();
     void createSampleFromLibrary(const QString& classname, const QString& title,
                                  const QString& description);
     void importSampleFromPython();
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 6d36a9a6ac9..787393f1a5e 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -105,23 +105,6 @@ QModelIndex SamplesQModel::copySample()
     return pushSample(t2);
 }
 
-QModelIndex SamplesQModel::createSample()
-{
-    const QStringList existingNames = set()->sampleNames();
-
-    auto* t = new SampleItem;
-    t->setName(GUI::Util::String::suggestName(existingNames, "Sample"));
-    t->addStandardMaterials();
-
-    const int row = set()->size();
-
-    beginInsertRows(QModelIndex(), row, row);
-    set()->push_back(t);
-    endInsertRows();
-
-    return indexForItem(t);
-}
-
 QModelIndex SamplesQModel::pushSample(SampleItem* t)
 {
     if (!t)
diff --git a/GUI/View/List/SamplesQModel.h b/GUI/View/List/SamplesQModel.h
index 54986f0a745..6dec1c5cb54 100644
--- a/GUI/View/List/SamplesQModel.h
+++ b/GUI/View/List/SamplesQModel.h
@@ -38,9 +38,6 @@ public:
     QModelIndex copySample();
     QModelIndex pushSample(SampleItem*);
 
-    //! Create a new sample (sample) and return the index of it.
-    QModelIndex createSample();
-
     //! Create sample from list of built-in examples.
     //!
     //! Returns invalid index if anything went wrong.
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 51e78045471..b7057c0dc62 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -134,8 +134,10 @@ void SampleView::setToolbarActions(QToolBar* toolbar)
     new_sample_action->setToolTip("Create new sample");
     toolbar->addAction(new_sample_action);
 
-    connect(new_sample_action, &QAction::triggered, m_qlistview,
-            &SamplesQListView::createNewSample);
+    connect(new_sample_action, &QAction::triggered,
+            [this] { m_qlistmodel->pushSample(new SampleItem);
+		// TODO call new_item->addStandardMaterials() ??
+	    });
 
     //... Copy and remove actions
 
-- 
GitLab


From 3c0c7cbbb5c1edb3ec17257b456f428b8eecdd98 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 11:16:19 +0100
Subject: [PATCH 092/108] import sample from Py: now in SampleView

---
 GUI/View/List/SamplesQListView.cpp | 11 -----------
 GUI/View/List/SamplesQListView.h   |  1 -
 GUI/View/List/SamplesQModel.cpp    | 19 -------------------
 GUI/View/List/SamplesQModel.h      |  7 -------
 GUI/View/Views/InstrumentView.cpp  |  4 ++--
 GUI/View/Views/SampleView.cpp      |  8 ++++----
 6 files changed, 6 insertions(+), 44 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 30bfae0b18e..25c7b89a1ff 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -48,17 +48,6 @@ void SamplesQListView::createSampleFromLibrary(const QString& classname, const Q
     }
 }
 
-void SamplesQListView::importSampleFromPython()
-{
-#ifdef BORNAGAIN_PYTHON
-    const QModelIndex newIndex = m_model->createSampleFromPython();
-    if (newIndex.isValid()) {
-        setCurrentIndex(newIndex);
-        gDoc->setModified();
-    }
-#endif
-}
-
 void SamplesQListView::onCurrentChanged(const QModelIndex& index)
 {
     gDoc->samplesModifier()->setCurrentIndex(index.row());
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index c1897968491..b5eea6f2362 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -28,7 +28,6 @@ public:
 
     void createSampleFromLibrary(const QString& classname, const QString& title,
                                  const QString& description);
-    void importSampleFromPython();
     void onCurrentChanged(const QModelIndex& index);
 signals:
     void currentSampleChanged(SampleItem* current);
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 787393f1a5e..62e80c24fc4 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -20,7 +20,6 @@
 #include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Model/Sample/SamplesSet.h"
 #include "GUI/Support/Util/String.h"
-#include "GUI/View/Manager/PyImportAssistant.h"
 #include "Sample/Multilayer/MultiLayer.h"
 #include <QColor>
 
@@ -136,21 +135,3 @@ QModelIndex SamplesQModel::createSampleFromExamples(const QString& className, co
 
     return indexForItem(t);
 }
-
-#ifdef BORNAGAIN_PYTHON
-QModelIndex SamplesQModel::createSampleFromPython()
-{
-    SampleItem* t = PyImportAssistant::importMultiLayer();
-    if (!t)
-        return {}; // any messages already shown to user
-    t->setDescription("Imported from python code");
-
-    const int row = set()->size();
-
-    beginInsertRows(QModelIndex(), row, row);
-    set()->push_back(t);
-    endInsertRows();
-
-    return indexForItem(t);
-}
-#endif
diff --git a/GUI/View/List/SamplesQModel.h b/GUI/View/List/SamplesQModel.h
index 6dec1c5cb54..7ee6954e34c 100644
--- a/GUI/View/List/SamplesQModel.h
+++ b/GUI/View/List/SamplesQModel.h
@@ -44,13 +44,6 @@ public:
     QModelIndex createSampleFromExamples(const QString& className, const QString& title,
                                          const QString& description);
 
-#ifdef BORNAGAIN_PYTHON
-    //! Create sample from an imported python code.
-    //!
-    //! Returns invalid index if anything went wrong.
-    QModelIndex createSampleFromPython();
-#endif
-
 private:
     SamplesSet* set();
     const SamplesSet* set() const;
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index e3560237972..641a7ac40ef 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -111,14 +111,14 @@ void InstrumentView::setToolbarActions(QToolBar* toolbar)
 
     //... Save and load actions
 
-    m_save_action = new QAction("Store in library", this);
+    m_save_action = new QAction("Save as XML", this);
     m_save_action->setIcon(QIcon(":/images/library.svg"));
     m_save_action->setToolTip("Store instrument in library");
     toolbar->addAction(m_save_action);
     connect(m_save_action, &QAction::triggered,
             [] { RW::saveComponentToXML("instrument", gDoc->instruments()->currentItem()); });
 
-    m_load_action = new QAction("Choose from library", this);
+    m_load_action = new QAction("Load from XML", this);
     m_load_action->setIcon(QIcon(":/images/library.svg"));
     m_load_action->setToolTip("Load an instrument from the instrument library");
     toolbar->addAction(m_load_action);
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index b7057c0dc62..570a81e13d8 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -25,6 +25,7 @@
 #include "GUI/View/Layout/mainwindow_constants.h"
 #include "GUI/View/List/SamplesQListView.h"
 #include "GUI/View/List/SamplesQModel.h"
+#include "GUI/View/Manager/PyImportAssistant.h"
 #include "GUI/View/Realspace/RealspacePanel.h"
 #include "GUI/View/Realspace/RealspaceWidget.h"
 #include "GUI/View/Sample/SampleEditor.h"
@@ -152,14 +153,13 @@ void SampleView::setToolbarActions(QToolBar* toolbar)
     //... Save and load actions
 
 #ifdef BORNAGAIN_PYTHON
-    auto* import_sample_action = new QAction("Import", this);
+    auto* import_sample_action = new QAction("Import Py", this);
     import_sample_action->setIcon(QIcon(":/images/import.svg"));
     import_sample_action->setToolTip(
         "Import sample from a Python script that contains a function that returns a multi-layer");
     toolbar->addAction(import_sample_action);
-
-    connect(import_sample_action, &QAction::triggered, m_qlistview,
-            &SamplesQListView::importSampleFromPython);
+    connect(import_sample_action, &QAction::triggered, [this]
+	{ m_qlistmodel->pushSample(PyImportAssistant::importMultiLayer()); });
 #endif
 
     auto* choose_from_library_action = new QAction("Examples", this);
-- 
GitLab


From 5edea6875de3a95604c0df3b60a131fa2959de31 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 11:20:21 +0100
Subject: [PATCH 093/108] load example: now in SampleView

---
 GUI/View/List/SamplesQListView.cpp | 10 ----------
 GUI/View/List/SamplesQListView.h   |  2 --
 GUI/View/List/SamplesQModel.cpp    | 20 --------------------
 GUI/View/List/SamplesQModel.h      |  6 ------
 GUI/View/Views/SampleView.cpp      |  7 ++++++-
 5 files changed, 6 insertions(+), 39 deletions(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 25c7b89a1ff..00c0495731b 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -38,16 +38,6 @@ SamplesQListView::SamplesQListView(SamplesQModel* model)
             &SamplesQListView::onCurrentChanged);
 }
 
-void SamplesQListView::createSampleFromLibrary(const QString& classname, const QString& title,
-                                               const QString& description)
-{
-    const QModelIndex newIndex = m_model->createSampleFromExamples(classname, title, description);
-    if (newIndex.isValid()) {
-        setCurrentIndex(newIndex);
-        gDoc->setModified();
-    }
-}
-
 void SamplesQListView::onCurrentChanged(const QModelIndex& index)
 {
     gDoc->samplesModifier()->setCurrentIndex(index.row());
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index b5eea6f2362..414261068a0 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,8 +26,6 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView(SamplesQModel*);
 
-    void createSampleFromLibrary(const QString& classname, const QString& title,
-                                 const QString& description);
     void onCurrentChanged(const QModelIndex& index);
 signals:
     void currentSampleChanged(SampleItem* current);
diff --git a/GUI/View/List/SamplesQModel.cpp b/GUI/View/List/SamplesQModel.cpp
index 62e80c24fc4..268389661ae 100644
--- a/GUI/View/List/SamplesQModel.cpp
+++ b/GUI/View/List/SamplesQModel.cpp
@@ -14,8 +14,6 @@
 
 #include "GUI/View/List/SamplesQModel.h"
 #include "Base/Util/Assert.h"
-#include "GUI/Model/FromCore/GUIExamplesFactory.h"
-#include "GUI/Model/FromCore/ItemizeSample.h"
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Model/Sample/SamplesSet.h"
@@ -117,21 +115,3 @@ QModelIndex SamplesQModel::pushSample(SampleItem* t)
 
     return createIndex(row, 0);
 }
-
-QModelIndex SamplesQModel::createSampleFromExamples(const QString& className, const QString& title,
-                                                    const QString& description)
-{
-    auto* t = dynamic_cast<SampleItem*>(GUI::ExamplesFactory::itemizeSample(className));
-    if (!t)
-        return {};
-    t->setName(title);
-    t->setDescription(description);
-
-    const int row = set()->size();
-
-    beginInsertRows(QModelIndex(), row, row);
-    set()->push_back(t);
-    endInsertRows();
-
-    return indexForItem(t);
-}
diff --git a/GUI/View/List/SamplesQModel.h b/GUI/View/List/SamplesQModel.h
index 7ee6954e34c..a7295af2928 100644
--- a/GUI/View/List/SamplesQModel.h
+++ b/GUI/View/List/SamplesQModel.h
@@ -38,12 +38,6 @@ public:
     QModelIndex copySample();
     QModelIndex pushSample(SampleItem*);
 
-    //! Create sample from list of built-in examples.
-    //!
-    //! Returns invalid index if anything went wrong.
-    QModelIndex createSampleFromExamples(const QString& className, const QString& title,
-                                         const QString& description);
-
 private:
     SamplesSet* set();
     const SamplesSet* set() const;
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 570a81e13d8..695aaa5a1d8 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -178,7 +178,12 @@ void SampleView::setToolbarActions(QToolBar* toolbar)
         auto* action = import_menu->addAction(icon, title);
         action->setToolTip(description);
         connect(action, &QAction::triggered, [this, exampleName, title, description] {
-            m_qlistview->createSampleFromLibrary(exampleName, title, description);
+	    SampleItem* t = GUI::ExamplesFactory::itemizeSample(exampleName);
+	    if (!t)
+		return;
+	    t->setName(title);
+	    t->setDescription(description);
+            m_qlistmodel->pushSample(t);
         });
     }
 }
-- 
GitLab


From 8387a77923ad933abe3e3aaf696e530dfbfc5257 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 12:01:09 +0100
Subject: [PATCH 094/108] Instruments - context settings

---
 GUI/View/List/InstrumentsQListView.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 854ac6d1a7b..4aa97f86389 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -37,6 +37,4 @@ InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
         setCurrentIndex(model->index(gDoc->instruments()->currentIndex(), 0));
         repaint();
     });
-
-    setContextMenuPolicy(Qt::ActionsContextMenu);
 }
-- 
GitLab


From 728e58ba28349574f7804cd6a9f6d43ab503a17d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 12:45:34 +0100
Subject: [PATCH 095/108] rm include

---
 GUI/View/Views/InstrumentView.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 641a7ac40ef..1d51b6fd3f6 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -31,7 +31,6 @@
 #include <QFormLayout>
 #include <QLineEdit>
 #include <QTextEdit>
-#include <iostream>
 
 InstrumentView::InstrumentView()
     : m_qlistmodel(new InstrumentsQModel(this))
-- 
GitLab


From a2d0039bcedaa393e68c12187756a9fd2e9d5f90 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 12:54:00 +0100
Subject: [PATCH 096/108] rm include

---
 GUI/View/Sample/SampleEditorController.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GUI/View/Sample/SampleEditorController.cpp b/GUI/View/Sample/SampleEditorController.cpp
index fa6fc9313af..c2a25bc223b 100644
--- a/GUI/View/Sample/SampleEditorController.cpp
+++ b/GUI/View/Sample/SampleEditorController.cpp
@@ -16,7 +16,6 @@
 #include "Base/Util/Assert.h"
 #include "Base/Util/Vec.h"
 #include "GUI/Model/Material/MaterialsSet.h"
-#include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/Model/Sample/CompoundItem.h"
 #include "GUI/Model/Sample/CoreAndShellItem.h"
 #include "GUI/Model/Sample/InterferenceItems.h"
@@ -46,6 +45,7 @@ void SampleEditorController::setSampleForm(SampleForm* view)
 {
     m_sample_form = view;
 }
+
 void SampleEditorController::addLayerItem(LayerItem* before)
 {
     const int i = (before != nullptr) ? Vec::indexOfPtr(before, m_sample_item->layerItems())
-- 
GitLab


From fea30e55a87efc5dc6c0c7149a325d9e3ece71bd Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 14:41:11 +0100
Subject: [PATCH 097/108] mv predefined colors to GUI/Support (cloned
 GUI/View/Sample/LayerEditorUtil -> GUI/Support/Style/PredefinedColors)

---
 GUI/Support/Style/PredefinedColors.cpp | 24 ++++++++++++++++++++++
 GUI/Support/Style/PredefinedColors.h   | 28 ++++++++++++++++++++++++++
 GUI/View/Sample/LayerForm.cpp          |  3 ++-
 GUI/View/Sample/SampleEditor.cpp       | 14 ++++++-------
 4 files changed, 60 insertions(+), 9 deletions(-)
 create mode 100644 GUI/Support/Style/PredefinedColors.cpp
 create mode 100644 GUI/Support/Style/PredefinedColors.h

diff --git a/GUI/Support/Style/PredefinedColors.cpp b/GUI/Support/Style/PredefinedColors.cpp
new file mode 100644
index 00000000000..ef45fd4e72a
--- /dev/null
+++ b/GUI/Support/Style/PredefinedColors.cpp
@@ -0,0 +1,24 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Support/Style/PredefinedColors.cpp
+//! @brief     Implements namespace GUI::Colors.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2021
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#include "GUI/Support/Style/PredefinedColors.h"
+
+const QVector<QColor>& GUI::Colors::layerDefaults()
+{
+    static QVector<QColor> colors = {QColor(230, 255, 213), QColor(194, 252, 240),
+                                     QColor(239, 228, 176), QColor(200, 191, 231),
+                                     QColor(253, 205, 193), QColor(224, 193, 253)};
+
+    return colors;
+}
diff --git a/GUI/Support/Style/PredefinedColors.h b/GUI/Support/Style/PredefinedColors.h
new file mode 100644
index 00000000000..77654e8a825
--- /dev/null
+++ b/GUI/Support/Style/PredefinedColors.h
@@ -0,0 +1,28 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Support/Style/PredefinedColors.h
+//! @brief     Defines namespace GUI::Colors.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2021
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#ifndef BORNAGAIN_GUI_SUPPORT_STYLE_PREDEFINEDCOLORS_H
+#define BORNAGAIN_GUI_SUPPORT_STYLE_PREDEFINEDCOLORS_H
+
+#include <QColor>
+#include <QVector>
+
+//! Utility functions to support layer oriented sample editor
+namespace GUI::Colors {
+
+const QVector<QColor>& layerDefaults();
+
+} // namespace GUI::Colors
+
+#endif // BORNAGAIN_GUI_SUPPORT_STYLE_PREDEFINEDCOLORS_H
diff --git a/GUI/View/Sample/LayerForm.cpp b/GUI/View/Sample/LayerForm.cpp
index b7539847fe6..a1605c5ec12 100644
--- a/GUI/View/Sample/LayerForm.cpp
+++ b/GUI/View/Sample/LayerForm.cpp
@@ -19,6 +19,7 @@
 #include "GUI/Model/Material/MaterialsSet.h"
 #include "GUI/Model/Sample/LayerItem.h"
 #include "GUI/Model/Sample/SampleItem.h"
+#include "GUI/Support/Style/PredefinedColors.h"
 #include "GUI/View/Numeric/NumWidgetUtil.h"
 #include "GUI/View/Sample/HeinzFormLayout.h"
 #include "GUI/View/Sample/MaterialInplaceForm.h"
@@ -52,7 +53,7 @@ LayerForm::LayerForm(QWidget* parent, LayerItem* layerItem, SampleEditorControll
         chooseColorAction->setMenu(menu);
         addTitleAction(chooseColorAction);
 
-        for (const auto& col : GUI::Util::Layer::predefinedLayerColors()) {
+        for (const auto& col : GUI::Colors::layerDefaults()) {
             QPixmap p(64, 64);
             p.fill(col);
             auto* ca = menu->addAction(QIcon(p), "");
diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index 260fdd78caa..e41d561303b 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -16,8 +16,8 @@
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/Model/Sample/LayerItem.h"
 #include "GUI/Model/Sample/SampleItem.h"
+#include "GUI/Support/Style/PredefinedColors.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
-#include "GUI/View/Sample/LayerEditorUtil.h"
 #include "GUI/View/Sample/SampleEditorController.h"
 #include "GUI/View/Sample/SampleForm.h"
 #include "GUI/View/Widget/StyledToolbar.h"
@@ -72,14 +72,12 @@ void SampleEditor::createLayerColors() // #baLayerEditor move to better place
     if (!m_current_sample)
         return;
 
+    const auto& colors = GUI::Colors::layerDefaults();
+
     int col = 0;
     for (auto* l : m_current_sample->layerItems()) {
-        if (l->color().isValid())
-            continue;
-
-        l->setColor(GUI::Util::Layer::predefinedLayerColors()[col]);
-        col++;
-        if (col == GUI::Util::Layer::predefinedLayerColors().size())
-            col = 0;
+        if (!l->color().isValid())
+	    l->setColor(colors[col]);
+        col = (col + 1) % colors.size();
     }
 }
-- 
GitLab


From dc8c3fbf4787b8ee872da0a2db2ea72ea6dfe3f9 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 14:52:34 +0100
Subject: [PATCH 098/108] + SampleItem::updateDefaultLayerColors

---
 GUI/Model/Sample/SampleItem.cpp  | 13 +++++++++++++
 GUI/Model/Sample/SampleItem.h    |  2 ++
 GUI/View/Sample/SampleEditor.cpp | 14 ++------------
 3 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/GUI/Model/Sample/SampleItem.cpp b/GUI/Model/Sample/SampleItem.cpp
index dd8cbb8e452..d1a874ad614 100644
--- a/GUI/Model/Sample/SampleItem.cpp
+++ b/GUI/Model/Sample/SampleItem.cpp
@@ -15,6 +15,7 @@
 #include "GUI/Model/Sample/SampleItem.h"
 #include "Base/Util/Vec.h"
 #include "GUI/Model/Sample/LayerItem.h"
+#include "GUI/Support/Style/PredefinedColors.h"
 #include "GUI/Support/XML/Backup.h"
 #include "GUI/Support/XML/UtilXML.h"
 #include <QXmlStreamWriter>
@@ -215,3 +216,15 @@ void SampleItem::readFrom(QXmlStreamReader* r)
             r->skipCurrentElement();
     }
 }
+
+void SampleItem::updateDefaultLayerColors()
+{
+    const auto& colors = GUI::Colors::layerDefaults();
+
+    int col = 0;
+    for (auto* l : layerItems()) {
+        if (!l->color().isValid())
+	    l->setColor(colors[col]);
+        col = (col + 1) % colors.size();
+    }
+}
diff --git a/GUI/Model/Sample/SampleItem.h b/GUI/Model/Sample/SampleItem.h
index f5708cfd504..4ad7e39cae0 100644
--- a/GUI/Model/Sample/SampleItem.h
+++ b/GUI/Model/Sample/SampleItem.h
@@ -63,6 +63,8 @@ public:
     MaterialsSet& materialModel() { return m_materials; }
     const MaterialsSet& materialModel() const { return m_materials; }
 
+    void updateDefaultLayerColors();
+
     bool expandInfo = true;
 
 private:
diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index e41d561303b..364234a8f05 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -16,7 +16,6 @@
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/Model/Sample/LayerItem.h"
 #include "GUI/Model/Sample/SampleItem.h"
-#include "GUI/Support/Style/PredefinedColors.h"
 #include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Sample/SampleEditorController.h"
 #include "GUI/View/Sample/SampleForm.h"
@@ -69,15 +68,6 @@ void SampleEditor::setCurrentSample(SampleItem* sampleItem)
 
 void SampleEditor::createLayerColors() // #baLayerEditor move to better place
 {
-    if (!m_current_sample)
-        return;
-
-    const auto& colors = GUI::Colors::layerDefaults();
-
-    int col = 0;
-    for (auto* l : m_current_sample->layerItems()) {
-        if (!l->color().isValid())
-	    l->setColor(colors[col]);
-        col = (col + 1) % colors.size();
-    }
+    if (m_current_sample)
+        m_current_sample->updateDefaultLayerColors();
 }
-- 
GitLab


From 7c3bbd5dfd26a4cfbbb963c8d804ed3782be0b27 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 14:53:14 +0100
Subject: [PATCH 099/108] rm trivialized method

---
 GUI/View/Sample/SampleEditor.cpp | 9 ++-------
 GUI/View/Sample/SampleEditor.h   | 2 --
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index 364234a8f05..c4a9aedcf44 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -58,16 +58,11 @@ void SampleEditor::setCurrentSample(SampleItem* sampleItem)
     connect(ec, &SampleEditorController::aboutToRemoveItem, this, &SampleEditor::aboutToRemoveItem);
     connect(ec, &SampleEditorController::modified, this, &SampleEditor::modified);
 
-    createLayerColors();
+    if (m_current_sample)
+        m_current_sample->updateDefaultLayerColors();
 
     m_current_sample_widget = new SampleForm(m_current_sample, ec);
     ec->setSampleForm(m_current_sample_widget);
     m_current_sample_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
     QScrollArea::setWidget(m_current_sample_widget);
 }
-
-void SampleEditor::createLayerColors() // #baLayerEditor move to better place
-{
-    if (m_current_sample)
-        m_current_sample->updateDefaultLayerColors();
-}
diff --git a/GUI/View/Sample/SampleEditor.h b/GUI/View/Sample/SampleEditor.h
index e4786ab810a..ab970543384 100644
--- a/GUI/View/Sample/SampleEditor.h
+++ b/GUI/View/Sample/SampleEditor.h
@@ -38,8 +38,6 @@ signals:
     void modified();
 
 private:
-    void createLayerColors();
-
     SampleForm* m_current_sample_widget;
     SampleItem* m_current_sample = nullptr;
     QMap<SampleItem*, SampleEditorController*> m_edit_controllers;
-- 
GitLab


From 778504e9e5e53eaa5a28f930d2274993c97569f3 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 14:58:04 +0100
Subject: [PATCH 100/108] SampleEditor controller: map -> unique_ptr

---
 GUI/View/Sample/SampleEditor.cpp | 10 ++--------
 GUI/View/Sample/SampleEditor.h   |  4 ++--
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index c4a9aedcf44..0eb7c02c7bf 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -33,16 +33,11 @@ SampleEditor::SampleEditor()
 
 SampleEditor::~SampleEditor()
 {
-    qDeleteAll(m_edit_controllers.values());
 }
 
 void SampleEditor::setCurrentSample(SampleItem* sampleItem)
 {
-    if (m_current_sample != nullptr)
-        m_edit_controllers[m_current_sample]->setSampleForm(nullptr);
-
     m_current_sample_widget = nullptr;
-    delete QScrollArea::takeWidget();
 
     m_current_sample = sampleItem;
     if (m_current_sample == nullptr) {
@@ -50,9 +45,8 @@ void SampleEditor::setCurrentSample(SampleItem* sampleItem)
         return;
     }
 
-    if (!m_edit_controllers.contains(m_current_sample))
-        m_edit_controllers.insert(m_current_sample, new SampleEditorController(m_current_sample));
-    auto* ec = m_edit_controllers[m_current_sample];
+    m_edit_controller = std::make_unique<SampleEditorController>(m_current_sample);
+    auto* ec = m_edit_controller.get();
     connect(ec, &SampleEditorController::requestViewInRealspace, this,
             &SampleEditor::requestViewInRealspace);
     connect(ec, &SampleEditorController::aboutToRemoveItem, this, &SampleEditor::aboutToRemoveItem);
diff --git a/GUI/View/Sample/SampleEditor.h b/GUI/View/Sample/SampleEditor.h
index ab970543384..4cad7280da9 100644
--- a/GUI/View/Sample/SampleEditor.h
+++ b/GUI/View/Sample/SampleEditor.h
@@ -15,8 +15,8 @@
 #ifndef BORNAGAIN_GUI_VIEW_SAMPLE_SAMPLEEDITOR_H
 #define BORNAGAIN_GUI_VIEW_SAMPLE_SAMPLEEDITOR_H
 
-#include <QMap>
 #include <QScrollArea>
+#include <memory>
 
 class Item3D;
 class SampleEditorController;
@@ -40,7 +40,7 @@ signals:
 private:
     SampleForm* m_current_sample_widget;
     SampleItem* m_current_sample = nullptr;
-    QMap<SampleItem*, SampleEditorController*> m_edit_controllers;
+    std::unique_ptr<SampleEditorController> m_edit_controller;
 };
 
 
-- 
GitLab


From 513e624b37343a514f1fab29ab428330ced95358 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:00:14 +0100
Subject: [PATCH 101/108] cleanup

---
 GUI/View/Sample/SampleEditor.cpp | 12 +++++-------
 GUI/View/Sample/SampleEditor.h   |  1 -
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index 0eb7c02c7bf..315264487ca 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -35,27 +35,25 @@ SampleEditor::~SampleEditor()
 {
 }
 
-void SampleEditor::setCurrentSample(SampleItem* sampleItem)
+void SampleEditor::setCurrentSample(SampleItem* t)
 {
     m_current_sample_widget = nullptr;
 
-    m_current_sample = sampleItem;
-    if (m_current_sample == nullptr) {
+    if (t == nullptr) {
         QScrollArea::setWidget(new QWidget());
         return;
     }
 
-    m_edit_controller = std::make_unique<SampleEditorController>(m_current_sample);
+    m_edit_controller = std::make_unique<SampleEditorController>(t);
     auto* ec = m_edit_controller.get();
     connect(ec, &SampleEditorController::requestViewInRealspace, this,
             &SampleEditor::requestViewInRealspace);
     connect(ec, &SampleEditorController::aboutToRemoveItem, this, &SampleEditor::aboutToRemoveItem);
     connect(ec, &SampleEditorController::modified, this, &SampleEditor::modified);
 
-    if (m_current_sample)
-        m_current_sample->updateDefaultLayerColors();
+    t->updateDefaultLayerColors();
 
-    m_current_sample_widget = new SampleForm(m_current_sample, ec);
+    m_current_sample_widget = new SampleForm(t, ec);
     ec->setSampleForm(m_current_sample_widget);
     m_current_sample_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
     QScrollArea::setWidget(m_current_sample_widget);
diff --git a/GUI/View/Sample/SampleEditor.h b/GUI/View/Sample/SampleEditor.h
index 4cad7280da9..233c88cc4b4 100644
--- a/GUI/View/Sample/SampleEditor.h
+++ b/GUI/View/Sample/SampleEditor.h
@@ -39,7 +39,6 @@ signals:
 
 private:
     SampleForm* m_current_sample_widget;
-    SampleItem* m_current_sample = nullptr;
     std::unique_ptr<SampleEditorController> m_edit_controller;
 };
 
-- 
GitLab


From 649961d2e5916b295fa64db616a4dcf9124be13d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:01:02 +0100
Subject: [PATCH 102/108] .

---
 GUI/View/Sample/SampleEditor.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index 315264487ca..86049cc7cce 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -31,9 +31,7 @@ SampleEditor::SampleEditor()
     QScrollArea::setWidget(new QWidget());
 }
 
-SampleEditor::~SampleEditor()
-{
-}
+SampleEditor::~SampleEditor() = default;
 
 void SampleEditor::setCurrentSample(SampleItem* t)
 {
-- 
GitLab


From a0fc58d5234360cfd503d0cd148c45c1fbbd37f0 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:09:01 +0100
Subject: [PATCH 103/108] member -> local var

---
 GUI/View/Sample/SampleEditor.cpp | 11 ++++-------
 GUI/View/Sample/SampleEditor.h   |  2 --
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index 86049cc7cce..f1f3b68672d 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -25,7 +25,6 @@
 #include <QPushButton>
 
 SampleEditor::SampleEditor()
-    : m_current_sample_widget(nullptr)
 {
     QScrollArea::setWidgetResizable(true);
     QScrollArea::setWidget(new QWidget());
@@ -35,8 +34,6 @@ SampleEditor::~SampleEditor() = default;
 
 void SampleEditor::setCurrentSample(SampleItem* t)
 {
-    m_current_sample_widget = nullptr;
-
     if (t == nullptr) {
         QScrollArea::setWidget(new QWidget());
         return;
@@ -51,8 +48,8 @@ void SampleEditor::setCurrentSample(SampleItem* t)
 
     t->updateDefaultLayerColors();
 
-    m_current_sample_widget = new SampleForm(t, ec);
-    ec->setSampleForm(m_current_sample_widget);
-    m_current_sample_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
-    QScrollArea::setWidget(m_current_sample_widget);
+    auto* f = new SampleForm(t, ec);
+    ec->setSampleForm(f);
+    f->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+    QScrollArea::setWidget(f);
 }
diff --git a/GUI/View/Sample/SampleEditor.h b/GUI/View/Sample/SampleEditor.h
index 233c88cc4b4..cac47b67278 100644
--- a/GUI/View/Sample/SampleEditor.h
+++ b/GUI/View/Sample/SampleEditor.h
@@ -20,7 +20,6 @@
 
 class Item3D;
 class SampleEditorController;
-class SampleForm;
 class SampleItem;
 
 //! Sample editor with layer oriented presentation of a sample
@@ -38,7 +37,6 @@ signals:
     void modified();
 
 private:
-    SampleForm* m_current_sample_widget;
     std::unique_ptr<SampleEditorController> m_edit_controller;
 };
 
-- 
GitLab


From f68b8e558431c524b4748e8912244736300173f2 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:10:24 +0100
Subject: [PATCH 104/108] rm includes

---
 GUI/View/Sample/SampleEditor.cpp | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index f1f3b68672d..2e3370e3d80 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -14,15 +14,9 @@
 
 #include "GUI/View/Sample/SampleEditor.h"
 #include "GUI/Model/Project/ProjectDocument.h"
-#include "GUI/Model/Sample/LayerItem.h"
 #include "GUI/Model/Sample/SampleItem.h"
-#include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Sample/SampleEditorController.h"
 #include "GUI/View/Sample/SampleForm.h"
-#include "GUI/View/Widget/StyledToolbar.h"
-#include <QActionGroup>
-#include <QBoxLayout>
-#include <QPushButton>
 
 SampleEditor::SampleEditor()
 {
-- 
GitLab


From 2c11c206031d62afefe8f3bab4acfa3a8906e47e Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:13:26 +0100
Subject: [PATCH 105/108] NamedItem + c'tor(name); default name for SampleItem

---
 GUI/Model/Sample/SampleItem.cpp |  4 ++--
 GUI/Model/Type/NamedItem.h      |  4 ++++
 GUI/View/Views/SampleView.cpp   | 22 +++++++++++-----------
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/GUI/Model/Sample/SampleItem.cpp b/GUI/Model/Sample/SampleItem.cpp
index d1a874ad614..35324c00b04 100644
--- a/GUI/Model/Sample/SampleItem.cpp
+++ b/GUI/Model/Sample/SampleItem.cpp
@@ -35,8 +35,8 @@ const QString ExpandInfoGroupbox("ExpandInfoGroupbox");
 } // namespace
 
 SampleItem::SampleItem()
+    : NamedItem("Sample")
 {
-
     m_cross_correlation_length.init("Cross-correlation length (nm)",
                                     "Cross correlation length of roughnesses between interfaces",
                                     0.0, 5, RealLimits::nonnegative(), "cross");
@@ -224,7 +224,7 @@ void SampleItem::updateDefaultLayerColors()
     int col = 0;
     for (auto* l : layerItems()) {
         if (!l->color().isValid())
-	    l->setColor(colors[col]);
+            l->setColor(colors[col]);
         col = (col + 1) % colors.size();
     }
 }
diff --git a/GUI/Model/Type/NamedItem.h b/GUI/Model/Type/NamedItem.h
index d982eace4c5..ef088ba376c 100644
--- a/GUI/Model/Type/NamedItem.h
+++ b/GUI/Model/Type/NamedItem.h
@@ -21,6 +21,10 @@
 
 class NamedItem {
 public:
+    NamedItem(const QString& name = {})
+        : m_name(name)
+    {
+    }
     virtual ~NamedItem() = default;
 
     void setName(const QString& name) { m_name = name; }
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 695aaa5a1d8..3ee731469ea 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -135,10 +135,10 @@ void SampleView::setToolbarActions(QToolBar* toolbar)
     new_sample_action->setToolTip("Create new sample");
     toolbar->addAction(new_sample_action);
 
-    connect(new_sample_action, &QAction::triggered,
-            [this] { m_qlistmodel->pushSample(new SampleItem);
-		// TODO call new_item->addStandardMaterials() ??
-	    });
+    connect(new_sample_action, &QAction::triggered, [this] {
+        m_qlistmodel->pushSample(new SampleItem);
+        // TODO call new_item->addStandardMaterials() ??
+    });
 
     //... Copy and remove actions
 
@@ -158,8 +158,8 @@ void SampleView::setToolbarActions(QToolBar* toolbar)
     import_sample_action->setToolTip(
         "Import sample from a Python script that contains a function that returns a multi-layer");
     toolbar->addAction(import_sample_action);
-    connect(import_sample_action, &QAction::triggered, [this]
-	{ m_qlistmodel->pushSample(PyImportAssistant::importMultiLayer()); });
+    connect(import_sample_action, &QAction::triggered,
+            [this] { m_qlistmodel->pushSample(PyImportAssistant::importMultiLayer()); });
 #endif
 
     auto* choose_from_library_action = new QAction("Examples", this);
@@ -178,11 +178,11 @@ void SampleView::setToolbarActions(QToolBar* toolbar)
         auto* action = import_menu->addAction(icon, title);
         action->setToolTip(description);
         connect(action, &QAction::triggered, [this, exampleName, title, description] {
-	    SampleItem* t = GUI::ExamplesFactory::itemizeSample(exampleName);
-	    if (!t)
-		return;
-	    t->setName(title);
-	    t->setDescription(description);
+            SampleItem* t = GUI::ExamplesFactory::itemizeSample(exampleName);
+            if (!t)
+                return;
+            t->setName(title);
+            t->setDescription(description);
             m_qlistmodel->pushSample(t);
         });
     }
-- 
GitLab


From d6363174c55678baa9e9a9fe0aa4dc7f7d5d0c5e Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:38:02 +0100
Subject: [PATCH 106/108] sample view and signals like instrument

---
 GUI/View/List/InstrumentsQListView.cpp |  5 ++--
 GUI/View/List/SamplesQListView.cpp     | 33 ++++++++++++--------------
 GUI/View/List/SamplesQListView.h       |  4 ----
 GUI/View/Views/InstrumentView.cpp      |  8 +++----
 GUI/View/Views/SampleView.cpp          |  8 +++----
 5 files changed, 23 insertions(+), 35 deletions(-)

diff --git a/GUI/View/List/InstrumentsQListView.cpp b/GUI/View/List/InstrumentsQListView.cpp
index 4aa97f86389..128224a929c 100644
--- a/GUI/View/List/InstrumentsQListView.cpp
+++ b/GUI/View/List/InstrumentsQListView.cpp
@@ -20,12 +20,11 @@
 
 InstrumentsQListView::InstrumentsQListView(InstrumentsQModel* model)
 {
+    setMinimumWidth(200);
     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
-    setMovement(QListView::Static);
     setSelectionMode(QAbstractItemView::NoSelection);
-
-    setModel(model);
     setItemDelegate(new ListItemDelegate(this));
+    setModel(model);
 
     connect(this, &QListView::clicked, [this](const QModelIndex& qi) {
         gDoc->instrumentsModifier()->setCurrentIndex(qi.row());
diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index 00c0495731b..faeabb371b5 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -13,33 +13,30 @@
 //  ************************************************************************************************
 
 #include "GUI/View/List/SamplesQListView.h"
-#include "Base/Util/SysUtil.h"
 #include "GUI/Model/Project/ProjectDocument.h"
-#include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Model/Sample/SamplesSet.h"
-#include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/List/SamplesQModel.h"
-#include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/ListItemDelegate.h"
-#include <QAction>
 
 SamplesQListView::SamplesQListView(SamplesQModel* model)
-    : m_model(model)
 {
-    setMaximumWidth(200);
-    setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
-
-    setModel(m_model);
+    setMinimumWidth(200);
+    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
     setSelectionMode(QAbstractItemView::NoSelection);
-
     setItemDelegate(new ListItemDelegate(this));
+    setModel(model);
 
-    connect(selectionModel(), &QItemSelectionModel::currentChanged, this,
-            &SamplesQListView::onCurrentChanged);
-}
+    connect(this, &QListView::clicked, [this, model](const QModelIndex& qi) {
+        gDoc->samplesModifier()->setCurrentIndex(qi.row());
+        emit gDoc->samples()->setChanged();
+	emit currentSampleChanged(model->itemForIndex(qi));
+    });
 
-void SamplesQListView::onCurrentChanged(const QModelIndex& index)
-{
-    gDoc->samplesModifier()->setCurrentIndex(index.row());
-    emit currentSampleChanged(m_model->itemForIndex(index));
+    disconnect(gDoc->samples(), &SamplesSet::setChanged, nullptr, nullptr);
+    connect(gDoc->samples(), &SamplesSet::setChanged, [this, model] {
+        setCurrentIndex(model->index(gDoc->samples()->currentIndex(), 0));
+        repaint();
+    });
+
+    // TODO reinvestigate connect(selectionModel(), &QItemSelectionModel::currentChanged,
 }
diff --git a/GUI/View/List/SamplesQListView.h b/GUI/View/List/SamplesQListView.h
index 414261068a0..a0d4d6c4afe 100644
--- a/GUI/View/List/SamplesQListView.h
+++ b/GUI/View/List/SamplesQListView.h
@@ -26,12 +26,8 @@ class SamplesQListView : public QListView {
 public:
     SamplesQListView(SamplesQModel*);
 
-    void onCurrentChanged(const QModelIndex& index);
 signals:
     void currentSampleChanged(SampleItem* current);
-
-private:
-    SamplesQModel* m_model;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_LIST_SAMPLESQLISTVIEW_H
diff --git a/GUI/View/Views/InstrumentView.cpp b/GUI/View/Views/InstrumentView.cpp
index 1d51b6fd3f6..72fbdad3c7d 100644
--- a/GUI/View/Views/InstrumentView.cpp
+++ b/GUI/View/Views/InstrumentView.cpp
@@ -39,12 +39,11 @@ InstrumentView::InstrumentView()
 {
     auto* layout = new QVBoxLayout(this);
 
-    //... Top toolbar with action buttons "new ...instrument" etc
+    //... Top toolbar with action buttons
 
     auto* toolbar = new StyledToolbar;
     layout->addWidget(toolbar);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
-
     setToolbarActions(toolbar);
 
     //... Everything below top toolbar
@@ -52,12 +51,11 @@ InstrumentView::InstrumentView()
     auto* hLayout = new QHBoxLayout;
     layout->addLayout(hLayout);
 
-    // Left margin: instrument list
+    //... Left margin: instrument list
 
     hLayout->addWidget(m_qlistview);
-    m_qlistview->setMinimumWidth(200);
 
-    // Large widget: current instrument
+    //... Large block on the right: current instrument
 
     hLayout->addWidget(m_scroll_area);
     m_scroll_area->setWidgetResizable(true);
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 3ee731469ea..868bbf38be0 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -48,24 +48,22 @@ SampleView::SampleView()
     , m_realspace_panel(new RealspacePanel(this))
 {
     auto* layout = new QVBoxLayout(this);
-    layout->setContentsMargins(0, 0, 0, 0);
 
-    // Top toolbar with action buttons "new", "import", "example"
+    //... Top toolbar with action buttons "new", "import", "example"
     auto* toolbar = new StyledToolbar;
     layout->addWidget(toolbar);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
     setToolbarActions(toolbar);
 
-    // Everything below
+    //... Everything below top toolbar
     auto* hLayout = new QHBoxLayout;
     layout->addLayout(hLayout);
 
     //... Left margin: sample listing
 
     hLayout->addWidget(m_qlistview);
-    m_qlistview->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
 
-    //... Right block: sample editor and bottom panels
+    //... Large block on the right: sample editor and bottom panels
 
     auto* vSplitter = new QSplitter;
     vSplitter->setOrientation(Qt::Vertical);
-- 
GitLab


From 247051c2498c2a397847a234fff035924b896231 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:49:05 +0100
Subject: [PATCH 107/108] ctd

---
 GUI/View/Sample/SampleEditor.cpp | 2 ++
 GUI/View/Views/SampleView.cpp    | 7 ++-----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/GUI/View/Sample/SampleEditor.cpp b/GUI/View/Sample/SampleEditor.cpp
index 2e3370e3d80..66f33641876 100644
--- a/GUI/View/Sample/SampleEditor.cpp
+++ b/GUI/View/Sample/SampleEditor.cpp
@@ -22,6 +22,8 @@ SampleEditor::SampleEditor()
 {
     QScrollArea::setWidgetResizable(true);
     QScrollArea::setWidget(new QWidget());
+    setMinimumWidth(1000);
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
 }
 
 SampleEditor::~SampleEditor() = default;
diff --git a/GUI/View/Views/SampleView.cpp b/GUI/View/Views/SampleView.cpp
index 868bbf38be0..1e093f432b4 100644
--- a/GUI/View/Views/SampleView.cpp
+++ b/GUI/View/Views/SampleView.cpp
@@ -21,7 +21,6 @@
 #include "GUI/Model/Sample/ParticleLayoutItem.h"
 #include "GUI/Model/Sample/SampleItem.h"
 #include "GUI/Model/Sample/SamplesSet.h"
-#include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Layout/mainwindow_constants.h"
 #include "GUI/View/List/SamplesQListView.h"
 #include "GUI/View/List/SamplesQModel.h"
@@ -33,14 +32,11 @@
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Widget/StyledToolbar.h"
 #include <QBoxLayout>
-#include <QCheckBox>
-#include <QDockWidget>
 #include <QMenu>
 #include <QMessageBox>
 #include <QSettings>
 #include <QSplitter>
 #include <QToolButton>
-#include <QWidgetAction>
 
 SampleView::SampleView()
     : m_qlistmodel(new SamplesQModel(this))
@@ -69,6 +65,8 @@ SampleView::SampleView()
     vSplitter->setOrientation(Qt::Vertical);
     hLayout->addWidget(vSplitter);
 
+    hLayout->addStretch(1);
+
     auto* editor = new SampleEditor;
     vSplitter->addWidget(editor);
 
@@ -215,7 +213,6 @@ void SampleView::onRequestViewInRealspace(Item3D* item)
         return;
     }
 
-    // m_docks->setDockVisible(REALSPACEPANEL);
     m_realspace_panel->widget()->setDisplayedItem(gDoc->samplesModifier()->currentItem(), item);
 }
 
-- 
GitLab


From 9e93bfcccc729627431bf682cc75f078ce98a396 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 26 Feb 2024 15:55:10 +0100
Subject: [PATCH 108/108] format

---
 GUI/View/List/SamplesQListView.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GUI/View/List/SamplesQListView.cpp b/GUI/View/List/SamplesQListView.cpp
index faeabb371b5..20e3a12ba13 100644
--- a/GUI/View/List/SamplesQListView.cpp
+++ b/GUI/View/List/SamplesQListView.cpp
@@ -29,7 +29,7 @@ SamplesQListView::SamplesQListView(SamplesQModel* model)
     connect(this, &QListView::clicked, [this, model](const QModelIndex& qi) {
         gDoc->samplesModifier()->setCurrentIndex(qi.row());
         emit gDoc->samples()->setChanged();
-	emit currentSampleChanged(model->itemForIndex(qi));
+        emit currentSampleChanged(model->itemForIndex(qi));
     });
 
     disconnect(gDoc->samples(), &SamplesSet::setChanged, nullptr, nullptr);
-- 
GitLab