From 5c29d5647d0056649308653a13feeb98a455739d Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Wed, 8 Dec 2021 20:13:36 +0100 Subject: [PATCH 01/15] fix warning "unused param" --- GUI/Model/Sample/SampleValidator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/Model/Sample/SampleValidator.cpp b/GUI/Model/Sample/SampleValidator.cpp index 00060132a8d..f69311d2af6 100644 --- a/GUI/Model/Sample/SampleValidator.cpp +++ b/GUI/Model/Sample/SampleValidator.cpp @@ -42,8 +42,8 @@ void SampleValidator::validateItem(const SessionItem* item) void SampleValidator::validateInterferences(const LayerItem* layer) { -#ifdef WIN32 ASSERT(layer); +#ifdef WIN32 int iLayout = 0; for (const auto* layout : layer->layouts()) { -- GitLab From ca559fcd19fa1170302e2d965752a26ce21a0b48 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 06:23:12 +0100 Subject: [PATCH 02/15] ensure correct layer-thickness when creating sample (GUI->domain) --- GUI/Model/To/DomainObjectBuilder.cpp | 8 +++++--- GUI/Model/To/DomainObjectBuilder.h | 2 +- GUI/Model/To/ToDomain.cpp | 7 ++++--- GUI/Model/To/ToDomain.h | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/GUI/Model/To/DomainObjectBuilder.cpp b/GUI/Model/To/DomainObjectBuilder.cpp index 13984572b0a..20a65f09846 100644 --- a/GUI/Model/To/DomainObjectBuilder.cpp +++ b/GUI/Model/To/DomainObjectBuilder.cpp @@ -26,7 +26,8 @@ GUI::Model::DomainObjectBuilder::buildMultiLayer(const MultiLayerItem& item) { auto P_multilayer = GUI::Transform::ToDomain::createMultiLayer(item); for (auto* layerItem : item.layers()) { - auto P_layer = buildLayer(*layerItem); + const bool isFirstOrLastLayer = layerItem == item.layers().first() || item.layers().last(); + auto P_layer = buildLayer(*layerItem, isFirstOrLastLayer); const auto roughness = layerItem->roughness().currentItem(); auto P_roughness = GUI::Transform::ToDomain::createLayerRoughness(roughness); if (P_layer) { @@ -39,9 +40,10 @@ GUI::Model::DomainObjectBuilder::buildMultiLayer(const MultiLayerItem& item) return P_multilayer; } -std::unique_ptr<Layer> GUI::Model::DomainObjectBuilder::buildLayer(const LayerItem& item) +std::unique_ptr<Layer> GUI::Model::DomainObjectBuilder::buildLayer(const LayerItem& item, + bool isFirstOrLastLayer) { - auto P_layer = GUI::Transform::ToDomain::createLayer(item); + auto P_layer = GUI::Transform::ToDomain::createLayer(item, isFirstOrLastLayer); for (ParticleLayoutItem* layout : item.layouts()) { auto P_layout = buildParticleLayout(*layout); if (P_layout) diff --git a/GUI/Model/To/DomainObjectBuilder.h b/GUI/Model/To/DomainObjectBuilder.h index 6221e2b81c7..132010d55d5 100644 --- a/GUI/Model/To/DomainObjectBuilder.h +++ b/GUI/Model/To/DomainObjectBuilder.h @@ -32,7 +32,7 @@ class ICoordSystem; namespace GUI::Model::DomainObjectBuilder { std::unique_ptr<MultiLayer> buildMultiLayer(const MultiLayerItem& item); -std::unique_ptr<Layer> buildLayer(const LayerItem& item); +std::unique_ptr<Layer> buildLayer(const LayerItem& item, bool isFirstOrLastLayer); std::unique_ptr<ParticleLayout> buildParticleLayout(const ParticleLayoutItem& item); } // namespace GUI::Model::DomainObjectBuilder diff --git a/GUI/Model/To/ToDomain.cpp b/GUI/Model/To/ToDomain.cpp index b7184922a69..9cc724da0ee 100644 --- a/GUI/Model/To/ToDomain.cpp +++ b/GUI/Model/To/ToDomain.cpp @@ -39,10 +39,11 @@ std::unique_ptr<MultiLayer> GUI::Transform::ToDomain::createMultiLayer(const Mul return P_multilayer; } -std::unique_ptr<Layer> GUI::Transform::ToDomain::createLayer(const LayerItem& item) +std::unique_ptr<Layer> GUI::Transform::ToDomain::createLayer(const LayerItem& item, + bool isFirstOrLastLayer) { - auto P_layer = - std::make_unique<Layer>(*item.materialItem()->createMaterial(), item.thickness()); + auto P_layer = std::make_unique<Layer>(*item.materialItem()->createMaterial(), + isFirstOrLastLayer ? 0.0 : item.thickness()); P_layer->setNumberOfSlices(item.numSlices()); return P_layer; } diff --git a/GUI/Model/To/ToDomain.h b/GUI/Model/To/ToDomain.h index c2f7607f978..3094cc184c4 100644 --- a/GUI/Model/To/ToDomain.h +++ b/GUI/Model/To/ToDomain.h @@ -37,7 +37,7 @@ class LayerBasicRoughnessItem; namespace GUI::Transform::ToDomain { std::unique_ptr<IParticle> createIParticle(const SessionItem& item); -std::unique_ptr<Layer> createLayer(const LayerItem& item); +std::unique_ptr<Layer> createLayer(const LayerItem& item, bool isFirstOrLastLayer); std::unique_ptr<LayerRoughness> createLayerRoughness( const std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*>& roughness); std::unique_ptr<MultiLayer> createMultiLayer(const MultiLayerItem& item); -- GitLab From e59c67d1445f11a2fccaf8c9d91ea70254239708 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 06:27:11 +0100 Subject: [PATCH 03/15] ensure correct roughness when creating sample (GUI->domain) --- GUI/Model/To/DomainObjectBuilder.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/GUI/Model/To/DomainObjectBuilder.cpp b/GUI/Model/To/DomainObjectBuilder.cpp index 20a65f09846..bc69ebd0f74 100644 --- a/GUI/Model/To/DomainObjectBuilder.cpp +++ b/GUI/Model/To/DomainObjectBuilder.cpp @@ -22,16 +22,17 @@ #include "GUI/Util/Error.h" std::unique_ptr<MultiLayer> -GUI::Model::DomainObjectBuilder::buildMultiLayer(const MultiLayerItem& item) +GUI::Model::DomainObjectBuilder::buildMultiLayer(const MultiLayerItem& multiLayerItem) { - auto P_multilayer = GUI::Transform::ToDomain::createMultiLayer(item); - for (auto* layerItem : item.layers()) { - const bool isFirstOrLastLayer = layerItem == item.layers().first() || item.layers().last(); - auto P_layer = buildLayer(*layerItem, isFirstOrLastLayer); - const auto roughness = layerItem->roughness().currentItem(); - auto P_roughness = GUI::Transform::ToDomain::createLayerRoughness(roughness); + auto P_multilayer = GUI::Transform::ToDomain::createMultiLayer(multiLayerItem); + for (auto* layerItem : multiLayerItem.layers()) { + const bool isFirstLayer = layerItem == multiLayerItem.layers().first(); + const bool isLastLayer = layerItem == multiLayerItem.layers().last(); + auto P_layer = buildLayer(*layerItem, isFirstLayer || isLastLayer); if (P_layer) { - if (P_roughness) + const auto roughness = layerItem->roughness().currentItem(); + auto P_roughness = GUI::Transform::ToDomain::createLayerRoughness(roughness); + if (P_roughness && !isLastLayer) P_multilayer->addLayerWithTopRoughness(*P_layer, *P_roughness); else P_multilayer->addLayer(*P_layer); -- GitLab From f4683b9f627785e904b03e417c660287a50dd90b Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 06:42:01 +0100 Subject: [PATCH 04/15] cleanup/simplify ToDomain (namespaces, files) --- GUI/Model/To/DomainObjectBuilder.cpp | 78 ---------------- GUI/Model/To/DomainObjectBuilder.h | 40 -------- GUI/Model/To/DomainSimulationBuilder.cpp | 4 +- GUI/Model/To/ToDomain.cpp | 104 +++++++++++++++++---- GUI/Model/To/ToDomain.h | 20 +--- GUI/View/SampleDesigner/ScriptPanel.cpp | 5 +- Tests/Unit/GUI/TestLayerRoughnessItems.cpp | 1 + 7 files changed, 94 insertions(+), 158 deletions(-) delete mode 100644 GUI/Model/To/DomainObjectBuilder.cpp delete mode 100644 GUI/Model/To/DomainObjectBuilder.h diff --git a/GUI/Model/To/DomainObjectBuilder.cpp b/GUI/Model/To/DomainObjectBuilder.cpp deleted file mode 100644 index bc69ebd0f74..00000000000 --- a/GUI/Model/To/DomainObjectBuilder.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/To/DomainObjectBuilder.cpp -//! @brief Implements DomainObjectBuilder namespace -//! -//! @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/To/DomainObjectBuilder.h" -#include "GUI/Model/Instrument/InstrumentItems.h" -#include "GUI/Model/Sample/InterferenceItems.h" -#include "GUI/Model/Sample/LayerItem.h" -#include "GUI/Model/Sample/MultiLayerItem.h" -#include "GUI/Model/Sample/ParticleLayoutItem.h" -#include "GUI/Model/To/ToDomain.h" -#include "GUI/Util/Error.h" - -std::unique_ptr<MultiLayer> -GUI::Model::DomainObjectBuilder::buildMultiLayer(const MultiLayerItem& multiLayerItem) -{ - auto P_multilayer = GUI::Transform::ToDomain::createMultiLayer(multiLayerItem); - for (auto* layerItem : multiLayerItem.layers()) { - const bool isFirstLayer = layerItem == multiLayerItem.layers().first(); - const bool isLastLayer = layerItem == multiLayerItem.layers().last(); - auto P_layer = buildLayer(*layerItem, isFirstLayer || isLastLayer); - if (P_layer) { - const auto roughness = layerItem->roughness().currentItem(); - auto P_roughness = GUI::Transform::ToDomain::createLayerRoughness(roughness); - if (P_roughness && !isLastLayer) - P_multilayer->addLayerWithTopRoughness(*P_layer, *P_roughness); - else - P_multilayer->addLayer(*P_layer); - } - } - return P_multilayer; -} - -std::unique_ptr<Layer> GUI::Model::DomainObjectBuilder::buildLayer(const LayerItem& item, - bool isFirstOrLastLayer) -{ - auto P_layer = GUI::Transform::ToDomain::createLayer(item, isFirstOrLastLayer); - for (ParticleLayoutItem* layout : item.layouts()) { - auto P_layout = buildParticleLayout(*layout); - if (P_layout) - P_layer->addLayout(*P_layout); - } - return P_layer; -} - -std::unique_ptr<ParticleLayout> -GUI::Model::DomainObjectBuilder::buildParticleLayout(const ParticleLayoutItem& item) -{ - auto P_layout = GUI::Transform::ToDomain::createParticleLayout(item); - QVector<SessionItem*> children = item.getItems(); - for (int i = 0; i < children.size(); ++i) { - auto P_particle = GUI::Transform::ToDomain::createIParticle(*children[i]); - if (P_particle) { - P_layout->addParticle(*P_particle); - continue; - } - - throw Error("GUI::Model::DomainObjectBuilder::buildParticleLayout()" - " -> Error! Not implemented"); - } - InterferenceItem* interference = item.interference().currentItem(); - if (interference) { - auto P_interference = interference->createInterference(); - if (P_interference) - P_layout->setInterference(*P_interference); - } - return P_layout; -} diff --git a/GUI/Model/To/DomainObjectBuilder.h b/GUI/Model/To/DomainObjectBuilder.h deleted file mode 100644 index 132010d55d5..00000000000 --- a/GUI/Model/To/DomainObjectBuilder.h +++ /dev/null @@ -1,40 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/To/DomainObjectBuilder.h -//! @brief Defines namespace GUI::Model::DomainObjectBuilder -//! -//! @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_TO_DOMAINOBJECTBUILDER_H -#define BORNAGAIN_GUI_MODEL_TO_DOMAINOBJECTBUILDER_H - -#include <memory> - -class MultiLayer; -class Layer; -class LayerItem; -class Instrument; -class MultiLayerItem; -class ParticleLayout; -class ParticleLayoutItem; -class IInterference; -class SessionItem; -class InstrumentItem; -class ICoordSystem; - -namespace GUI::Model::DomainObjectBuilder { - -std::unique_ptr<MultiLayer> buildMultiLayer(const MultiLayerItem& item); -std::unique_ptr<Layer> buildLayer(const LayerItem& item, bool isFirstOrLastLayer); -std::unique_ptr<ParticleLayout> buildParticleLayout(const ParticleLayoutItem& item); - -} // namespace GUI::Model::DomainObjectBuilder - -#endif // BORNAGAIN_GUI_MODEL_TO_DOMAINOBJECTBUILDER_H diff --git a/GUI/Model/To/DomainSimulationBuilder.cpp b/GUI/Model/To/DomainSimulationBuilder.cpp index 5ee90855d10..8d79baa67c6 100644 --- a/GUI/Model/To/DomainSimulationBuilder.cpp +++ b/GUI/Model/To/DomainSimulationBuilder.cpp @@ -30,7 +30,7 @@ #include "GUI/Model/Instrument/InstrumentItems.h" #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Session/SimulationOptionsItem.h" -#include "GUI/Model/To/DomainObjectBuilder.h" +#include "GUI/Model/To/ToDomain.h" #include "GUI/Util/Error.h" #include "Param/Distrib/RangedDistributions.h" #include "Resample/Options/SimulationOptions.h" @@ -220,7 +220,7 @@ GUI::Model::DomainSimulationBuilder::createSimulation(const MultiLayerItem* samp throw Error(message); } - auto P_multilayer = GUI::Model::DomainObjectBuilder::buildMultiLayer(*sampleItem); + auto P_multilayer = GUI::Transform::ToDomain::buildMultiLayer(*sampleItem); if (const auto* gisasInstrument = dynamic_cast<const GISASInstrumentItem*>(instrumentItem)) return createGISASSimulation(std::move(P_multilayer), gisasInstrument, optionsItem); diff --git a/GUI/Model/To/ToDomain.cpp b/GUI/Model/To/ToDomain.cpp index 9cc724da0ee..3e2ff9eed3e 100644 --- a/GUI/Model/To/ToDomain.cpp +++ b/GUI/Model/To/ToDomain.cpp @@ -14,6 +14,7 @@ #include "GUI/Model/To/ToDomain.h" #include "GUI/Model/Material/MaterialItem.h" +#include "GUI/Model/Sample/InterferenceItems.h" #include "GUI/Model/Sample/LayerItem.h" #include "GUI/Model/Sample/LayerRoughnessItems.h" #include "GUI/Model/Sample/MesoCrystalItem.h" @@ -24,11 +25,20 @@ #include "GUI/Model/Sample/ParticleLayoutItem.h" #include "GUI/Model/Types/DoubleDescriptor.h" #include "GUI/Model/Types/UIntDescriptor.h" +#include "GUI/Util/Error.h" +#include "Sample/Aggregate/IInterference.h" +#include "Sample/Aggregate/ParticleLayout.h" +#include "Sample/Interface/LayerRoughness.h" +#include "Sample/Multilayer/Layer.h" +#include "Sample/Multilayer/MultiLayer.h" +#include "Sample/Particle/IParticle.h" #include "Sample/Particle/MesoCrystal.h" #include "Sample/Particle/Particle.h" #include "Sample/Particle/ParticleCoreShell.h" -std::unique_ptr<MultiLayer> GUI::Transform::ToDomain::createMultiLayer(const MultiLayerItem& item) +namespace { + +std::unique_ptr<MultiLayer> createMultiLayer(const MultiLayerItem& item) { auto P_multilayer = std::make_unique<MultiLayer>(); double cross_corr_length = item.crossCorrLength(); @@ -39,8 +49,7 @@ std::unique_ptr<MultiLayer> GUI::Transform::ToDomain::createMultiLayer(const Mul return P_multilayer; } -std::unique_ptr<Layer> GUI::Transform::ToDomain::createLayer(const LayerItem& item, - bool isFirstOrLastLayer) +std::unique_ptr<Layer> createLayer(const LayerItem& item, bool isFirstOrLastLayer) { auto P_layer = std::make_unique<Layer>(*item.materialItem()->createMaterial(), isFirstOrLastLayer ? 0.0 : item.thickness()); @@ -48,22 +57,7 @@ std::unique_ptr<Layer> GUI::Transform::ToDomain::createLayer(const LayerItem& it return P_layer; } -std::unique_ptr<LayerRoughness> GUI::Transform::ToDomain::createLayerRoughness( - const std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*>& roughness) -{ - if (std::holds_alternative<LayerZeroRoughnessItem*>(roughness)) - return nullptr; - if (std::holds_alternative<LayerBasicRoughnessItem*>(roughness)) { - const auto& basicRoughnessItem = *std::get<LayerBasicRoughnessItem*>(roughness); - return std::make_unique<LayerRoughness>(basicRoughnessItem.sigma(), - basicRoughnessItem.hurst(), - basicRoughnessItem.lateralCorrelationLength()); - } - ASSERT(0); -} - -std::unique_ptr<ParticleLayout> -GUI::Transform::ToDomain::createParticleLayout(const ParticleLayoutItem& item) +std::unique_ptr<ParticleLayout> createParticleLayout(const ParticleLayoutItem& item) { auto P_layout = std::make_unique<ParticleLayout>(); double total_density = item.totalDensity(); @@ -73,7 +67,7 @@ GUI::Transform::ToDomain::createParticleLayout(const ParticleLayoutItem& item) return P_layout; } -std::unique_ptr<IParticle> GUI::Transform::ToDomain::createIParticle(const SessionItem& item) +std::unique_ptr<IParticle> createIParticle(const SessionItem& item) { std::unique_ptr<IParticle> P_particle; if (item.hasModelType<ParticleItem>()) { @@ -91,3 +85,73 @@ std::unique_ptr<IParticle> GUI::Transform::ToDomain::createIParticle(const Sessi } return P_particle; } + +std::unique_ptr<ParticleLayout> buildParticleLayout(const ParticleLayoutItem& item) +{ + auto P_layout = createParticleLayout(item); + QVector<SessionItem*> children = item.getItems(); + for (int i = 0; i < children.size(); ++i) { + auto P_particle = createIParticle(*children[i]); + if (P_particle) { + P_layout->addParticle(*P_particle); + continue; + } + + throw Error("GUI::Model::DomainObjectBuilder::buildParticleLayout()" + " -> Error! Not implemented"); + } + InterferenceItem* interference = item.interference().currentItem(); + if (interference) { + auto P_interference = interference->createInterference(); + if (P_interference) + P_layout->setInterference(*P_interference); + } + return P_layout; +} + +std::unique_ptr<Layer> buildLayer(const LayerItem& item, bool isFirstOrLastLayer) +{ + auto P_layer = createLayer(item, isFirstOrLastLayer); + for (ParticleLayoutItem* layout : item.layouts()) { + auto P_layout = buildParticleLayout(*layout); + if (P_layout) + P_layer->addLayout(*P_layout); + } + return P_layer; +} + +} // namespace + +std::unique_ptr<LayerRoughness> GUI::Transform::ToDomain::createLayerRoughness( + const std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*>& roughness) +{ + if (std::holds_alternative<LayerZeroRoughnessItem*>(roughness)) + return nullptr; + if (std::holds_alternative<LayerBasicRoughnessItem*>(roughness)) { + const auto& basicRoughnessItem = *std::get<LayerBasicRoughnessItem*>(roughness); + return std::make_unique<LayerRoughness>(basicRoughnessItem.sigma(), + basicRoughnessItem.hurst(), + basicRoughnessItem.lateralCorrelationLength()); + } + ASSERT(0); +} + +std::unique_ptr<MultiLayer> +GUI::Transform::ToDomain::buildMultiLayer(const MultiLayerItem& multiLayerItem) +{ + auto P_multilayer = createMultiLayer(multiLayerItem); + for (auto* layerItem : multiLayerItem.layers()) { + const bool isFirstLayer = layerItem == multiLayerItem.layers().first(); + const bool isLastLayer = layerItem == multiLayerItem.layers().last(); + auto P_layer = buildLayer(*layerItem, isFirstLayer || isLastLayer); + if (P_layer) { + const auto roughness = layerItem->roughness().currentItem(); + auto P_roughness = createLayerRoughness(roughness); + if (P_roughness && !isLastLayer) + P_multilayer->addLayerWithTopRoughness(*P_layer, *P_roughness); + else + P_multilayer->addLayer(*P_layer); + } + } + return P_multilayer; +} diff --git a/GUI/Model/To/ToDomain.h b/GUI/Model/To/ToDomain.h index 3094cc184c4..7fb9eb4225d 100644 --- a/GUI/Model/To/ToDomain.h +++ b/GUI/Model/To/ToDomain.h @@ -15,33 +15,23 @@ #ifndef BORNAGAIN_GUI_MODEL_TO_TODOMAIN_H #define BORNAGAIN_GUI_MODEL_TO_TODOMAIN_H -#include "Device/Instrument/Instrument.h" -#include "Param/Distrib/Distributions.h" // for IDistribution1D -#include "Param/Distrib/ParameterDistribution.h" -#include "Sample/Aggregate/IInterference.h" -#include "Sample/Aggregate/ParticleLayout.h" -#include "Sample/Interface/LayerRoughness.h" -#include "Sample/Multilayer/Layer.h" -#include "Sample/Multilayer/MultiLayer.h" -#include "Sample/Particle/IParticle.h" #include <memory> #include <variant> class LayerItem; class MultiLayerItem; -class ParticleLayoutItem; -class SessionItem; +class MultiLayer; class LayerZeroRoughnessItem; class LayerBasicRoughnessItem; +class LayerRoughness; namespace GUI::Transform::ToDomain { -std::unique_ptr<IParticle> createIParticle(const SessionItem& item); -std::unique_ptr<Layer> createLayer(const LayerItem& item, bool isFirstOrLastLayer); std::unique_ptr<LayerRoughness> createLayerRoughness( const std::variant<LayerZeroRoughnessItem*, LayerBasicRoughnessItem*>& roughness); -std::unique_ptr<MultiLayer> createMultiLayer(const MultiLayerItem& item); -std::unique_ptr<ParticleLayout> createParticleLayout(const ParticleLayoutItem& item); + +std::unique_ptr<MultiLayer> buildMultiLayer(const MultiLayerItem& item); + } // namespace GUI::Transform::ToDomain diff --git a/GUI/View/SampleDesigner/ScriptPanel.cpp b/GUI/View/SampleDesigner/ScriptPanel.cpp index 8e3af3eb6b2..6c74ff967d3 100644 --- a/GUI/View/SampleDesigner/ScriptPanel.cpp +++ b/GUI/View/SampleDesigner/ScriptPanel.cpp @@ -16,7 +16,7 @@ #include "Core/Export/ExportToPython.h" #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Sample/SampleModel.h" -#include "GUI/Model/To/DomainObjectBuilder.h" +#include "GUI/Model/To/ToDomain.h" #include "GUI/View/Info/CautionSign.h" #include "GUI/View/Info/PythonSyntaxHighlighter.h" #include "GUI/View/Tool/DesignerHelper.h" @@ -122,8 +122,7 @@ QString ScriptPanel::generateCodeSnippet() QString result; try { - auto multilayer = - GUI::Model::DomainObjectBuilder::buildMultiLayer(*m_currentMultiLayerItem); + auto multilayer = GUI::Transform::ToDomain::buildMultiLayer(*m_currentMultiLayerItem); result.append(QString::fromStdString(Py::Export::sampleCode(*multilayer))); } catch (const std::exception& ex) { QString message = diff --git a/Tests/Unit/GUI/TestLayerRoughnessItems.cpp b/Tests/Unit/GUI/TestLayerRoughnessItems.cpp index 43b7bf204b4..ae1684fa16c 100644 --- a/Tests/Unit/GUI/TestLayerRoughnessItems.cpp +++ b/Tests/Unit/GUI/TestLayerRoughnessItems.cpp @@ -2,6 +2,7 @@ #include "GUI/Model/Sample/LayerRoughnessItems.h" #include "GUI/Model/To/ToDomain.h" #include "GUI/Model/Types/DoubleDescriptor.h" +#include "Sample/Interface/LayerRoughness.h" #include "Tests/GTestWrapper/google_test.h" class TestLayerRoughnessItems : public ::testing::Test { -- GitLab From ae0746d1589a05e9243dfc60d12da98f2f0b9e27 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 07:23:15 +0100 Subject: [PATCH 05/15] rm SessionItem signaling from MultiLayer (functionality changed to signal-free by the last commits) rm obsolete unit tests --- GUI/Model/Job/ParameterTreeUtils.cpp | 14 ++- GUI/Model/Sample/MultiLayerItem.cpp | 17 --- GUI/Model/Sample/MultiLayerItem.h | 3 - Tests/Unit/GUI/TestMapperForItem.cpp | 19 ---- Tests/Unit/GUI/TestMultiLayerItem.cpp | 144 -------------------------- 5 files changed, 13 insertions(+), 184 deletions(-) delete mode 100644 Tests/Unit/GUI/TestMultiLayerItem.cpp diff --git a/GUI/Model/Job/ParameterTreeUtils.cpp b/GUI/Model/Job/ParameterTreeUtils.cpp index 94c00843153..eb0d2a7de90 100644 --- a/GUI/Model/Job/ParameterTreeUtils.cpp +++ b/GUI/Model/Job/ParameterTreeUtils.cpp @@ -21,6 +21,7 @@ #include "GUI/Model/Material/MaterialItem.h" #include "GUI/Model/Sample/InterferenceItems.h" #include "GUI/Model/Sample/Lattice2DItems.h" +#include "GUI/Model/Sample/LayerItem.h" #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Sample/ParticleCoreShellItem.h" #include "GUI/Model/Sample/ParticleItem.h" @@ -134,7 +135,18 @@ void GUI::Model::ParameterTreeUtils::createParameterTree(JobItem* jobItem, } } - // add sample + // add sample. + // #baMigration To ignore thickness/roughness, they are disabled. This has to be changed after + // SessionModel migration. Compare also to handling in + // LayerForm::updateLayerPositionDependentElements() + for (auto* layer : jobItem->sampleItem()->layers()) { + const bool isFirstLayer = jobItem->sampleItem()->layers().first() == layer; + const bool isLastLayer = jobItem->sampleItem()->layers().last() == layer; + + layer->setRoughnessEnabled(!isFirstLayer); + layer->setThicknessEnabled(!isFirstLayer && !isLastLayer); + } + populateParameterContainer(container, jobItem->sampleItem(), recreateBackupValues); // add instrument diff --git a/GUI/Model/Sample/MultiLayerItem.cpp b/GUI/Model/Sample/MultiLayerItem.cpp index 5b783ba1e81..f4efbd14577 100644 --- a/GUI/Model/Sample/MultiLayerItem.cpp +++ b/GUI/Model/Sample/MultiLayerItem.cpp @@ -36,8 +36,6 @@ MultiLayerItem::MultiLayerItem() : SessionItem(M_TYPE) registerTag(T_LAYERS, 0, -1, {LayerItem::M_TYPE}); setDefaultTag(T_LAYERS); - - mapper()->setOnChildrenChange([this](SessionItem*) { updateLayers(); }); } QVector<ItemWithMaterial*> MultiLayerItem::itemsWithMaterial() const @@ -120,7 +118,6 @@ void MultiLayerItem::removeLayer(LayerItem* item) model()->removeItem(item); } - void MultiLayerItem::moveLayer(LayerItem* item, LayerItem* beforeThisLayer) { int index = -1; // move to end @@ -129,17 +126,3 @@ void MultiLayerItem::moveLayer(LayerItem* item, LayerItem* beforeThisLayer) model()->moveItem(item, this, index); } - -void MultiLayerItem::updateLayers() -{ - QVector<LayerItem*> list = childrenOfType<LayerItem>(); - for (auto* it = list.begin(); it != list.end(); ++it) { - (*it)->setRoughnessEnabled(it != list.begin()); - - if (it == list.begin() || it == (list.end() - 1)) { - (*it)->setThicknessEnabled(false); - (*it)->thickness().set(0.0); - } else - (*it)->setThicknessEnabled(true); - } -} diff --git a/GUI/Model/Sample/MultiLayerItem.h b/GUI/Model/Sample/MultiLayerItem.h index b5e42623853..e89ec57a230 100644 --- a/GUI/Model/Sample/MultiLayerItem.h +++ b/GUI/Model/Sample/MultiLayerItem.h @@ -62,9 +62,6 @@ public: void removeLayer(LayerItem* item); void moveLayer(LayerItem* item, LayerItem* beforeThisLayer); - -private: - void updateLayers(); }; #endif // BORNAGAIN_GUI_MODEL_SAMPLE_MULTILAYERITEM_H diff --git a/Tests/Unit/GUI/TestMapperForItem.cpp b/Tests/Unit/GUI/TestMapperForItem.cpp index e5178cd382c..174881cb6ca 100644 --- a/Tests/Unit/GUI/TestMapperForItem.cpp +++ b/Tests/Unit/GUI/TestMapperForItem.cpp @@ -176,25 +176,6 @@ TEST_F(TestMapperForItem, onPropertyChange) && MultiLayerItem::isCrossCorrLengthPropertyName(w.m_reported_names[0])); } -TEST_F(TestMapperForItem, onChildrenChange) -{ - Widget w; - SampleModel model; - auto* multilayer = model.insertItem<MultiLayerItem>(); - - // Mapper is looking on parent; adding new child to parent - setItem(multilayer, &w); - EXPECT_TRUE(m_mapped_item == multilayer); - model.insertItem<LayerItem>(multilayer); - - EXPECT_EQ(w.m_onPropertyChangeCount, 0); - EXPECT_EQ(w.m_onChildPropertyChangeCount, 2); - EXPECT_EQ(w.m_onParentChangeCount, 0); - EXPECT_EQ(w.m_onChildrenChangeCount, 1); - EXPECT_EQ(w.m_reported_items.size(), 2); - EXPECT_EQ(w.m_reported_names.size(), 2); -} - TEST_F(TestMapperForItem, onSiblingsChange) { Widget w; diff --git a/Tests/Unit/GUI/TestMultiLayerItem.cpp b/Tests/Unit/GUI/TestMultiLayerItem.cpp deleted file mode 100644 index bf2f2bd60cb..00000000000 --- a/Tests/Unit/GUI/TestMultiLayerItem.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "GUI/Model/Sample/LayerItem.h" -#include "GUI/Model/Sample/LayerRoughnessItems.h" -#include "GUI/Model/Sample/MultiLayerItem.h" -#include "GUI/Model/Sample/SampleModel.h" -#include "GUI/Model/Types/DoubleDescriptor.h" -#include "Tests/GTestWrapper/google_test.h" - -class TestMultiLayerItem : public ::testing::Test { -}; - -//! Testing layer appearance (enabled, disabled) in a MultiLayer made of two default layers. -//! -//! In two layer system top and bottom layers should have disabled thickness and roughness. - -TEST_F(TestMultiLayerItem, twoLayerSystem) -{ - SampleModel model; - - auto* multilayer = model.addMultiLayer(); - auto* top = multilayer->addLayer(); - auto* bottom = multilayer->addLayer(); - - // Thickness property should be disabled for top and bottom layers - EXPECT_FALSE(top->thicknessItem()->isEnabled()); - EXPECT_FALSE(bottom->thicknessItem()->isEnabled()); - - // Thickness value should be 0.0 for top and bottom layers - EXPECT_EQ(top->thickness(), 0.0); - EXPECT_EQ(bottom->thickness(), 0.0); - - // Roughness group property should be disabled for top, and enabled for bottom layers - EXPECT_FALSE(top->roughnessItem()->isEnabled()); - EXPECT_TRUE(bottom->roughnessItem()->isEnabled()); - - // Default roughness should be "LayerZeroRoughness" - EXPECT_TRUE(std::holds_alternative<LayerZeroRoughnessItem*>(top->roughness().currentItem())); - EXPECT_TRUE(std::holds_alternative<LayerZeroRoughnessItem*>(bottom->roughness().currentItem())); -} - -//! Testing layer appearance (enabled, disabled) in a MultiLayer made of three default layers. -//! -//! In three layer system middle layer's thickness/roughness should be enabled. - -TEST_F(TestMultiLayerItem, threeLayerSystem) -{ - SampleModel model; - - auto* multilayer = model.addMultiLayer(); - auto* top = multilayer->addLayer(); - auto* middle = multilayer->addLayer(); - auto* bottom = multilayer->addLayer(); - - // Thickness property should be disabled for top and bottom layers and enabled for middle - EXPECT_FALSE(top->thicknessItem()->isEnabled()); - EXPECT_TRUE(middle->thicknessItem()->isEnabled()); - EXPECT_FALSE(bottom->thicknessItem()->isEnabled()); - - // Thickness value should be 0.0 for top and bottom layers - EXPECT_EQ(top->thickness(), 0.0); - EXPECT_EQ(middle->thickness(), 0.0); - EXPECT_EQ(bottom->thickness(), 0.0); - - // Roughness group property should be disabled for top, and enabled for other layers - EXPECT_FALSE(top->roughnessItem()->isEnabled()); - EXPECT_TRUE(middle->roughnessItem()->isEnabled()); - EXPECT_TRUE(bottom->roughnessItem()->isEnabled()); - - // Default roughness should be "LayerZeroRoughness" - EXPECT_TRUE(std::holds_alternative<LayerZeroRoughnessItem*>(top->roughness().currentItem())); - EXPECT_TRUE(std::holds_alternative<LayerZeroRoughnessItem*>(middle->roughness().currentItem())); - EXPECT_TRUE(std::holds_alternative<LayerZeroRoughnessItem*>(bottom->roughness().currentItem())); -} - -//! Testing middle layer appearance when it is moved to the top. -//! -//! In three layer system, the moving of middle layer on top should lead to the disabling -//! of roughness/thickness. - -TEST_F(TestMultiLayerItem, movingMiddleLayerOnTop) -{ - SampleModel model; - - auto* multilayer = model.addMultiLayer(); - auto* top = multilayer->addLayer(); - auto* middle = multilayer->addLayer(); - auto* bottom = multilayer->addLayer(); - - const double thickness = 10.0; - middle->thickness().set(thickness); - - // Thickness property should be disabled for top and bottom layers and enabled for middle - EXPECT_FALSE(top->thicknessItem()->isEnabled()); - EXPECT_TRUE(middle->thicknessItem()->isEnabled()); - EXPECT_FALSE(bottom->thicknessItem()->isEnabled()); - - // Roughness group property should be disabled for top, and enabled for other layers - EXPECT_FALSE(top->roughnessItem()->isEnabled()); - EXPECT_TRUE(middle->roughnessItem()->isEnabled()); - EXPECT_TRUE(bottom->roughnessItem()->isEnabled()); - - // Thickness value should be 0.0 for top and bottom layers - EXPECT_EQ(top->thickness(), 0.0); - EXPECT_EQ(middle->thickness(), thickness); - EXPECT_EQ(bottom->thickness(), 0.0); - - // Moving middle layer to top - multilayer->moveLayer(middle, top); - // checking that middle is top now, and top layer is middle now - EXPECT_EQ(middle, multilayer->layers().at(0)); - EXPECT_EQ(top, multilayer->layers().at(1)); - - // Thickness and roughness of middle layer should be disabled now - EXPECT_FALSE(middle->thicknessItem()->isEnabled()); - EXPECT_FALSE(middle->roughnessItem()->isEnabled()); - // And, thickness of middle should become 0 to stress the fact that it become top - EXPECT_EQ(middle->thickness(), 0.0); - - // Thickness and roughness of former top layer should be enabled now, since it is in the middle - EXPECT_TRUE(top->thicknessItem()->isEnabled()); - EXPECT_TRUE(top->roughnessItem()->isEnabled()); -} - -//! Testing layer appearance when it is moved from a MultiLayer to canvas. -//! -//! If top layer was moved to canvas, its thickness and roughness should be reenabled. - -TEST_F(TestMultiLayerItem, movingLayerOnCanvas) -{ - SampleModel model; - - auto* multilayer = model.addMultiLayer(); - auto* top = model.insertItem<LayerItem>(multilayer); - model.insertItem<LayerItem>(multilayer); - - // Moving top layer to canvas - model.moveItem(top, nullptr); - - // checking that it was moved - EXPECT_EQ(top->parent(), model.rootItem()); - - // thickness should be reenabled - // EXPECT_TRUE(top->getItem(LayerItem::P_THICKNESS)->isEnabled()); - // EXPECT_TRUE(top->getItem(LayerItem::P_THICKNESS)->isEnabled()); -} -- GitLab From 271cc41526e4bf5c3d15bda2a890f334abdb4e28 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 07:16:10 +0100 Subject: [PATCH 06/15] reduce SessionItem usage, reduce SessionItem signaling --- GUI/Model/Job/ParameterTreeUtils.cpp | 5 ++ GUI/Model/Sample/ParticleLayoutItem.cpp | 49 +++++-------------- GUI/Model/Sample/ParticleLayoutItem.h | 10 +++- .../SampleDesigner/ParticleLayoutForm.cpp | 10 +--- .../SampleDesigner/SampleEditorController.cpp | 4 +- 5 files changed, 30 insertions(+), 48 deletions(-) diff --git a/GUI/Model/Job/ParameterTreeUtils.cpp b/GUI/Model/Job/ParameterTreeUtils.cpp index eb0d2a7de90..1363a6f03d0 100644 --- a/GUI/Model/Job/ParameterTreeUtils.cpp +++ b/GUI/Model/Job/ParameterTreeUtils.cpp @@ -25,6 +25,7 @@ #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Sample/ParticleCoreShellItem.h" #include "GUI/Model/Sample/ParticleItem.h" +#include "GUI/Model/Sample/ParticleLayoutItem.h" #include "GUI/Model/Session/ModelPath.h" #include "GUI/Model/Types/VectorDescriptor.h" #include "GUI/Util/Error.h" @@ -139,12 +140,16 @@ void GUI::Model::ParameterTreeUtils::createParameterTree(JobItem* jobItem, // #baMigration To ignore thickness/roughness, they are disabled. This has to be changed after // SessionModel migration. Compare also to handling in // LayerForm::updateLayerPositionDependentElements() + // dto. for totalDensity of particle layout for (auto* layer : jobItem->sampleItem()->layers()) { const bool isFirstLayer = jobItem->sampleItem()->layers().first() == layer; const bool isLastLayer = jobItem->sampleItem()->layers().last() == layer; layer->setRoughnessEnabled(!isFirstLayer); layer->setThicknessEnabled(!isFirstLayer && !isLastLayer); + + for (auto* layout : layer->layouts()) + layout->enableDensity(!layout->totalDensityIsDefinedByInterference()); } populateParameterContainer(container, jobItem->sampleItem(), recreateBackupValues); diff --git a/GUI/Model/Sample/ParticleLayoutItem.cpp b/GUI/Model/Sample/ParticleLayoutItem.cpp index e86e9254883..5337931b463 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.cpp +++ b/GUI/Model/Sample/ParticleLayoutItem.cpp @@ -23,21 +23,6 @@ namespace { -//! Returns true if name is related to 2D interference functions. -bool isInterference2D(const QString& model_type) -{ - return model_type == Interference2DLatticeItem::M_TYPE - || model_type == Interference2DParaCrystalItem::M_TYPE - || model_type == InterferenceFinite2DLatticeItem::M_TYPE - || model_type == InterferenceHardDiskItem::M_TYPE; -} - -//! Returns true if name is related to 2D interference functions. -bool isLattice2D(SessionItem* item) -{ - return dynamic_cast<Lattice2DItem*>(item); -} - const QString density_tooltip = "Number of particles per square nanometer (particle surface density).\n " "Should be defined for disordered and 1d-ordered particle collections."; @@ -64,15 +49,7 @@ ParticleLayoutItem::ParticleLayoutItem() : SessionItem(M_TYPE) Interference2DParaCrystalItem::M_TYPE, InterferenceFinite2DLatticeItem::M_TYPE, InterferenceHardDiskItem::M_TYPE, InterferenceRadialParaCrystalItem::M_TYPE}); - mapper()->setOnChildrenChange([this](SessionItem*) { - updateDensityAppearance(); - updateDensityValue(); - }); - - mapper()->setOnAnyChildChange([this](SessionItem* item) { - if (isLattice2D(item) || (item && isLattice2D(item->parent()))) - updateDensityValue(); - }); + mapper()->setOnAnyChildChange([this](SessionItem*) { updateDensityValue(); }); } DoubleDescriptor ParticleLayoutItem::totalDensity() const @@ -157,18 +134,6 @@ void ParticleLayoutItem::removeInterference() model()->removeItem(item); } -//! Disables/enables total density property, depending on type of interference function. -//! Two dimensional interference calculates density automatically, so property should -//! be disabled. - -void ParticleLayoutItem::updateDensityAppearance() -{ - getItem(P_TOTAL_DENSITY)->setEnabled(true); - if (auto* interferenceItem = getItem(T_INTERFERENCE)) - if (isInterference2D(interferenceItem->modelType())) - getItem(P_TOTAL_DENSITY)->setEnabled(false); -} - //! Updates the value of TotalSurfaceDensity on lattice type change. void ParticleLayoutItem::updateDensityValue() @@ -190,3 +155,15 @@ void ParticleLayoutItem::updateDensityValue() } } } + +void ParticleLayoutItem::enableDensity(bool b) +{ + getItem(P_TOTAL_DENSITY)->setEnabled(b); +} + +bool ParticleLayoutItem::totalDensityIsDefinedByInterference() const +{ + const auto* interferenceItem = getItem(T_INTERFERENCE); + return dynamic_cast<const Interference2DAbstractLatticeItem*>(interferenceItem) + || dynamic_cast<const InterferenceHardDiskItem*>(interferenceItem); +} diff --git a/GUI/Model/Sample/ParticleLayoutItem.h b/GUI/Model/Sample/ParticleLayoutItem.h index 911b01e763d..45dcd29bb0c 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.h +++ b/GUI/Model/Sample/ParticleLayoutItem.h @@ -48,8 +48,14 @@ public: void updateDensityValue(); -private: - void updateDensityAppearance(); + // #baMigration Use only while not migrated to SessionModel! + void enableDensity(bool b); + + //! Returns whether total density is defined by the currently selected interference. + //! + //! Two dimensional interference calculates density automatically; in these cases the "own" + //! total density value should not be edited but set by the one from the interference. + bool totalDensityIsDefinedByInterference() const; }; template <typename T> T* ParticleLayoutItem::createInterference() diff --git a/GUI/View/SampleDesigner/ParticleLayoutForm.cpp b/GUI/View/SampleDesigner/ParticleLayoutForm.cpp index 6ee952899de..4b3e091411b 100644 --- a/GUI/View/SampleDesigner/ParticleLayoutForm.cpp +++ b/GUI/View/SampleDesigner/ParticleLayoutForm.cpp @@ -100,15 +100,7 @@ void ParticleLayoutForm::onAboutToRemoveParticle(ItemWithParticles* item) void ParticleLayoutForm::updateDensityEnabling() { - const auto* currentInterference = m_layoutItem->interference().currentItem(); - const bool enableTotalDensityInParticleLayout = - currentInterference == nullptr - || (!dynamic_cast<const Interference2DLatticeItem*>(currentInterference) - && !dynamic_cast<const Interference2DParaCrystalItem*>(currentInterference) - && !dynamic_cast<const InterferenceFinite2DLatticeItem*>(currentInterference) - && !dynamic_cast<const InterferenceHardDiskItem*>(currentInterference)); - - m_totalDensitySpinBox->setEnabled(enableTotalDensityInParticleLayout); + m_totalDensitySpinBox->setEnabled(!m_layoutItem->totalDensityIsDefinedByInterference()); } void ParticleLayoutForm::updateDensityValue() diff --git a/GUI/View/SampleDesigner/SampleEditorController.cpp b/GUI/View/SampleDesigner/SampleEditorController.cpp index 8515bf3e0c9..d26d2dbb0a3 100644 --- a/GUI/View/SampleDesigner/SampleEditorController.cpp +++ b/GUI/View/SampleDesigner/SampleEditorController.cpp @@ -421,8 +421,10 @@ void SampleEditorController::selectInterference(InterferenceForm* widget, int ne while (parent != nullptr && dynamic_cast<ParticleLayoutForm*>(parent) == nullptr) parent = parent->parentWidget(); - if (auto* particleLayoutForm = dynamic_cast<ParticleLayoutForm*>(parent)) + if (auto* particleLayoutForm = dynamic_cast<ParticleLayoutForm*>(parent)) { particleLayoutForm->updateDensityEnabling(); + particleLayoutForm->layoutItem()->updateDensityValue(); + } } void SampleEditorController::setIntegrateOverXi(LatticeTypeSelectionForm* widget, bool newValue) -- GitLab From f831e92d237956b126bb4cddcf0067e352cc3d49 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 11 Nov 2021 15:54:32 +0100 Subject: [PATCH 07/15] free ParticleLayoutItem from SessionItem signaling --- GUI/Model/From/GUISampleBuilder.cpp | 2 +- GUI/Model/Sample/ParticleLayoutItem.cpp | 54 ++++++++++--------- GUI/Model/Sample/ParticleLayoutItem.h | 16 ++++-- .../SampleDesigner/ParticleLayoutForm.cpp | 8 ++- .../SampleDesigner/SampleEditorController.cpp | 3 +- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/GUI/Model/From/GUISampleBuilder.cpp b/GUI/Model/From/GUISampleBuilder.cpp index 56cd8f585dc..3c589f04920 100644 --- a/GUI/Model/From/GUISampleBuilder.cpp +++ b/GUI/Model/From/GUISampleBuilder.cpp @@ -68,7 +68,7 @@ MultiLayerItem* GUISampleBuilder::populateSampleModel(SampleModel* sampleModel, // iterate over particle layouts for (const auto* layout : layer->layouts()) { auto* layoutItem = layerItem->addLayout(); - layoutItem->totalDensity().set(layout->totalParticleSurfaceDensity()); + layoutItem->ownDensity().set(layout->totalParticleSurfaceDensity()); layoutItem->weight().set(layout->weight()); FromDomain::setInterference(layoutItem, layout->interferenceFunction()); diff --git a/GUI/Model/Sample/ParticleLayoutItem.cpp b/GUI/Model/Sample/ParticleLayoutItem.cpp index 5337931b463..413e99a4c1e 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.cpp +++ b/GUI/Model/Sample/ParticleLayoutItem.cpp @@ -48,11 +48,9 @@ ParticleLayoutItem::ParticleLayoutItem() : SessionItem(M_TYPE) {Interference1DLatticeItem::M_TYPE, Interference2DLatticeItem::M_TYPE, Interference2DParaCrystalItem::M_TYPE, InterferenceFinite2DLatticeItem::M_TYPE, InterferenceHardDiskItem::M_TYPE, InterferenceRadialParaCrystalItem::M_TYPE}); - - mapper()->setOnAnyChildChange([this](SessionItem*) { updateDensityValue(); }); } -DoubleDescriptor ParticleLayoutItem::totalDensity() const +DoubleDescriptor ParticleLayoutItem::ownDensity() const { DoubleDescriptor d(getItem(P_TOTAL_DENSITY), Unit::nanometerPowerMinus2); d.tooltip = "Number of particles per area (particle surface density).\n " @@ -60,6 +58,34 @@ DoubleDescriptor ParticleLayoutItem::totalDensity() const return d; } +double ParticleLayoutItem::totalDensity() const +{ + if (!totalDensityIsDefinedByInterference()) + return ownDensity(); + + const auto* interferenceItem = getItem(T_INTERFERENCE); + ASSERT(interferenceItem); + + if (const auto* interLatticeItem = + dynamic_cast<const Interference2DAbstractLatticeItem*>(interferenceItem)) { + Lattice2DItem* latticeItem = interLatticeItem->latticeType().currentItem(); + try { + const double area = latticeItem->unitCellArea(); + return area == 0.0 ? 0.0 : 1.0 / area; + } catch (const std::exception&) { + // nothing to do here; new exception will be caught during job execution + return 0.0; + } + } else if (const auto* interHDItem = + dynamic_cast<const InterferenceHardDiskItem*>(interferenceItem)) + return interHDItem->density(); + else { + ASSERT(false); + return 0.0; + } +} + + DoubleDescriptor ParticleLayoutItem::weight() const { return DoubleDescriptor(getItem(P_WEIGHT), Unit::unitless); @@ -134,28 +160,6 @@ void ParticleLayoutItem::removeInterference() model()->removeItem(item); } -//! Updates the value of TotalSurfaceDensity on lattice type change. - -void ParticleLayoutItem::updateDensityValue() -{ - if (auto* interferenceItem = getItem(T_INTERFERENCE)) { - if (auto* interLatticeItem = - dynamic_cast<Interference2DAbstractLatticeItem*>(interferenceItem)) { - Lattice2DItem* latticeItem = interLatticeItem->latticeType().currentItem(); - double area = 0.0; - try { - area = latticeItem->unitCellArea(); - } catch (const std::exception&) { - // nothing to do here; new exception will be caught during job execution - } - setItemValue(P_TOTAL_DENSITY, area == 0.0 ? 0.0 : 1.0 / area); - } else if (auto* interHDItem = dynamic_cast<InterferenceHardDiskItem*>(interferenceItem)) { - double density = interHDItem->density(); - setItemValue(P_TOTAL_DENSITY, density); - } - } -} - void ParticleLayoutItem::enableDensity(bool b) { getItem(P_TOTAL_DENSITY)->setEnabled(b); diff --git a/GUI/Model/Sample/ParticleLayoutItem.h b/GUI/Model/Sample/ParticleLayoutItem.h index 45dcd29bb0c..95a1b26e47d 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.h +++ b/GUI/Model/Sample/ParticleLayoutItem.h @@ -34,7 +34,19 @@ public: ParticleLayoutItem(); - DoubleDescriptor totalDensity() const; + //! The density value which belonging only to the layout. + //! + //! This is the editable value. If an interference is present, this value may not be the one to + //! be used for building the domain layout or to be presented. For the correct value-to-use, + //! whether an interference is present or not, use totalDensity(). + DoubleDescriptor ownDensity() const; + + //! The real density. + //! + //! Returns ownDensity() if the interference is not influencing the density. If the + //! interference is defining the density, this is the interference-calculated density. + double totalDensity() const; + DoubleDescriptor weight() const; QVector<ItemWithParticles*> particles() const; @@ -46,8 +58,6 @@ public: void setInterference(InterferenceItem* interference); void removeInterference(); - void updateDensityValue(); - // #baMigration Use only while not migrated to SessionModel! void enableDensity(bool b); diff --git a/GUI/View/SampleDesigner/ParticleLayoutForm.cpp b/GUI/View/SampleDesigner/ParticleLayoutForm.cpp index 4b3e091411b..c774df6e970 100644 --- a/GUI/View/SampleDesigner/ParticleLayoutForm.cpp +++ b/GUI/View/SampleDesigner/ParticleLayoutForm.cpp @@ -34,7 +34,7 @@ ParticleLayoutForm::ParticleLayoutForm(LayerForm* parent, ParticleLayoutItem* la { FormLayouter layouter(this, ec); layouter.setContentsMargins(30, 6, 0, 0); - int rowOfTotalDensity = layouter.addValue(m_layoutItem->totalDensity()); + int rowOfTotalDensity = layouter.addValue(m_layoutItem->ownDensity()); m_totalDensitySpinBox = layouter.widgetAt<DoubleSpinBox*>(rowOfTotalDensity, QFormLayout::FieldRole); ASSERT(m_totalDensitySpinBox); @@ -105,7 +105,11 @@ void ParticleLayoutForm::updateDensityEnabling() void ParticleLayoutForm::updateDensityValue() { - m_totalDensitySpinBox->updateValue(); + if (m_layoutItem->totalDensityIsDefinedByInterference()) { + QSignalBlocker b(m_totalDensitySpinBox); + m_totalDensitySpinBox->setBaseValue(m_layoutItem->totalDensity()); + } else + m_totalDensitySpinBox->updateValue(); } void ParticleLayoutForm::updateTitle(const LayerItem* layerItem) diff --git a/GUI/View/SampleDesigner/SampleEditorController.cpp b/GUI/View/SampleDesigner/SampleEditorController.cpp index d26d2dbb0a3..7648d6e4fb5 100644 --- a/GUI/View/SampleDesigner/SampleEditorController.cpp +++ b/GUI/View/SampleDesigner/SampleEditorController.cpp @@ -348,7 +348,6 @@ void SampleEditorController::setDensityRelatedValue(InterferenceItem* interferen auto* particlelayoutItem = dynamic_cast<ParticleLayoutItem*>(interferenceItem->parent()); if (!particlelayoutItem) return; - particlelayoutItem->updateDensityValue(); // -- notify the containing particle layout UI about changed value ASSERT(m_multiLayerForm); @@ -423,7 +422,7 @@ void SampleEditorController::selectInterference(InterferenceForm* widget, int ne if (auto* particleLayoutForm = dynamic_cast<ParticleLayoutForm*>(parent)) { particleLayoutForm->updateDensityEnabling(); - particleLayoutForm->layoutItem()->updateDensityValue(); + particleLayoutForm->updateDensityValue(); } } -- GitLab From e021c014219152c96dd9ca738d8442572873d00c Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 07:55:52 +0100 Subject: [PATCH 08/15] cleanup --- GUI/Model/Sample/ParticleLayoutItem.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/GUI/Model/Sample/ParticleLayoutItem.cpp b/GUI/Model/Sample/ParticleLayoutItem.cpp index 413e99a4c1e..704f166e372 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.cpp +++ b/GUI/Model/Sample/ParticleLayoutItem.cpp @@ -21,24 +21,13 @@ #include "GUI/Model/Sample/ParticleItem.h" #include "GUI/Model/Types/DoubleDescriptor.h" -namespace { - -const QString density_tooltip = - "Number of particles per square nanometer (particle surface density).\n " - "Should be defined for disordered and 1d-ordered particle collections."; -const QString weight_tooltip = - "Weight of this particle layout.\n" - "Should be used when multiple layouts define different domains in the sample."; - -} // namespace - ParticleLayoutItem::ParticleLayoutItem() : SessionItem(M_TYPE) { setToolTip("A layout of particles"); - addProperty(P_TOTAL_DENSITY, 0.01)->setToolTip(density_tooltip); + addProperty(P_TOTAL_DENSITY, 0.01); getItem(P_TOTAL_DENSITY)->setDecimals(10); - addProperty(P_WEIGHT, 1.0)->setToolTip(weight_tooltip); + addProperty(P_WEIGHT, 1.0); registerTag(T_PARTICLES, 0, -1, {ParticleItem::M_TYPE, ParticleCoreShellItem::M_TYPE, @@ -85,10 +74,12 @@ double ParticleLayoutItem::totalDensity() const } } - DoubleDescriptor ParticleLayoutItem::weight() const { - return DoubleDescriptor(getItem(P_WEIGHT), Unit::unitless); + DoubleDescriptor d(getItem(P_WEIGHT), Unit::unitless); + d.tooltip = "Weight of this particle layout.\n" + "Should be used when multiple layouts define different domains in the sample."; + return d; } QVector<ItemWithParticles*> ParticleLayoutItem::particles() const -- GitLab From 74940f034ad9537bdef1424e03820f30ba98ebfb Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 08:14:54 +0100 Subject: [PATCH 09/15] free InterferenceItems from SessionItem signaling --- GUI/Model/Job/ParameterTreeUtils.cpp | 21 +++++++++++++++++- GUI/Model/Sample/InterferenceItems.cpp | 30 -------------------------- GUI/Model/Sample/InterferenceItems.h | 3 --- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/GUI/Model/Job/ParameterTreeUtils.cpp b/GUI/Model/Job/ParameterTreeUtils.cpp index 1363a6f03d0..d5f095b9948 100644 --- a/GUI/Model/Job/ParameterTreeUtils.cpp +++ b/GUI/Model/Job/ParameterTreeUtils.cpp @@ -19,6 +19,7 @@ #include "GUI/Model/Instrument/InstrumentItems.h" #include "GUI/Model/Job/JobItem.h" #include "GUI/Model/Material/MaterialItem.h" +#include "GUI/Model/Sample/FTDistributionItems.h" #include "GUI/Model/Sample/InterferenceItems.h" #include "GUI/Model/Sample/Lattice2DItems.h" #include "GUI/Model/Sample/LayerItem.h" @@ -148,8 +149,26 @@ void GUI::Model::ParameterTreeUtils::createParameterTree(JobItem* jobItem, layer->setRoughnessEnabled(!isFirstLayer); layer->setThicknessEnabled(!isFirstLayer && !isLastLayer); - for (auto* layout : layer->layouts()) + for (auto* layout : layer->layouts()) { layout->enableDensity(!layout->totalDensityIsDefinedByInterference()); + + // if PDF1 and PDF2 are of same type, add a number to the name + if (auto* itf = dynamic_cast<Interference2DParaCrystalItem*>( + layout->interference().currentItem())) { + SessionItem* pdf1 = itf->probabilityDistribution1().currentItem(); + SessionItem* pdf2 = itf->probabilityDistribution2().currentItem(); + + if (pdf1 && pdf2) { + if (pdf1->modelType() == pdf2->modelType()) { + pdf1->setDisplayName(pdf1->modelType() + " 0"); + pdf2->setDisplayName(pdf2->modelType() + " 1"); + } else { + pdf1->setDisplayName(pdf1->modelType()); + pdf2->setDisplayName(pdf2->modelType()); + } + } + } + } } populateParameterContainer(container, jobItem->sampleItem(), recreateBackupValues); diff --git a/GUI/Model/Sample/InterferenceItems.cpp b/GUI/Model/Sample/InterferenceItems.cpp index 54d34ea8fd9..c9f3e65a3b7 100644 --- a/GUI/Model/Sample/InterferenceItems.cpp +++ b/GUI/Model/Sample/InterferenceItems.cpp @@ -181,14 +181,6 @@ Interference2DParaCrystalItem::Interference2DParaCrystalItem() ->setToolTip("Probability distribution in first lattice direction"); addGroupProperty(P_PDF2, info) ->setToolTip("Probability distribution in second lattice direction"); - - mapper()->setOnChildPropertyChange([this](SessionItem* item, const QString& property) { - if (item->hasModelType<GroupItem>() && GroupItem::isItemsTagName(property) && isTag(P_PDF1) - && isTag(P_PDF2)) - update_distribution_displaynames(); - }); - - update_distribution_displaynames(); } std::unique_ptr<IInterference> Interference2DParaCrystalItem::createInterference() const @@ -260,28 +252,6 @@ Interference2DParaCrystalItem::probabilityDistribution2() const return SelectionDescriptor<FTDistribution2DItem*>(item<GroupItem>(P_PDF2)); } -void Interference2DParaCrystalItem::update_distribution_displaynames() -{ - auto* group1 = dynamic_cast<GroupItem*>(getItem(P_PDF1)); - auto* group2 = dynamic_cast<GroupItem*>(getItem(P_PDF2)); - - if (!group1 || !group2) - return; - - SessionItem* pdf1 = group1->currentItem(); - SessionItem* pdf2 = group2->currentItem(); - - if (pdf1 && pdf2) { - if (pdf1->modelType() == pdf2->modelType()) { - pdf1->setDisplayName(pdf1->modelType() + QString::number(0)); - pdf2->setDisplayName(pdf2->modelType() + QString::number(1)); - } else { - pdf1->setDisplayName(pdf1->modelType()); - pdf2->setDisplayName(pdf2->modelType()); - } - } -} - // --------------------------------------------------------------------------------------------- // InterferenceFinite2DLatticeItem::InterferenceFinite2DLatticeItem() diff --git a/GUI/Model/Sample/InterferenceItems.h b/GUI/Model/Sample/InterferenceItems.h index 18ee21c7b05..d62a7721718 100644 --- a/GUI/Model/Sample/InterferenceItems.h +++ b/GUI/Model/Sample/InterferenceItems.h @@ -117,9 +117,6 @@ public: SelectionDescriptor<FTDistribution2DItem*> probabilityDistribution2() const; template <typename T> T* setPDF2Type(); - -private: - void update_distribution_displaynames(); }; class InterferenceFinite2DLatticeItem : public Interference2DAbstractLatticeItem { -- GitLab From e4816af79546cc09793d9f7a687ec95a1d0537ab Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 08:30:32 +0100 Subject: [PATCH 10/15] docu --- GUI/Model/Sample/ParticleLayoutItem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/Model/Sample/ParticleLayoutItem.h b/GUI/Model/Sample/ParticleLayoutItem.h index 95a1b26e47d..47c06bb4b7d 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.h +++ b/GUI/Model/Sample/ParticleLayoutItem.h @@ -58,7 +58,7 @@ public: void setInterference(InterferenceItem* interference); void removeInterference(); - // #baMigration Use only while not migrated to SessionModel! + // #baMigration Use only while not migrated from SessionModel! void enableDensity(bool b); //! Returns whether total density is defined by the currently selected interference. -- GitLab From 88f4b0b6351d6ddf50b281657569894de1e9d2dc Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 08:44:09 +0100 Subject: [PATCH 11/15] free ItemWithParticles from SessionItem signaling --- GUI/Model/Job/ParameterTreeUtils.cpp | 3 + GUI/Model/Sample/ItemWithParticles.cpp | 32 ++++------ GUI/Model/Sample/ItemWithParticles.h | 4 ++ Tests/Unit/GUI/TestParticleCoreShell.cpp | 80 ------------------------ Tests/Unit/GUI/TestParticleItem.cpp | 20 ------ 5 files changed, 19 insertions(+), 120 deletions(-) delete mode 100644 Tests/Unit/GUI/TestParticleCoreShell.cpp diff --git a/GUI/Model/Job/ParameterTreeUtils.cpp b/GUI/Model/Job/ParameterTreeUtils.cpp index d5f095b9948..3cc4eba2a72 100644 --- a/GUI/Model/Job/ParameterTreeUtils.cpp +++ b/GUI/Model/Job/ParameterTreeUtils.cpp @@ -60,6 +60,9 @@ void handleItem(ParameterContainerItem* container, SessionItem* tree, SessionIte for (SessionItem* child : source->children()) { + if (auto* c = dynamic_cast<ItemWithParticles*>(child)) + c->enableAbundance(!c->parentHasOwnAbundance()); + // later in handleItems the position of a shell particle has to be ignored. if (auto* c = dynamic_cast<ParticleCoreShellItem*>(child)) if (c->shell()) diff --git a/GUI/Model/Sample/ItemWithParticles.cpp b/GUI/Model/Sample/ItemWithParticles.cpp index e4cb2ac8133..7d83a527051 100644 --- a/GUI/Model/Sample/ItemWithParticles.cpp +++ b/GUI/Model/Sample/ItemWithParticles.cpp @@ -25,18 +25,6 @@ #include "Sample/Particle/IParticle.h" #include "Sample/Scattering/Rotations.h" -namespace { - -bool hasOwnAbundance(const SessionItem* item) -{ - static QStringList special_parent{ParticleCoreShellItem::M_TYPE, - ParticleCompositionItem::M_TYPE, MesoCrystalItem::M_TYPE}; - - return item ? special_parent.contains(item->modelType()) : false; -} - -} // namespace - DoubleDescriptor ItemWithParticles::abundance() const { return DoubleDescriptor(getItem(P_ABUNDANCE), Unit::unitless); @@ -52,6 +40,18 @@ SessionItem* ItemWithParticles::abundanceItem() const return getItem(P_ABUNDANCE); } +void ItemWithParticles::enableAbundance(bool b) +{ + getItem(P_ABUNDANCE)->setEnabled(b); +} + +bool ItemWithParticles::parentHasOwnAbundance() const +{ + return dynamic_cast<ParticleCoreShellItem*>(parent()) + || dynamic_cast<ParticleCompositionItem*>(parent()) + || dynamic_cast<MesoCrystalItem*>(parent()); +} + R3 ItemWithParticles::position() const { return item<VectorItem>(P_POSITION)->getVector(); @@ -151,14 +151,6 @@ ItemWithParticles::ItemWithParticles(const QString& model_type, const QString& a addProperty<VectorItem>(P_POSITION)->setToolTip(position_tooltip); registerTag(T_TRANSFORMATION, 0, 1, {TransformationItem::M_TYPE}); - - mapper()->setOnParentChange([this](SessionItem* parent) { - if (hasOwnAbundance(parent)) { - setItemValue(P_ABUNDANCE, 1.0); - getItem(P_ABUNDANCE)->setEnabled(false); - } else - getItem(P_ABUNDANCE)->setEnabled(true); - }); } void ItemWithParticles::setDefaultTagTransformation() diff --git a/GUI/Model/Sample/ItemWithParticles.h b/GUI/Model/Sample/ItemWithParticles.h index 5e243ac849e..a965189ffd8 100644 --- a/GUI/Model/Sample/ItemWithParticles.h +++ b/GUI/Model/Sample/ItemWithParticles.h @@ -38,6 +38,10 @@ public: DoubleDescriptor abundance() const; void setAbundance(double abundance); SessionItem* abundanceItem() const; + bool parentHasOwnAbundance() const; + + // #baMigration Use only while not migrated from SessionModel! + void enableAbundance(bool b); R3 position() const; void setPosition(const R3& position); diff --git a/Tests/Unit/GUI/TestParticleCoreShell.cpp b/Tests/Unit/GUI/TestParticleCoreShell.cpp deleted file mode 100644 index 470a316ca84..00000000000 --- a/Tests/Unit/GUI/TestParticleCoreShell.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "GUI/Model/Material/MaterialModel.h" -#include "GUI/Model/Sample/ParticleCompositionItem.h" -#include "GUI/Model/Sample/ParticleCoreShellItem.h" -#include "GUI/Model/Sample/ParticleItem.h" -#include "GUI/Model/Sample/SampleModel.h" -#include "GUI/Model/Session/SessionItemUtils.h" -#include "GUI/Model/Types/DoubleDescriptor.h" -#include "GUI/Model/Types/VectorItem.h" -#include "Tests/GTestWrapper/google_test.h" -#include <QtTest> - -using namespace GUI::Session::ItemUtils; - -class TestParticleCoreShell : public ::testing::Test { -}; - -//! Checking that adding and removing core/shell leads to enabling/disabling of their position -//! and abundance properties. - -TEST_F(TestParticleCoreShell, propertyAppearance) -{ - SampleModel model; - MaterialModel materials; - materials.addRefractiveMaterial("Default", 1e-3, 1e-5); - - // empty coreshell particle - auto* coreshell = model.insertItem<ParticleCoreShellItem>(); - EXPECT_TRUE(coreshell->abundanceItem()->isEnabled()); - EXPECT_EQ(coreshell->abundance(), 1.0); - EXPECT_TRUE(coreshell->positionItem()->isEnabled()); - R3 pos = coreshell->positionItem()->getVector(); - EXPECT_EQ(pos.x(), 0.0); - EXPECT_EQ(pos.y(), 0.0); - EXPECT_EQ(pos.z(), 0.0); - - // adding core, and checking that abundance is disabled - auto* core = coreshell->createCore(&materials); - EXPECT_FALSE(core->abundanceItem()->isEnabled()); - EXPECT_TRUE(core->positionItem()->isEnabled()); - - // removing core, checking that abundance restored - coreshell->takeRow(ParentRow(*core)); - EXPECT_TRUE(core->abundanceItem()->isEnabled()); - EXPECT_TRUE(core->positionItem()->isEnabled()); - delete core; - - // create a shell and checking abundance disabled - coreshell->createShell(&materials); - EXPECT_FALSE(coreshell->shell()->abundanceItem()->isEnabled()); - EXPECT_FALSE(coreshell->shell()->positionItem()->isEnabled()); - // checking that position and abundance values were reset to defaults - EXPECT_EQ(coreshell->shell()->positionItem()->x(), 0.0); - EXPECT_EQ(coreshell->shell()->abundance(), 1.0); -} - - -//! Checking that abundance gets disabled in particle composition context. - -TEST_F(TestParticleCoreShell, compositionContext) -{ - SampleModel model; - - // coreshell particle - auto* coreshell = model.insertItem<ParticleCoreShellItem>(); - coreshell->setAbundance(0.2); - EXPECT_TRUE(coreshell->abundanceItem()->isEnabled()); - EXPECT_EQ(coreshell->abundance(), 0.2); - - // create composition, adding coreshell to it - auto* composition = model.insertItem<ParticleCompositionItem>(); - composition->addParticle(coreshell); - // checking abundance has switched to defaults - EXPECT_FALSE(coreshell->abundanceItem()->isEnabled()); - EXPECT_EQ(coreshell->abundance(), 1.0); - - // removing coreshell - composition->takeRow(ParentRow(*coreshell)); - EXPECT_TRUE(coreshell->abundanceItem()->isEnabled()); - delete coreshell; -} diff --git a/Tests/Unit/GUI/TestParticleItem.cpp b/Tests/Unit/GUI/TestParticleItem.cpp index 7747e629803..04145e20def 100644 --- a/Tests/Unit/GUI/TestParticleItem.cpp +++ b/Tests/Unit/GUI/TestParticleItem.cpp @@ -25,23 +25,3 @@ TEST_F(TestParticleItem, InitialState) EXPECT_EQ(group->displayName(), "Form Factor"); EXPECT_EQ(group->children().size(), 1); } - -TEST_F(TestParticleItem, compositionContext) -{ - SampleModel model; - auto* particle = model.insertItem<ParticleItem>(); - particle->setAbundance(0.2); - EXPECT_TRUE(particle->abundanceItem()->isEnabled()); - EXPECT_EQ(particle->abundance(), 0.2); - - // adding particle to composition, checking that abundance is default - auto* composition = model.insertItem<ParticleCompositionItem>(); - composition->addParticle(particle); - EXPECT_FALSE(particle->abundanceItem()->isEnabled()); - EXPECT_EQ(particle->abundance(), 1.0); - - // removing particle, checking that abundance is enabled again - composition->takeRow(ParentRow(*particle)); - EXPECT_TRUE(particle->abundanceItem()->isEnabled()); - delete particle; -} -- GitLab From 82cefa40ded0d8dd347725dc1c54180b03e205c1 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 08:46:17 +0100 Subject: [PATCH 12/15] fix tuning tree hierarchy --- GUI/Model/Job/ParameterTreeUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/Model/Job/ParameterTreeUtils.cpp b/GUI/Model/Job/ParameterTreeUtils.cpp index 3cc4eba2a72..5b148256c3d 100644 --- a/GUI/Model/Job/ParameterTreeUtils.cpp +++ b/GUI/Model/Job/ParameterTreeUtils.cpp @@ -116,7 +116,7 @@ void GUI::Model::ParameterTreeUtils::createParameterTree(JobItem* jobItem, auto* materialTopLabel = container->model()->insertItem<ParameterLabelItem>(container); materialTopLabel->setDisplayName("Materials"); for (auto* material : jobItem->materialItems().materialItems()) { - auto* materialLabel = container->model()->insertItem<ParameterLabelItem>(container); + auto* materialLabel = container->model()->insertItem<ParameterLabelItem>(materialTopLabel); materialLabel->setDisplayName(material->materialName()); DoubleDescriptors descriptors; -- GitLab From 4ee3eb6a2012530f132464f6e1024348c7dbf04a Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 11:21:35 +0100 Subject: [PATCH 13/15] rm unpractical const --- GUI/Model/Project/OutputDataIOService.cpp | 18 +++++------------- GUI/Model/Session/ModelPath.cpp | 8 ++------ GUI/Model/Session/ModelPath.h | 5 ++++- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/GUI/Model/Project/OutputDataIOService.cpp b/GUI/Model/Project/OutputDataIOService.cpp index 4d8e84edecb..f7649109643 100644 --- a/GUI/Model/Project/OutputDataIOService.cpp +++ b/GUI/Model/Project/OutputDataIOService.cpp @@ -24,7 +24,11 @@ namespace { -JobItem* parentJobItem(SaveLoadInterface* item); +JobItem* parentJobItem(SaveLoadInterface* item) +{ + auto* session_item = dynamic_cast<SessionItem*>(item); // sidecast + return dynamic_cast<JobItem*>(GUI::Model::Path::ancestor(session_item, JobItem::M_TYPE)); +} } // namespace @@ -124,15 +128,3 @@ void OutputDataIOService::cleanOldFiles(const QString& projectDir, const QString for (const auto& name : toRemove) QFile::remove(projectDir + "/" + name); } - -namespace { - -JobItem* parentJobItem(SaveLoadInterface* item) -{ - auto* session_item = dynamic_cast<SessionItem*>(item); // sidecast - const auto* jobItem = - dynamic_cast<const JobItem*>(GUI::Model::Path::ancestor(session_item, JobItem::M_TYPE)); - return const_cast<JobItem*>(jobItem); -} - -} // namespace diff --git a/GUI/Model/Session/ModelPath.cpp b/GUI/Model/Session/ModelPath.cpp index 5f74fd2790d..75c05a8ca63 100644 --- a/GUI/Model/Session/ModelPath.cpp +++ b/GUI/Model/Session/ModelPath.cpp @@ -80,13 +80,9 @@ bool GUI::Model::Path::isValidItem(SessionModel* model, SessionItem* item, return false; } -//! Returns ancestor of given modelType for given item. -//! For example, returns corresponding jobItem owning ParameterItem via ParameterContainer. - -const SessionItem* GUI::Model::Path::ancestor(const SessionItem* item, - const QString& requiredModelType) +SessionItem* GUI::Model::Path::ancestor(SessionItem* item, const QString& requiredModelType) { - const SessionItem* cur = item; + SessionItem* cur = item; while (cur && cur->modelType() != requiredModelType) cur = cur->parent(); diff --git a/GUI/Model/Session/ModelPath.h b/GUI/Model/Session/ModelPath.h index 6959793cd73..94cc394a0cc 100644 --- a/GUI/Model/Session/ModelPath.h +++ b/GUI/Model/Session/ModelPath.h @@ -38,7 +38,10 @@ SessionItem* getItemFromPath(const QString& relPath, const SessionItem* parent); bool isValidItem(SessionModel* model, SessionItem* item, const QModelIndex& parent); -const SessionItem* ancestor(const SessionItem* item, const QString& requiredModelType); +//! Returns ancestor of given modelType for given item. +//! +//! For example, returns corresponding jobItem owning ParameterItem via ParameterContainer. +SessionItem* ancestor(SessionItem* item, const QString& requiredModelType); } // namespace GUI::Model::Path -- GitLab From 7de5461b69c1decb1f30ba838354322eb1aa64a5 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 14:47:52 +0100 Subject: [PATCH 14/15] add signals to sample model and use them instead of generic SessionModel signals --- GUI/Model/Data/ApplicationModels.cpp | 1 - GUI/Model/Project/ProjectDocument.cpp | 5 +++++ GUI/Model/Sample/SampleModel.cpp | 8 ++++++++ GUI/Model/Sample/SampleModel.h | 4 ++++ GUI/View/SampleDesigner/ScriptPanel.cpp | 9 +-------- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/GUI/Model/Data/ApplicationModels.cpp b/GUI/Model/Data/ApplicationModels.cpp index b6b1a083daa..3888f2d2224 100644 --- a/GUI/Model/Data/ApplicationModels.cpp +++ b/GUI/Model/Data/ApplicationModels.cpp @@ -34,7 +34,6 @@ ApplicationModels::ApplicationModels(QObject* parent) m_realDataModel = new RealDataModel(this); m_jobModel = new JobModel(this); - connectModel(m_sampleModel); connectModel(m_instrumentModel); connectModel(m_realDataModel); connectModel(m_jobModel); diff --git a/GUI/Model/Project/ProjectDocument.cpp b/GUI/Model/Project/ProjectDocument.cpp index b97371e418e..4b3a5a83c09 100644 --- a/GUI/Model/Project/ProjectDocument.cpp +++ b/GUI/Model/Project/ProjectDocument.cpp @@ -63,6 +63,11 @@ ProjectDocument::ProjectDocument(const QString& projectFileName) connect(&m_materials, &MaterialModel::materialChanged, this, &ProjectDocument::onModelChanged, Qt::UniqueConnection); + connect(sampleModel(), &SampleModel::sampleAddedOrRemoved, this, + &ProjectDocument::onModelChanged, Qt::UniqueConnection); + connect(sampleModel(), &SampleModel::sampleChanged, this, &ProjectDocument::onModelChanged, + Qt::UniqueConnection); + m_linkManager = std::make_unique<LinkInstrumentManager>(instrumentModel(), realDataModel()); setObjectName("ProjectDocument"); if (!projectFileName.isEmpty()) diff --git a/GUI/Model/Sample/SampleModel.cpp b/GUI/Model/Sample/SampleModel.cpp index c5d28d0cd74..e8db5919479 100644 --- a/GUI/Model/Sample/SampleModel.cpp +++ b/GUI/Model/Sample/SampleModel.cpp @@ -16,6 +16,7 @@ #include "GUI/Model/Group/PropertyItem.h" #include "GUI/Model/Sample/ItemWithMaterial.h" #include "GUI/Model/Sample/MultiLayerItem.h" +#include "GUI/Model/Session/ModelPath.h" #include "GUI/Model/Session/ModelUtils.h" #include <QApplication> #include <QFontMetrics> @@ -80,11 +81,13 @@ QVector<ItemWithMaterial*> SampleModel::itemsWithMaterial() const MultiLayerItem* SampleModel::addMultiLayer() { return insertItem<MultiLayerItem>(); + emit sampleAddedOrRemoved(); } void SampleModel::removeMultiLayer(MultiLayerItem* item) { removeItem(item); + emit sampleAddedOrRemoved(); } void SampleModel::onDataChanged(const QModelIndex& index, const QModelIndex&) @@ -93,4 +96,9 @@ void SampleModel::onDataChanged(const QModelIndex& index, const QModelIndex&) auto* const item = itemForIndex(index); if (item) emit itemDataChanged(item); + + auto* multiLayerItem = + dynamic_cast<MultiLayerItem*>(GUI::Model::Path::ancestor(item, MultiLayerItem::M_TYPE)); + if (multiLayerItem) + emit sampleChanged(multiLayerItem); } diff --git a/GUI/Model/Sample/SampleModel.h b/GUI/Model/Sample/SampleModel.h index 591441a369e..bc6426cd49c 100644 --- a/GUI/Model/Sample/SampleModel.h +++ b/GUI/Model/Sample/SampleModel.h @@ -49,6 +49,10 @@ signals: //! item is the one given in the first index of dataChanged(idx1,idx2) void itemDataChanged(const SessionItem* item); +signals: + void sampleAddedOrRemoved(); + void sampleChanged(MultiLayerItem* multiLayerItem); + private: void onDataChanged(const QModelIndex& index, const QModelIndex&); }; diff --git a/GUI/View/SampleDesigner/ScriptPanel.cpp b/GUI/View/SampleDesigner/ScriptPanel.cpp index 6c74ff967d3..cf03707013a 100644 --- a/GUI/View/SampleDesigner/ScriptPanel.cpp +++ b/GUI/View/SampleDesigner/ScriptPanel.cpp @@ -84,20 +84,13 @@ void ScriptPanel::updateEditor() void ScriptPanel::setEditorConnected(bool isConnected) { if (isConnected) { - connect(m_sampleModel, &SampleModel::rowsInserted, m_updateTimer, + connect(m_sampleModel, &SampleModel::sampleChanged, m_updateTimer, &UpdateTimer::scheduleUpdate); - connect(m_sampleModel, &SampleModel::rowsRemoved, m_updateTimer, - &UpdateTimer::scheduleUpdate); - connect(m_sampleModel, &SampleModel::itemDataChanged, m_updateTimer, - &UpdateTimer::scheduleUpdate); - connect(m_sampleModel, &SampleModel::modelReset, this, &ScriptPanel::updateEditor, - Qt::UniqueConnection); connect(m_updateTimer, &UpdateTimer::timeToUpdate, this, &ScriptPanel::updateEditor, Qt::UniqueConnection); m_updateTimer->scheduleUpdate(); } else { - m_sampleModel->disconnect(this); m_sampleModel->disconnect(m_updateTimer); m_updateTimer->disconnect(this); } -- GitLab From f61af160d76c65e985fe65d80e2c93fb50caa073 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 9 Dec 2021 15:54:23 +0100 Subject: [PATCH 15/15] fix GUI->domain transformation --- GUI/Model/To/ToDomain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/Model/To/ToDomain.cpp b/GUI/Model/To/ToDomain.cpp index 3e2ff9eed3e..133d2f506dc 100644 --- a/GUI/Model/To/ToDomain.cpp +++ b/GUI/Model/To/ToDomain.cpp @@ -147,7 +147,7 @@ GUI::Transform::ToDomain::buildMultiLayer(const MultiLayerItem& multiLayerItem) if (P_layer) { const auto roughness = layerItem->roughness().currentItem(); auto P_roughness = createLayerRoughness(roughness); - if (P_roughness && !isLastLayer) + if (P_roughness && !isFirstLayer) P_multilayer->addLayerWithTopRoughness(*P_layer, *P_roughness); else P_multilayer->addLayer(*P_layer); -- GitLab