From 072e02cfb1835999359ea66725bec5bebfffaaf9 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Tue, 30 Nov 2021 15:46:02 +0100 Subject: [PATCH] rm SessionItem from MaterialItem --- GUI/Model/Material/MaterialDataItems.cpp | 48 ---- GUI/Model/Material/MaterialDataItems.h | 51 ---- GUI/Model/Material/MaterialItem.cpp | 322 +++++++++++++++-------- GUI/Model/Material/MaterialItem.h | 63 +++-- GUI/Model/Session/ModelPath.cpp | 6 + GUI/Model/Session/ModelPath.h | 3 + 6 files changed, 264 insertions(+), 229 deletions(-) delete mode 100644 GUI/Model/Material/MaterialDataItems.cpp delete mode 100644 GUI/Model/Material/MaterialDataItems.h diff --git a/GUI/Model/Material/MaterialDataItems.cpp b/GUI/Model/Material/MaterialDataItems.cpp deleted file mode 100644 index ebd044005cd..00000000000 --- a/GUI/Model/Material/MaterialDataItems.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Material/MaterialDataItems.cpp -//! @brief Implements MaterialDataItems classes -//! -//! @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/Model/Material/MaterialDataItems.h" - -MaterialDataItem::MaterialDataItem(const QString& modelType) : SessionItem(modelType) -{ - setEditable(false); // empty label, non-editable -} - -// ------------------------------------------------------------------------------------------------ - -MaterialRefractiveDataItem::MaterialRefractiveDataItem() : MaterialDataItem(M_TYPE) -{ - addProperty(P_DELTA, 0.0) - ->setEditorType("ScientificDouble") - .setLimits(RealLimits::limitless()) - .setToolTip("Delta of refractive index (n = 1 - delta + i*beta)"); - addProperty(P_BETA, 0.0) - ->setEditorType("ScientificDouble") - .setLimits(RealLimits::limitless()) - .setToolTip("Beta of refractive index (n = 1 - delta + i*beta)"); -} - -// ------------------------------------------------------------------------------------------------ - -MaterialSLDDataItem::MaterialSLDDataItem() : MaterialDataItem(M_TYPE) -{ - addProperty(P_SLD_REAL, 0.0) - ->setEditorType("ScientificDouble") - .setLimits(RealLimits::limitless()) - .setToolTip("Real part of SLD (SLD = real - i*imag), AA^{-2}"); - addProperty(P_SLD_IMAG, 0.0) - ->setEditorType("ScientificDouble") - .setLimits(RealLimits::limitless()) - .setToolTip("Imaginary part of SLD (SLD = real - i*imag), AA^{-2}"); -} diff --git a/GUI/Model/Material/MaterialDataItems.h b/GUI/Model/Material/MaterialDataItems.h deleted file mode 100644 index ea25e70dd75..00000000000 --- a/GUI/Model/Material/MaterialDataItems.h +++ /dev/null @@ -1,51 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Material/MaterialDataItems.h -//! @brief Defines MaterialDataItems classes -//! -//! @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_MODEL_MATERIAL_MATERIALDATAITEMS_H -#define BORNAGAIN_GUI_MODEL_MATERIAL_MATERIALDATAITEMS_H - -#include "GUI/Model/Session/SessionItem.h" - -class BA_CORE_API_ MaterialDataItem : public SessionItem { -protected: - MaterialDataItem(const QString& modelType); -}; - -class MaterialRefractiveDataItem : public MaterialDataItem { -private: - static constexpr auto P_DELTA{"Delta"}; - static constexpr auto P_BETA{"Beta"}; - -public: - static constexpr auto M_TYPE{"MaterialRefractiveData"}; - - MaterialRefractiveDataItem(); - - friend class MaterialItem; -}; - -class MaterialSLDDataItem : public MaterialDataItem { -private: - static constexpr auto P_SLD_REAL{"SLD, real"}; - static constexpr auto P_SLD_IMAG{"SLD, imaginary"}; - -public: - static constexpr auto M_TYPE{"MaterialSLDData"}; - - MaterialSLDDataItem(); - - friend class MaterialItem; -}; - -#endif // BORNAGAIN_GUI_MODEL_MATERIAL_MATERIALDATAITEMS_H diff --git a/GUI/Model/Material/MaterialItem.cpp b/GUI/Model/Material/MaterialItem.cpp index 03257f19837..a9defd62f76 100644 --- a/GUI/Model/Material/MaterialItem.cpp +++ b/GUI/Model/Material/MaterialItem.cpp @@ -14,179 +14,293 @@ #include "GUI/Model/Material/MaterialItem.h" #include "Base/Util/Assert.h" -#include "GUI/Model/Group/GroupInfo.h" -#include "GUI/Model/Material/MaterialDataItems.h" +#include "GUI/Model/Session/ModelPath.h" +#include "GUI/Model/Session/SessionXML.h" #include "GUI/Model/Types/VectorDescriptor.h" +#include "GUI/Util/DeserializationException.h" #include "Sample/Material/MaterialFactoryFuncs.h" #include <QColor> #include <QUuid> +#include <QXmlStreamReader> -namespace { - -const QString magnetization_tooltip = "Magnetization (A/m)"; +using namespace GUI::Session::XML; +namespace { +namespace Tags { +const QString Color("Color"); +const QString Id("Id"); +const QString Name("Name"); +const QString Delta("Delta"); +const QString Beta("Beta"); +const QString Sld("Sld"); +const QString Magnetization("Magnetization"); +} // namespace Tags +} // namespace + +#define m_delta std::get<Refractive>(m_data).delta +#define m_beta std::get<Refractive>(m_data).beta + +#define m_real std ::get<complex_t>(m_data).real() +#define m_imag std ::get<complex_t>(m_data).imag() + +MaterialItem::MaterialItem() : m_data(Refractive(0.0, 0.0)) +{ + m_color = Qt::red; + m_id = QUuid::createUuid().toString(); } - -MaterialItem::MaterialItem() : SessionItem(M_TYPE) +MaterialItem::MaterialItem(const MaterialItem& other) + : m_name(other.m_name) + , m_id(other.m_id) + , m_color(other.m_color) + , m_data(other.m_data) + , m_magnetization(other.m_magnetization) { - setItemName("Material"); - - addProperty(P_COLOR, QColor(Qt::red)); - - GroupInfo info; - info.add(MaterialRefractiveDataItem::M_TYPE, "Refractive index based"); - info.add(MaterialSLDDataItem::M_TYPE, "SLD based"); - info.setDefaultType(MaterialRefractiveDataItem::M_TYPE); - addGroupProperty(P_MATERIAL_DATA, info); - - addProperty<VectorItem>(P_MAGNETIZATION)->setToolTip(magnetization_tooltip); - addProperty(P_IDENTIFIER, QUuid::createUuid().toString()); - getItem(P_IDENTIFIER)->setVisible(false); } -//! Turns material into refractive index material. - void MaterialItem::setRefractiveIndex(const double delta, const double beta) { - auto* refractiveData = setGroupProperty(P_MATERIAL_DATA, MaterialRefractiveDataItem::M_TYPE); - refractiveData->setItemValue(MaterialRefractiveDataItem::P_DELTA, delta); - refractiveData->setItemValue(MaterialRefractiveDataItem::P_BETA, beta); -} + const Refractive r(delta, beta); + if (hasRefractiveIndex() && std::get<Refractive>(m_data) == r) + return; -//! Turns material into SLD based material. + m_data = r; + emit dataChanged(); +} void MaterialItem::setScatteringLengthDensity(const complex_t sld) { - auto* sldData = setGroupProperty(P_MATERIAL_DATA, MaterialSLDDataItem::M_TYPE); - sldData->setItemValue(MaterialSLDDataItem::P_SLD_REAL, sld.real()); - sldData->setItemValue(MaterialSLDDataItem::P_SLD_IMAG, sld.imag()); + if (!hasRefractiveIndex() && std::get<complex_t>(m_data) == sld) + return; + + m_data = sld; + emit dataChanged(); } DoubleDescriptor MaterialItem::delta() { - return DoubleDescriptor( - getGroupItem(P_MATERIAL_DATA)->getItem(MaterialRefractiveDataItem::P_DELTA), - Unit::unitless); + ASSERT(hasRefractiveIndex()); + const auto setter = [=](double v) { + if (m_delta != v) { + m_delta = v; + emit dataChanged(); + } + }; + + DoubleDescriptor d( + "Delta", "Delta of refractive index (n = 1 - delta + i*beta)", 3, RealLimits::limitless(), + setter, [=] { return m_delta; }, Unit::unitless); + d.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/delta"; }; + return d; } DoubleDescriptor MaterialItem::beta() { - return DoubleDescriptor( - getGroupItem(P_MATERIAL_DATA)->getItem(MaterialRefractiveDataItem::P_BETA), Unit::unitless); + ASSERT(hasRefractiveIndex()); + const auto setter = [=](double v) { + if (m_beta != v) { + m_beta = v; + emit dataChanged(); + } + }; + + DoubleDescriptor d( + "Beta", "Beta of refractive index (n = 1 - delta + i*beta)", 3, RealLimits::limitless(), + setter, [=] { return m_beta; }, Unit::unitless); + d.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/beta"; }; + return d; } DoubleDescriptor MaterialItem::sldRe() { - return DoubleDescriptor(getGroupItem(P_MATERIAL_DATA)->getItem(MaterialSLDDataItem::P_SLD_REAL), - Unit::unitless); + ASSERT(!hasRefractiveIndex()); + const auto setter = [=](double v) { + if (m_real != v) { + std::get<complex_t>(m_data).real(v); + emit dataChanged(); + } + }; + + DoubleDescriptor d( + "SLD, real", "Real part of SLD (SLD = real - i*imag), AA^{-2}", 3, RealLimits::limitless(), + setter, [=] { return m_real; }, Unit::unitless); + d.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/re"; }; + return d; } DoubleDescriptor MaterialItem::sldIm() { - return DoubleDescriptor(getGroupItem(P_MATERIAL_DATA)->getItem(MaterialSLDDataItem::P_SLD_IMAG), - Unit::unitless); + ASSERT(!hasRefractiveIndex()); + const auto setter = [=](double v) { + if (m_imag != v) { + std::get<complex_t>(m_data).imag(v); + emit dataChanged(); + } + }; + + DoubleDescriptor d( + "SLD, imaginary", "Imaginary part of SLD (SLD = real - i*imag), AA^{-2}", 3, + RealLimits::limitless(), setter, [=] { return m_imag; }, Unit::unitless); + d.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/im"; }; + return d; } VectorDescriptor MaterialItem::magnetizationVector() { - return VectorDescriptor(item<VectorItem>(P_MAGNETIZATION), "A/m"); + VectorDescriptor d("Magnetization", "Magnetization (A/m)", "A/m"); + + d.x.set = [=](double v) { + if (m_magnetization.x() != v) { + m_magnetization.setX(v); + emit dataChanged(); + } + }; + d.x.get = [=]() { return m_magnetization.x(); }; + d.x.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/mx"; }; + + d.y.set = [=](double v) { + if (m_magnetization.y() != v) { + m_magnetization.setY(v); + emit dataChanged(); + } + }; + d.y.get = [=]() { return m_magnetization.y(); }; + d.y.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/my"; }; + + d.z.set = [=](double v) { + if (m_magnetization.z() != v) { + m_magnetization.setZ(v); + emit dataChanged(); + } + }; + d.z.get = [=]() { return m_magnetization.z(); }; + d.z.path = [=] { return GUI::Model::Path::getPathFromItem(this) + "/mz"; }; + + return d; } bool MaterialItem::hasRefractiveIndex() const { - SessionItem* data = getGroupItem(P_MATERIAL_DATA); - ASSERT(data); - return dynamic_cast<MaterialRefractiveDataItem*>(data) != nullptr; -} - -double MaterialItem::refractiveIndexDelta() const -{ - ASSERT(hasRefractiveIndex()); - return getGroupItem(P_MATERIAL_DATA) - ->getItemValue(MaterialRefractiveDataItem::P_DELTA) - .toDouble(); -} - -double MaterialItem::refractiveIndexBeta() const -{ - ASSERT(hasRefractiveIndex()); - return getGroupItem(P_MATERIAL_DATA) - ->getItemValue(MaterialRefractiveDataItem::P_BETA) - .toDouble(); -} - -complex_t MaterialItem::scatteringLengthDensity() const -{ - ASSERT(!hasRefractiveIndex()); - SessionItem* ri = getGroupItem(P_MATERIAL_DATA); - double real = ri->getItemValue(MaterialSLDDataItem::P_SLD_REAL).toDouble(); - double imag = ri->getItemValue(MaterialSLDDataItem::P_SLD_IMAG).toDouble(); - return complex_t(real, imag); + return std::holds_alternative<Refractive>(m_data); } QString MaterialItem::materialName() const { - return itemName(); + return m_name; } void MaterialItem::setMaterialName(const QString& name) { - setItemName(name); + if (m_name != name) { + m_name = name; + emit dataChanged(); + } } QString MaterialItem::identifier() const { - return getItemValue(P_IDENTIFIER).toString(); + return m_id; } void MaterialItem::setIdentifier(const QString& id) { - setItemValue(P_IDENTIFIER, id); + m_id = id; + // no "emit dataChanged()" here +} + +void MaterialItem::createNewIdentifier() +{ + m_id = QUuid::createUuid().toString(); + // no "emit dataChanged()" here } QColor MaterialItem::color() const { - return getItemValue(P_COLOR).value<QColor>(); + return m_color; } void MaterialItem::setColor(const QColor& color) { - setItemValue(P_COLOR, color); + if (m_color != color) { + m_color = color; + emit dataChanged(); + } } R3 MaterialItem::magnetization() const { - return item<VectorItem>(P_MAGNETIZATION)->getVector(); + return m_magnetization; } void MaterialItem::setMagnetization(const R3& magnetization) { - item<VectorItem>(P_MAGNETIZATION)->setVector(magnetization); + if (m_magnetization != magnetization) { + m_magnetization = magnetization; + emit dataChanged(); + } } -void MaterialItem::hideMagnetization() +std::unique_ptr<Material> MaterialItem::createMaterial() const { - getItem(MaterialItem::P_MAGNETIZATION)->setVisible(false); + if (hasRefractiveIndex()) + return std::make_unique<Material>( + HomogeneousMaterial(materialName().toStdString(), m_delta, m_beta, m_magnetization)); + + return std::make_unique<Material>( + MaterialBySLD(materialName().toStdString(), m_real, m_imag, m_magnetization)); } -std::unique_ptr<Material> MaterialItem::createMaterial() const +void MaterialItem::writeContentTo(QXmlStreamWriter* writer) const { - auto* dataItem = getGroupItem(P_MATERIAL_DATA); - auto magnetization = item<VectorItem>(P_MAGNETIZATION)->getVector(); - auto name = itemName().toStdString(); + writeAttribute(writer, GUI::Session::XML::Version, int(1)); + + writeAttribute(writer, Tags::Id, m_id); + writeAttribute(writer, Tags::Color, m_color); + writeAttribute(writer, Tags::Name, m_name); + writeAttribute(writer, Tags::Magnetization, m_magnetization); - if (dataItem->modelType() == MaterialRefractiveDataItem::M_TYPE) { - double delta = dataItem->getItemValue(MaterialRefractiveDataItem::P_DELTA).toDouble(); - double beta = dataItem->getItemValue(MaterialRefractiveDataItem::P_BETA).toDouble(); - return std::make_unique<Material>(HomogeneousMaterial(name, delta, beta, magnetization)); + if (hasRefractiveIndex()) { + writeAttribute(writer, Tags::Delta, m_delta); + writeAttribute(writer, Tags::Beta, m_beta); + } else + writeAttribute(writer, Tags::Sld, std::get<complex_t>(m_data)); +} + +void MaterialItem::readContentFrom(QXmlStreamReader* reader) +{ + const int version = reader->attributes().value(GUI::Session::XML::Version).toInt(); + + if (version < 1) + throw DeserializationException::tooOld(); + + if (version > 1) + throw DeserializationException::tooNew(); + + readAttribute(reader, Tags::Id, &m_id); + readAttribute(reader, Tags::Color, &m_color); + readAttribute(reader, Tags::Name, &m_name); + readAttribute(reader, Tags::Magnetization, &m_magnetization); + if (reader->attributes().hasAttribute(Tags::Delta)) { + double d, b; + readAttribute(reader, Tags::Delta, &d); + readAttribute(reader, Tags::Beta, &b); + m_data = Refractive(d, b); + } else { + complex_t c; + readAttribute(reader, Tags::Sld, &c); + m_data = c; } - if (dataItem->modelType() == MaterialSLDDataItem::M_TYPE) { - double sld_real = dataItem->getItemValue(MaterialSLDDataItem::P_SLD_REAL).toDouble(); - double sld_imag = dataItem->getItemValue(MaterialSLDDataItem::P_SLD_IMAG).toDouble(); - return std::make_unique<Material>(MaterialBySLD(name, sld_real, sld_imag, magnetization)); +} + +void MaterialItem::updateFrom(const MaterialItem& other) +{ + if (operator!=(other)) { + m_name = other.m_name; + m_color = other.m_color; + m_data = other.m_data; + m_magnetization = other.m_magnetization; + emit dataChanged(); } - ASSERT(0); } bool MaterialItem::operator!=(const MaterialItem& other) const @@ -196,27 +310,13 @@ bool MaterialItem::operator!=(const MaterialItem& other) const bool MaterialItem::operator==(const MaterialItem& other) const { - if (identifier() != other.identifier()) - return false; - if (itemName() != other.itemName()) - return false; - if (color() != other.color()) - return false; - if (magnetization() != other.magnetization()) - return false; - - if (hasRefractiveIndex() != other.hasRefractiveIndex()) - return false; - if (hasRefractiveIndex()) { - if (refractiveIndexBeta() != other.refractiveIndexBeta()) - return false; - if (refractiveIndexDelta() != other.refractiveIndexDelta()) - return false; - } else { - if (scatteringLengthDensity() != other.scatteringLengthDensity()) + if (std::get<Refractive>(m_data) != std::get<Refractive>(other.m_data)) return false; - } + } else if (std::get<complex_t>(m_data) != std::get<complex_t>(other.m_data)) + return false; + - return true; + return (m_id == other.m_id) && (m_name == other.m_name) && (m_color == other.m_color) + && (m_magnetization == other.m_magnetization); } diff --git a/GUI/Model/Material/MaterialItem.h b/GUI/Model/Material/MaterialItem.h index af486c7f1fb..af17bab0e5f 100644 --- a/GUI/Model/Material/MaterialItem.h +++ b/GUI/Model/Material/MaterialItem.h @@ -15,29 +15,33 @@ #ifndef BORNAGAIN_GUI_MODEL_MATERIAL_MATERIALITEM_H #define BORNAGAIN_GUI_MODEL_MATERIAL_MATERIALITEM_H -#include "GUI/Model/Session/SessionItem.h" - +#include <QColor> +#include <QObject> #include <heinz/Complex.h> #include <heinz/Vectors3D.h> +#include <variant> class Material; class DoubleDescriptor; class VectorDescriptor; +class QXmlStreamReader; +class QXmlStreamWriter; -class BA_CORE_API_ MaterialItem : public SessionItem { -private: - static constexpr auto P_COLOR{"Color"}; - static constexpr auto P_MATERIAL_DATA{"Material data"}; - static constexpr auto P_MAGNETIZATION{"Magnetization"}; - static constexpr auto P_IDENTIFIER{"Identifier"}; +class MaterialItem : public QObject { + Q_OBJECT public: - static constexpr auto M_TYPE{"Material"}; - MaterialItem(); - /// set refractive index as in 1 - delta + i * beta + //! Creates a complete copy, also the identifier is the same. + MaterialItem(const MaterialItem& other); + + //! Turns material into refractive index material. + //! + //! Set refractive index as in 1 - delta + i * beta void setRefractiveIndex(double delta, double beta); + + //! Turns material into SLD based material. void setScatteringLengthDensity(complex_t sld); DoubleDescriptor delta(); @@ -49,17 +53,12 @@ public: /// \return true if refractive index was given, otherwise SLD was given bool hasRefractiveIndex() const; - double refractiveIndexDelta() const; - double refractiveIndexBeta() const; - - /// \pre ! hasRefractiveIndex - complex_t scatteringLengthDensity() const; - QString materialName() const; void setMaterialName(const QString& name); QString identifier() const; void setIdentifier(const QString& id); + void createNewIdentifier(); QColor color() const; void setColor(const QColor& color); @@ -67,14 +66,40 @@ public: R3 magnetization() const; void setMagnetization(const R3& magnetization); - void hideMagnetization(); - std::unique_ptr<Material> createMaterial() const; //! Compares all contents. The inactive contents (e.g. SLD in case of refractive) are not taken //! into account. bool operator==(const MaterialItem& other) const; bool operator!=(const MaterialItem& other) const; + + void writeContentTo(QXmlStreamWriter* writer) const; + void readContentFrom(QXmlStreamReader* reader); + + //! Updates content from the other material. + //! + //! Does NOT change the identifier. + //! emits dataChanged, if differences exist. + void updateFrom(const MaterialItem& other); + +signals: + void dataChanged() const; + +private: + QString m_name; + QString m_id; + QColor m_color; + + struct Refractive { + Refractive(double d, double b) : delta(d), beta(b) {} + double delta = 0.0; + double beta = 0.0; + bool operator==(const Refractive& o) const { return delta == o.delta && beta == o.beta; } + bool operator!=(const Refractive& o) const { return !operator==(o); } + }; + + std::variant<Refractive, complex_t> m_data; + R3 m_magnetization; }; #endif // BORNAGAIN_GUI_MODEL_MATERIAL_MATERIALITEM_H diff --git a/GUI/Model/Session/ModelPath.cpp b/GUI/Model/Session/ModelPath.cpp index 905a5b8487f..5f74fd2790d 100644 --- a/GUI/Model/Session/ModelPath.cpp +++ b/GUI/Model/Session/ModelPath.cpp @@ -15,6 +15,7 @@ #include "GUI/Model/Session/ModelPath.h" #include "GUI/Model/Instrument/InstrumentItems.h" #include "GUI/Model/Job/JobItem.h" +#include "GUI/Model/Material/MaterialItem.h" QString GUI::Model::Path::getPathFromIndex(const QModelIndex& index) { @@ -97,3 +98,8 @@ QString GUI::Model::Path::getPathFromItem(SessionItem* item) ASSERT(item->model()); // if assert, item is not completely initialized return getPathFromIndex(item->model()->indexOfItem(item)); } + +QString GUI::Model::Path::getPathFromItem(const MaterialItem* item) +{ + return "material/" + item->identifier(); +} diff --git a/GUI/Model/Session/ModelPath.h b/GUI/Model/Session/ModelPath.h index b1bfa2206dc..6959793cd73 100644 --- a/GUI/Model/Session/ModelPath.h +++ b/GUI/Model/Session/ModelPath.h @@ -22,6 +22,7 @@ class SessionItem; class QModelIndex; class SessionModel; class QString; +class MaterialItem; namespace GUI::Model::Path { @@ -29,6 +30,8 @@ QString getPathFromIndex(const QModelIndex& index); QString getPathFromItem(SessionItem* item); +QString getPathFromItem(const MaterialItem* item); + QModelIndex getIndexFromPath(const SessionModel* model, const QString& path); SessionItem* getItemFromPath(const QString& relPath, const SessionItem* parent); -- GitLab