diff --git a/GUI/Models/GUIDomainSampleVisitor.cpp b/GUI/Models/GUIDomainSampleVisitor.cpp index c0a18d115ea8c44b3fd254df0c13766e0b73a402..6e881b9bbb308e3ac697f2e18ece223f8a27f5e5 100644 --- a/GUI/Models/GUIDomainSampleVisitor.cpp +++ b/GUI/Models/GUIDomainSampleVisitor.cpp @@ -45,13 +45,13 @@ #include "Sample/SoftParticle/SoftParticles.h" #include <boost/polymorphic_cast.hpp> -using boost::polymorphic_downcast; +using boost::polymorphic_cast; namespace { template <typename T> T* AddFormFactorItem(SessionItem* parent) { if (parent->hasModelType<ParticleItem>()) - return polymorphic_downcast<ParticleItem*>(parent)->setFormFactorType<T>(); + return polymorphic_cast<ParticleItem*>(parent)->setFormFactorType<T>(); else if (parent->modelType() == "MesoCrystal") return parent->setGroupPropertyType<T>(MesoCrystalItem::P_OUTER_SHAPE); else @@ -130,7 +130,7 @@ void GUIDomainSampleVisitor::visit(const MultiLayer* sample) void GUIDomainSampleVisitor::visit(const Particle* sample) { - auto particle_item = polymorphic_downcast<ParticleItem*> + auto particle_item = polymorphic_cast<ParticleItem*> (InsertIParticle(sample, ParticleItem::M_TYPE)); particle_item->setMaterial(createMaterialFromDomain(sample->material())); } diff --git a/GUI/Models/ItemWithMaterial.cpp b/GUI/Models/ItemWithMaterial.cpp index 7da9728b87dc2c68c6695d7919fd00f573c8b84d..b86b5d90121043bce9c909bcd69ac9b0f25f99a4 100644 --- a/GUI/Models/ItemWithMaterial.cpp +++ b/GUI/Models/ItemWithMaterial.cpp @@ -17,8 +17,6 @@ const QString ItemWithMaterial::P_MATERIAL = "Material"; -ItemWithMaterial::~ItemWithMaterial() = default; - ExternalProperty ItemWithMaterial::material() const { return getItemValue(P_MATERIAL).value<ExternalProperty>(); diff --git a/GUI/Models/ItemWithMaterial.h b/GUI/Models/ItemWithMaterial.h index 4f8a4261888ec54c66d514c10fdc6ddd9b0b9222..1b17cf138eea3b626aca4aba97a006cd8f910503 100644 --- a/GUI/Models/ItemWithMaterial.h +++ b/GUI/Models/ItemWithMaterial.h @@ -18,13 +18,11 @@ #include "GUI/Models/ExternalProperty.h" #include "GUI/Models/SessionGraphicsItem.h" -class BA_CORE_API_ ItemWithMaterial : public SessionGraphicsItem { +class BA_CORE_API_ ItemWithMaterial : public virtual SessionGraphicsItem { private: static const QString P_MATERIAL; public: - virtual ~ItemWithMaterial() = 0; - ExternalProperty material() const; void setMaterial(const ExternalProperty& material); static bool isMaterialPropertyName(const QString& name); diff --git a/GUI/Models/ItemWithParticles.cpp b/GUI/Models/ItemWithParticles.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cea0ad1133ca32a1fc2787fd0b862eda7179b7cb --- /dev/null +++ b/GUI/Models/ItemWithParticles.cpp @@ -0,0 +1,55 @@ +// ************************************************************************************************ +// +// BornAgain: simulate and fit reflection and scattering +// +//! @file GUI/Models/ItemWithParticles.cpp +//! @brief Implements class ItemWithParticles +//! +//! @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/Models/ItemWithParticles.h" +#include "GUI/Models/VectorItem.h" +#include "GUI/Models/SessionItemUtils.h" + +const QString ItemWithParticles::P_ABUNDANCE = "Abundance"; +const QString ItemWithParticles::P_POSITION = "Position Offset"; +const QString ItemWithParticles::T_TRANSFORMATION = "Transformation Tag"; + +ItemWithParticles::ItemWithParticles(const QString& model_type, const QString& abundance_tooltip, + const QString& position_tooltip) + : SessionGraphicsItem(model_type) +{ + addProperty(P_ABUNDANCE, 1.0) + ->setLimits(RealLimits::limited(0.0, 1.0)) + .setDecimals(3) + .setToolTip(abundance_tooltip); + addProperty<VectorItem>(P_POSITION)->setToolTip(position_tooltip); + + registerTag(T_TRANSFORMATION, 0, 1, QStringList() << "Rotation"); + + mapper()->setOnParentChange([this](SessionItem* parent) { + if (GUI::Session::ItemUtils::HasOwnAbundance(parent)) { + setItemValue(P_ABUNDANCE, 1.0); + getItem(P_ABUNDANCE)->setEnabled(false); + if (isShellParticle()) { + auto pos = item<VectorItem>(P_POSITION); + pos->setVector(kvector_t()); + pos->setEnabled(false); + } + } else { + getItem(P_ABUNDANCE)->setEnabled(true); + if (isShellParticle()) + item<VectorItem>(P_POSITION)->setEnabled(true); + } + }); +} + +bool ItemWithParticles::isShellParticle() const +{ + return false; +} diff --git a/GUI/Models/ItemWithParticles.h b/GUI/Models/ItemWithParticles.h new file mode 100644 index 0000000000000000000000000000000000000000..51de33901e8163b1b0573c847467ad4782772124 --- /dev/null +++ b/GUI/Models/ItemWithParticles.h @@ -0,0 +1,35 @@ +// ************************************************************************************************ +// +// BornAgain: simulate and fit reflection and scattering +// +//! @file GUI/Models/ItemWithParticles.h +//! @brief Defines abstract item with a material property +//! +//! @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_MODELS_ITEMWITHPARTICLES_H +#define BORNAGAIN_GUI_MODELS_ITEMWITHPARTICLES_H + +#include "GUI/Models/ExternalProperty.h" +#include "GUI/Models/SessionGraphicsItem.h" + +class BA_CORE_API_ ItemWithParticles : public virtual SessionGraphicsItem { +public: + static const QString P_ABUNDANCE; + static const QString P_POSITION; + static const QString T_TRANSFORMATION; + +protected: + ItemWithParticles(const QString& model_type, const QString& abundance_tooltip, + const QString& position_tooltip); + +private: + virtual bool isShellParticle() const; +}; + +#endif // BORNAGAIN_GUI_MODELS_ITEMWITHMATERIAL_H diff --git a/GUI/Models/LayerItem.cpp b/GUI/Models/LayerItem.cpp index 0f0119ec57113a5c4d6d4d14a2e73ad1786374fc..d7478fbbf44b12338ca54055bc16260ecafd050f 100644 --- a/GUI/Models/LayerItem.cpp +++ b/GUI/Models/LayerItem.cpp @@ -30,7 +30,7 @@ const QString LayerItem::T_LAYOUTS = "Layout tag"; const QString LayerItem::M_TYPE = "Layer"; -LayerItem::LayerItem() : ItemWithMaterial(M_TYPE) +LayerItem::LayerItem() : SessionGraphicsItem(M_TYPE), ItemWithMaterial(M_TYPE) { setToolTip("A layer with thickness and material"); addProperty(P_THICKNESS, 0.0) diff --git a/GUI/Models/MaterialItemUtils.cpp b/GUI/Models/MaterialItemUtils.cpp index 76929fece518851587cba383ec76a2c0a6b0db55..653d34075f1d464860334044df8298965ac3fd2a 100644 --- a/GUI/Models/MaterialItemUtils.cpp +++ b/GUI/Models/MaterialItemUtils.cpp @@ -160,9 +160,9 @@ QVector<SessionItem*> GUI::Model::MaterialItemUtils::materialPropertyItems(Sessi } if (model_type == ParticleItem::M_TYPE) - materials.append(static_cast<ParticleItem*>(item)->materialPropertyItems()); + materials.append(dynamic_cast<ParticleItem*>(item)->materialPropertyItems()); else if (model_type == "ParticleCoreShell") - materials.append(static_cast<ParticleCoreShellItem*>(item)->materialPropertyItems()); + materials.append(dynamic_cast<ParticleCoreShellItem*>(item)->materialPropertyItems()); else throw Error("Error in GUI::Model::MaterialItemUtils::materialProperties: cannot handle " "passed model type '" diff --git a/GUI/Models/MaterialPropertyController.cpp b/GUI/Models/MaterialPropertyController.cpp index a497f2721e598e4ffdcdcb0e112af8221a650623..c74dd5dca320e40eb177afbdcba51793212c3aef 100644 --- a/GUI/Models/MaterialPropertyController.cpp +++ b/GUI/Models/MaterialPropertyController.cpp @@ -22,7 +22,7 @@ #include <QVector> #include <boost/polymorphic_cast.hpp> -using boost::polymorphic_downcast; +using boost::polymorphic_cast; MaterialPropertyController::MaterialPropertyController(QObject* parent) : QObject(parent), m_materialModel(nullptr), m_sampleModel(nullptr) @@ -124,7 +124,7 @@ QVector<ItemWithMaterial*> MaterialPropertyController::relatedSampleItems() if (SessionItem* item = m_sampleModel->itemForIndex(index)) if (materialRelated.contains(item->modelType())) - result.push_back(polymorphic_downcast<ItemWithMaterial*>(item)); + result.push_back(polymorphic_cast<ItemWithMaterial*>(item)); }); return result; diff --git a/GUI/Models/MesoCrystalItem.cpp b/GUI/Models/MesoCrystalItem.cpp index b0317757cc6eb36b274def82d64e5c17a3a8fb3d..853034a82114e58c8be84caa4c72a2416a23fc7b 100644 --- a/GUI/Models/MesoCrystalItem.cpp +++ b/GUI/Models/MesoCrystalItem.cpp @@ -52,23 +52,17 @@ const QString MesoCrystalItem::P_VECTOR_A = "First lattice vector"; const QString MesoCrystalItem::P_VECTOR_B = "Second lattice vector"; const QString MesoCrystalItem::P_VECTOR_C = "Third lattice vector"; -// TODO make derived from ParticleItem - -MesoCrystalItem::MesoCrystalItem() : SessionGraphicsItem("MesoCrystal") +MesoCrystalItem::MesoCrystalItem() + : SessionGraphicsItem("MesoCrystal"), + ItemWithParticles("MesoCrystal", abundance_tooltip, position_tooltip) { setToolTip("A 3D crystal structure of nanoparticles"); addGroupProperty(P_OUTER_SHAPE, "Form Factor"); - addProperty(ParticleItem::P_ABUNDANCE, 1.0) - ->setLimits(RealLimits::limited(0.0, 1.0)) - .setDecimals(3) - .setToolTip(abundance_tooltip); - addProperty<VectorItem>(P_VECTOR_A)->setToolTip(lattice_vector1_tooltip); addProperty<VectorItem>(P_VECTOR_B)->setToolTip(lattice_vector2_tooltip); addProperty<VectorItem>(P_VECTOR_C)->setToolTip(lattice_vector3_tooltip); - addProperty<VectorItem>(ParticleItem::P_POSITION)->setToolTip(position_tooltip); registerTag(T_BASIS_PARTICLE, 0, 1, QStringList() << ParticleItem::M_TYPE @@ -76,22 +70,11 @@ MesoCrystalItem::MesoCrystalItem() : SessionGraphicsItem("MesoCrystal") << "ParticleComposition" << "MesoCrystal"); setDefaultTag(T_BASIS_PARTICLE); - - registerTag(ParticleItem::T_TRANSFORMATION, 0, 1, QStringList() << "Rotation"); - - mapper()->setOnParentChange([this](SessionItem* parent) { - if (GUI::Session::ItemUtils::HasOwnAbundance(parent)) { - setItemValue(ParticleItem::P_ABUNDANCE, 1.0); - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(false); - } else { - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(true); - } - }); } VectorItem* MesoCrystalItem::positionItem() const { - return item<VectorItem>(ParticleItem::P_POSITION); + return item<VectorItem>(P_POSITION); } std::unique_ptr<MesoCrystal> MesoCrystalItem::createMesoCrystal() const @@ -130,16 +113,16 @@ std::unique_ptr<IParticle> MesoCrystalItem::getBasis() const QVector<SessionItem*> childlist = children(); for (int i = 0; i < childlist.size(); ++i) { if (childlist[i]->hasModelType<ParticleItem>()) { - auto* particle_item = static_cast<ParticleItem*>(childlist[i]); + auto* particle_item = dynamic_cast<ParticleItem*>(childlist[i]); return particle_item->createParticle(); } else if (childlist[i]->modelType() == "ParticleCoreShell") { - auto* particle_coreshell_item = static_cast<ParticleCoreShellItem*>(childlist[i]); + auto* particle_coreshell_item = dynamic_cast<ParticleCoreShellItem*>(childlist[i]); return particle_coreshell_item->createParticleCoreShell(); } else if (childlist[i]->modelType() == "ParticleComposition") { - auto* particlecomposition_item = static_cast<ParticleCompositionItem*>(childlist[i]); + auto* particlecomposition_item = dynamic_cast<ParticleCompositionItem*>(childlist[i]); return particlecomposition_item->createParticleComposition(); } else if (childlist[i]->modelType() == "MesoCrystal") { - auto* mesocrystal_item = static_cast<MesoCrystalItem*>(childlist[i]); + auto* mesocrystal_item = dynamic_cast<MesoCrystalItem*>(childlist[i]); return mesocrystal_item->createMesoCrystal(); } } diff --git a/GUI/Models/MesoCrystalItem.h b/GUI/Models/MesoCrystalItem.h index 4b8a3a7b0d165e33bbd51a3d2a6f02ec8e6b5ac8..84bf240d95327b438aa0918591250fdb0392ed06 100644 --- a/GUI/Models/MesoCrystalItem.h +++ b/GUI/Models/MesoCrystalItem.h @@ -15,7 +15,7 @@ #ifndef BORNAGAIN_GUI_MODELS_MESOCRYSTALITEM_H #define BORNAGAIN_GUI_MODELS_MESOCRYSTALITEM_H -#include "GUI/Models/SessionGraphicsItem.h" +#include "GUI/Models/ItemWithParticles.h" #include "Sample/Lattice/Lattice3D.h" class IFormFactor; @@ -23,7 +23,7 @@ class IParticle; class MesoCrystal; class VectorItem; -class BA_CORE_API_ MesoCrystalItem : public SessionGraphicsItem { +class BA_CORE_API_ MesoCrystalItem : public ItemWithParticles { public: static const QString P_OUTER_SHAPE; static const QString T_BASIS_PARTICLE; diff --git a/GUI/Models/MultiLayerItem.cpp b/GUI/Models/MultiLayerItem.cpp index 64d12559ab16665187a26d966d1cbee4168d3548..ab72da339c78711f97dee16d670689e5797eb050 100644 --- a/GUI/Models/MultiLayerItem.cpp +++ b/GUI/Models/MultiLayerItem.cpp @@ -48,7 +48,7 @@ QVector<SessionItem*> MultiLayerItem::materialPropertyItems() { QVector<SessionItem*> result; for (auto layer_item : getItems(T_LAYERS)) - result.append(static_cast<LayerItem*>(layer_item)->materialPropertyItems()); + result.append(dynamic_cast<LayerItem*>(layer_item)->materialPropertyItems()); return result; } diff --git a/GUI/Models/ParticleCompositionItem.cpp b/GUI/Models/ParticleCompositionItem.cpp index 6268d8bd256c186821abeb2b858d9046a1f00043..48d36de52d817a34c27be63ba28b1e99d8b9aa1e 100644 --- a/GUI/Models/ParticleCompositionItem.cpp +++ b/GUI/Models/ParticleCompositionItem.cpp @@ -33,69 +33,52 @@ const QString position_tooltip = "Relative position of the particle's reference const QString ParticleCompositionItem::T_PARTICLES = "Particle Tag"; -// TODO make ParticleCoreShellItem and ParticleItem to derive from common base. - -ParticleCompositionItem::ParticleCompositionItem() : SessionGraphicsItem("ParticleComposition") +ParticleCompositionItem::ParticleCompositionItem() + : SessionGraphicsItem("ParticleComposition"), + ItemWithParticles("ParticleComposition", abundance_tooltip, position_tooltip) { setToolTip("Composition of particles with fixed positions"); - addProperty(ParticleItem::P_ABUNDANCE, 1.0) - ->setLimits(RealLimits::limited(0.0, 1.0)) - .setDecimals(3) - .setToolTip(abundance_tooltip); - - addProperty<VectorItem>(ParticleItem::P_POSITION)->setToolTip(position_tooltip); - registerTag(T_PARTICLES, 0, -1, QStringList() << ParticleItem::M_TYPE << "ParticleCoreShell" << "ParticleComposition" << "MesoCrystal"); setDefaultTag(T_PARTICLES); - registerTag(ParticleItem::T_TRANSFORMATION, 0, 1, QStringList() << "Rotation"); - - mapper()->setOnParentChange([this](SessionItem* parent) { - if (GUI::Session::ItemUtils::HasOwnAbundance(parent)) { - setItemValue(ParticleItem::P_ABUNDANCE, 1.0); - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(false); - } else { - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(true); - } - }); } VectorItem* ParticleCompositionItem::positionItem() const { - return item<VectorItem>(ParticleItem::P_POSITION); + return item<VectorItem>(P_POSITION); } std::unique_ptr<ParticleComposition> ParticleCompositionItem::createParticleComposition() const { - double abundance = getItemValue(ParticleItem::P_ABUNDANCE).toDouble(); + double abundance = getItemValue(P_ABUNDANCE).toDouble(); auto P_composition = std::make_unique<ParticleComposition>(); P_composition->setAbundance(abundance); QVector<SessionItem*> childlist = children(); for (int i = 0; i < childlist.size(); ++i) { if (childlist[i]->hasModelType<ParticleItem>()) { - auto* particle_item = static_cast<ParticleItem*>(childlist[i]); + auto* particle_item = dynamic_cast<ParticleItem*>(childlist[i]); auto P_particle = particle_item->createParticle(); if (P_particle) { P_composition->addParticle(*P_particle); } } else if (childlist[i]->modelType() == "ParticleCoreShell") { - auto* particle_coreshell_item = static_cast<ParticleCoreShellItem*>(childlist[i]); + auto* particle_coreshell_item = dynamic_cast<ParticleCoreShellItem*>(childlist[i]); auto P_particle_coreshell = particle_coreshell_item->createParticleCoreShell(); if (P_particle_coreshell) { P_composition->addParticle(*P_particle_coreshell); } } else if (childlist[i]->modelType() == "ParticleComposition") { - auto* particlecomposition_item = static_cast<ParticleCompositionItem*>(childlist[i]); + auto* particlecomposition_item = dynamic_cast<ParticleCompositionItem*>(childlist[i]); auto P_child_composition = particlecomposition_item->createParticleComposition(); if (P_child_composition) { P_composition->addParticle(*P_child_composition); } } else if (childlist[i]->modelType() == "MesoCrystal") { - auto* mesocrystal_item = static_cast<MesoCrystalItem*>(childlist[i]); + auto* mesocrystal_item = dynamic_cast<MesoCrystalItem*>(childlist[i]); auto P_child_meso = mesocrystal_item->createMesoCrystal(); if (P_child_meso) { P_composition->addParticle(*P_child_meso); diff --git a/GUI/Models/ParticleCompositionItem.h b/GUI/Models/ParticleCompositionItem.h index 97d37c9d07776d2548ff98e916b8afe91b593a29..2e0f6ad4c7d712272bc8e3cde7b01694b1fb3a75 100644 --- a/GUI/Models/ParticleCompositionItem.h +++ b/GUI/Models/ParticleCompositionItem.h @@ -15,12 +15,12 @@ #ifndef BORNAGAIN_GUI_MODELS_PARTICLECOMPOSITIONITEM_H #define BORNAGAIN_GUI_MODELS_PARTICLECOMPOSITIONITEM_H -#include "GUI/Models/SessionGraphicsItem.h" +#include "GUI/Models/ItemWithParticles.h" #include "Sample/Particle/ParticleComposition.h" class VectorItem; -class BA_CORE_API_ ParticleCompositionItem : public SessionGraphicsItem { +class BA_CORE_API_ ParticleCompositionItem : public ItemWithParticles { public: static const QString T_PARTICLES; ParticleCompositionItem(); diff --git a/GUI/Models/ParticleCoreShellItem.cpp b/GUI/Models/ParticleCoreShellItem.cpp index 525363a464a7e149a549f587577e1298dc43bc67..88ca0c1e559dc3f66bc0ddff93d53fa398c2ee2d 100644 --- a/GUI/Models/ParticleCoreShellItem.cpp +++ b/GUI/Models/ParticleCoreShellItem.cpp @@ -34,41 +34,24 @@ const QString position_tooltip = "Relative position of the particle's reference const QString ParticleCoreShellItem::T_CORE = "Core tag"; const QString ParticleCoreShellItem::T_SHELL = "Shell tag"; -// TODO make ParticleCoreShellItem and ParticleItem to derive from common base. - -ParticleCoreShellItem::ParticleCoreShellItem() : SessionGraphicsItem("ParticleCoreShell") +ParticleCoreShellItem::ParticleCoreShellItem() + : SessionGraphicsItem("ParticleCoreShell"), + ItemWithParticles("ParticleCoreShell", abundance_tooltip, position_tooltip) { setToolTip("A particle with a core/shell geometry"); - addProperty(ParticleItem::P_ABUNDANCE, 1.0) - ->setLimits(RealLimits::limited(0.0, 1.0)) - .setDecimals(3) - .setToolTip(abundance_tooltip); - - addProperty<VectorItem>(ParticleItem::P_POSITION)->setToolTip(position_tooltip); - registerTag(T_CORE, 0, 1, {ParticleItem::M_TYPE}); registerTag(T_SHELL, 0, 1, {ParticleItem::M_TYPE}); - registerTag(ParticleItem::T_TRANSFORMATION, 0, 1, QStringList() << "Rotation"); - - mapper()->setOnParentChange([this](SessionItem* parent) { - if (GUI::Session::ItemUtils::HasOwnAbundance(parent)) { - setItemValue(ParticleItem::P_ABUNDANCE, 1.0); - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(false); - } else { - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(true); - } - }); } VectorItem* ParticleCoreShellItem::positionItem() const { - return item<VectorItem>(ParticleItem::P_POSITION); + return item<VectorItem>(P_POSITION); } std::unique_ptr<ParticleCoreShell> ParticleCoreShellItem::createParticleCoreShell() const { - double abundance = getItemValue(ParticleItem::P_ABUNDANCE).toDouble(); + double abundance = getItemValue(P_ABUNDANCE).toDouble(); std::unique_ptr<Particle> P_core{}; std::unique_ptr<Particle> P_shell{}; auto core_item = dynamic_cast<ParticleItem*>(getItem(T_CORE)); @@ -89,10 +72,10 @@ std::unique_ptr<ParticleCoreShell> ParticleCoreShellItem::createParticleCoreShel QVector<SessionItem*> ParticleCoreShellItem::materialPropertyItems() { QVector<SessionItem*> result; - if (auto core = static_cast<ParticleItem*>(getItem(T_CORE))) + if (auto core = dynamic_cast<ParticleItem*>(getItem(T_CORE))) result.append(core->materialPropertyItems()); - if (auto shell = static_cast<ParticleItem*>(getItem(T_SHELL))) + if (auto shell = dynamic_cast<ParticleItem*>(getItem(T_SHELL))) result.append(shell->materialPropertyItems()); return result; diff --git a/GUI/Models/ParticleCoreShellItem.h b/GUI/Models/ParticleCoreShellItem.h index 41278e3170e03837a9c59b580625f493b506d32e..1e0048127875d6e494f64d5448b7c568c1d03d8d 100644 --- a/GUI/Models/ParticleCoreShellItem.h +++ b/GUI/Models/ParticleCoreShellItem.h @@ -15,12 +15,12 @@ #ifndef BORNAGAIN_GUI_MODELS_PARTICLECORESHELLITEM_H #define BORNAGAIN_GUI_MODELS_PARTICLECORESHELLITEM_H -#include "GUI/Models/SessionGraphicsItem.h" +#include "GUI/Models/ItemWithParticles.h" class ParticleCoreShell; class VectorItem; -class BA_CORE_API_ ParticleCoreShellItem : public SessionGraphicsItem { +class BA_CORE_API_ ParticleCoreShellItem : public ItemWithParticles { public: static const QString T_CORE; static const QString T_SHELL; diff --git a/GUI/Models/ParticleItem.cpp b/GUI/Models/ParticleItem.cpp index eb15c372bb3dfd185bbc807ad2d27d8c4bcf1dc1..ef8cca506a092884241f343d90f35128b08cc907 100644 --- a/GUI/Models/ParticleItem.cpp +++ b/GUI/Models/ParticleItem.cpp @@ -33,27 +33,16 @@ const QString position_tooltip = "Relative position of the particle's reference } // namespace const QString ParticleItem::P_FORM_FACTOR = "Form Factor"; -const QString ParticleItem::P_ABUNDANCE = QString::fromStdString("Abundance"); -const QString ParticleItem::P_POSITION = "Position Offset"; -const QString ParticleItem::T_TRANSFORMATION = "Transformation Tag"; const QString ParticleItem::M_TYPE = "Particle"; -ParticleItem::ParticleItem() : ItemWithMaterial(M_TYPE) +ParticleItem::ParticleItem() + : SessionGraphicsItem(M_TYPE), ItemWithMaterial(M_TYPE), + ItemWithParticles(M_TYPE, abundance_tooltip, position_tooltip) { addGroupProperty(P_FORM_FACTOR, "Form Factor"); - addProperty(P_ABUNDANCE, 1.0) - ->setLimits(RealLimits::limited(0.0, 1.0)) - .setDecimals(3) - .setToolTip(abundance_tooltip); - addProperty<VectorItem>(P_POSITION)->setToolTip(position_tooltip); - - registerTag(T_TRANSFORMATION, 0, 1, QStringList() << "Rotation"); setDefaultTag(T_TRANSFORMATION); - - mapper()->setOnParentChange( - [this](SessionItem* newParent) { updatePropertiesAppearance(newParent); }); } VectorItem* ParticleItem::positionItem() const @@ -63,9 +52,9 @@ VectorItem* ParticleItem::positionItem() const std::unique_ptr<Particle> ParticleItem::createParticle() const { - auto& ffItem = groupItem<FormFactorItem>(ParticleItem::P_FORM_FACTOR); + auto& ffItem = groupItem<FormFactorItem>(P_FORM_FACTOR); auto material = GUI::Transform::ToDomain::createDomainMaterial(*this); - double abundance = getItemValue(ParticleItem::P_ABUNDANCE).toDouble(); + double abundance = getItemValue(P_ABUNDANCE).toDouble(); auto particle = std::make_unique<Particle>(*material, *ffItem.createFormFactor()); particle->setAbundance(abundance); @@ -103,24 +92,6 @@ GroupItem* ParticleItem::formFactorItem() const return item<GroupItem>(P_FORM_FACTOR); } -//! Updates enabled/disabled for particle position and particle abundance depending on context. - -void ParticleItem::updatePropertiesAppearance(SessionItem* newParent) -{ - if (GUI::Session::ItemUtils::HasOwnAbundance(newParent)) { - setItemValue(ParticleItem::P_ABUNDANCE, 1.0); - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(false); - if (isShellParticle()) { - auto pos = positionItem(); - pos->setVector(kvector_t()); - pos->setEnabled(false); - } - } else { - getItem(ParticleItem::P_ABUNDANCE)->setEnabled(true); - positionItem()->setEnabled(true); - } -} - //! Returns true if this particle is a shell particle. bool ParticleItem::isShellParticle() const diff --git a/GUI/Models/ParticleItem.h b/GUI/Models/ParticleItem.h index 93cf29c582514266763a0b4623611d9a7c6bc413..a9035e65d3a81439d56526da57ae36df61a2a2a5 100644 --- a/GUI/Models/ParticleItem.h +++ b/GUI/Models/ParticleItem.h @@ -16,21 +16,18 @@ #define BORNAGAIN_GUI_MODELS_PARTICLEITEM_H #include "GUI/Models/ItemWithMaterial.h" +#include "GUI/Models/ItemWithParticles.h" class FormFactorItem; class GroupItem; class Particle; class VectorItem; -class BA_CORE_API_ ParticleItem : public ItemWithMaterial { +class BA_CORE_API_ ParticleItem : public ItemWithMaterial, public ItemWithParticles { private: static const QString P_FORM_FACTOR; public: - static const QString P_ABUNDANCE; - static const QString P_POSITION; - static const QString T_TRANSFORMATION; - static const QString M_TYPE; ParticleItem(); @@ -47,8 +44,7 @@ public: GroupItem* formFactorItem() const; private: - void updatePropertiesAppearance(SessionItem*); - bool isShellParticle() const; + virtual bool isShellParticle() const override; bool parentIsParticleLayout() const; }; diff --git a/GUI/Models/SessionItem.h b/GUI/Models/SessionItem.h index e02ca42254e17ccbbaa2957bfba6a57cfd36a82c..dd01e885c216e32a566c3732080531fda1c6170e 100644 --- a/GUI/Models/SessionItem.h +++ b/GUI/Models/SessionItem.h @@ -343,7 +343,7 @@ template <typename T> QVector<T*> SessionItem::childrenOfType() const QVector<T*> result; for (auto child : m_children) if (child->modelType() == T::M_TYPE) - result.append(static_cast<T*>(child)); + result.append(dynamic_cast<T*>(child)); return result; } diff --git a/GUI/Models/SessionModel.h b/GUI/Models/SessionModel.h index dd677eac37fbd2a0cd7d4ff9a9a55af684404405..049a86fb9a08cbebc05f330899b169a07e88166d 100644 --- a/GUI/Models/SessionModel.h +++ b/GUI/Models/SessionModel.h @@ -139,7 +139,7 @@ private: template <typename T> T* SessionModel::insertItem(SessionItem* parent, int row, QString tag) { - return static_cast<T*>(insertNewItem(T().modelType(), parent, row, tag)); + return dynamic_cast<T*>(insertNewItem(T().modelType(), parent, row, tag)); } template <typename T> T* SessionModel::insertItem(const QModelIndex& parent, int row, QString tag) diff --git a/GUI/Models/TransformToDomain.cpp b/GUI/Models/TransformToDomain.cpp index 4cdf23197d94f36868b3867d1d5506b30d543b41..ea7b67e6b67edd73c3de467f8d5d76f60e870287 100644 --- a/GUI/Models/TransformToDomain.cpp +++ b/GUI/Models/TransformToDomain.cpp @@ -108,16 +108,16 @@ std::unique_ptr<IParticle> GUI::Transform::ToDomain::createIParticle(const Sessi { std::unique_ptr<IParticle> P_particle; if (item.hasModelType<ParticleItem>()) { - auto& particle_item = static_cast<const ParticleItem&>(item); + auto& particle_item = dynamic_cast<const ParticleItem&>(item); P_particle = particle_item.createParticle(); } else if (item.modelType() == "ParticleCoreShell") { - auto& particle_coreshell_item = static_cast<const ParticleCoreShellItem&>(item); + auto& particle_coreshell_item = dynamic_cast<const ParticleCoreShellItem&>(item); P_particle = particle_coreshell_item.createParticleCoreShell(); } else if (item.modelType() == "ParticleComposition") { - auto& particle_composition_item = static_cast<const ParticleCompositionItem&>(item); + auto& particle_composition_item = dynamic_cast<const ParticleCompositionItem&>(item); P_particle = particle_composition_item.createParticleComposition(); } else if (item.modelType() == "MesoCrystal") { - auto& mesocrystal_item = static_cast<const MesoCrystalItem&>(item); + auto& mesocrystal_item = dynamic_cast<const MesoCrystalItem&>(item); P_particle = mesocrystal_item.createMesoCrystal(); } return P_particle; diff --git a/GUI/Views/SampleDesigner/ParticleView.cpp b/GUI/Views/SampleDesigner/ParticleView.cpp index e35a848df26967569eda7bdd024df970a612c6a6..65a5f81292856cc24b7407e596cd9c95bdabbaf6 100644 --- a/GUI/Views/SampleDesigner/ParticleView.cpp +++ b/GUI/Views/SampleDesigner/ParticleView.cpp @@ -97,7 +97,7 @@ void ParticleView::updatePixmap() if (!getItem()) return; - QString ff_type = static_cast<ParticleItem*>(getItem())->formFactorItem()->currentType(); + QString ff_type = dynamic_cast<ParticleItem*>(getItem())->formFactorItem()->currentType(); QString filename = QString(":/widgetbox/images/ff_%1_64x64.png").arg(ff_type); m_pixmap = QPixmap(filename); } @@ -107,6 +107,6 @@ void ParticleView::updateToolTip() if (!getItem()) return; - auto ffItem = static_cast<ParticleItem*>(getItem())->formFactorItem()->currentItem(); + auto ffItem = dynamic_cast<ParticleItem*>(getItem())->formFactorItem()->currentItem(); setToolTip(ffItem->toolTip()); } diff --git a/Tests/UnitTests/GUI/TestComponentUtils.cpp b/Tests/UnitTests/GUI/TestComponentUtils.cpp index 011c75f1411b21efebeb222bdedc5199540353cc..5168878ba3ad249e06580a0df1fb1ce931ec6023 100644 --- a/Tests/UnitTests/GUI/TestComponentUtils.cpp +++ b/Tests/UnitTests/GUI/TestComponentUtils.cpp @@ -21,11 +21,14 @@ TEST_F(TestComponentUtils, test_componentItems) CylinderItem* ffCylinder = dynamic_cast<CylinderItem*>(ffItem); EXPECT_NE(ffCylinder, nullptr); - QList<const SessionItem*> expectedList = QList<const SessionItem*>() - << particle->materialItem() << group - << ffCylinder->radiusItem() << ffCylinder->heightItem() - << particle->getItem(ParticleItem::P_ABUNDANCE) - << particle->getItem(ParticleItem::P_POSITION); + QList<const SessionItem*> expectedList = + QList<const SessionItem*>() + << particle->materialItem() + << particle->getItem(ParticleItem::P_ABUNDANCE) + << particle->getItem(ParticleItem::P_POSITION) + << group + << ffCylinder->radiusItem() + << ffCylinder->heightItem(); auto itemList = GUI::Model::ComponentUtils::componentItems(*particle); EXPECT_EQ(itemList.size(), 6); @@ -42,10 +45,12 @@ TEST_F(TestComponentUtils, test_componentItemsFFChange) particle->setFormFactorType<FullSphereItem>(); FullSphereItem* sphereItem = dynamic_cast<FullSphereItem*>(particle->formFactor()); - QList<const SessionItem*> expectedList = - QList<const SessionItem*>() << particle->materialItem() << group << sphereItem->radiusItem() - << particle->getItem(ParticleItem::P_ABUNDANCE) - << particle->getItem(ParticleItem::P_POSITION); + QList<const SessionItem*> expectedList = QList<const SessionItem*>() + << particle->materialItem() + << particle->getItem(ParticleItem::P_ABUNDANCE) + << particle->getItem(ParticleItem::P_POSITION) + << group + << sphereItem->radiusItem(); auto itemList = GUI::Model::ComponentUtils::componentItems(*particle); EXPECT_EQ(itemList.size(), 5);