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] 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