From e580a0ce25f97a6eb7ae497065e859a905eec3eb Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Fri, 12 Nov 2021 08:39:05 +0100 Subject: [PATCH] implement density of InterferenceHardDiskItem --- GUI/Model/Sample/ParticleLayoutItem.h | 2 +- GUI/View/Edit/DoubleSpinBox.cpp | 6 ++++++ GUI/View/Edit/DoubleSpinBox.h | 5 +++++ GUI/View/SampleDesigner/FormLayouter.cpp | 17 ++++++++++++--- GUI/View/SampleDesigner/FormLayouter.h | 15 ++++++++++++- GUI/View/SampleDesigner/InterferenceForm.cpp | 11 ++++++++++ .../SampleDesigner/ParticleLayoutForm.cpp | 5 +++++ GUI/View/SampleDesigner/ParticleLayoutForm.h | 5 +++++ .../SampleDesigner/SampleEditorController.cpp | 21 +++++++++++++++++++ .../SampleDesigner/SampleEditorController.h | 10 +++++++++ 10 files changed, 92 insertions(+), 5 deletions(-) diff --git a/GUI/Model/Sample/ParticleLayoutItem.h b/GUI/Model/Sample/ParticleLayoutItem.h index 896271fb5bf..85a193db159 100644 --- a/GUI/Model/Sample/ParticleLayoutItem.h +++ b/GUI/Model/Sample/ParticleLayoutItem.h @@ -45,10 +45,10 @@ public: SelectionDescriptor<InterferenceItem*> interference() const; template <typename T> T* createInterference(); void setInterference(InterferenceItem* interference); + void updateDensityValue(); private: void updateDensityAppearance(); - void updateDensityValue(); }; template <typename T> T* ParticleLayoutItem::createInterference() diff --git a/GUI/View/Edit/DoubleSpinBox.cpp b/GUI/View/Edit/DoubleSpinBox.cpp index 7b176a3d162..9a2c7fd2bea 100644 --- a/GUI/View/Edit/DoubleSpinBox.cpp +++ b/GUI/View/Edit/DoubleSpinBox.cpp @@ -97,3 +97,9 @@ Unit DoubleSpinBox::baseUnit() const return std::get<Unit>(m_valueDescriptor.unit); } + +void DoubleSpinBox::updateValue() +{ + QSignalBlocker b(this); + setBaseValue(m_valueDescriptor.get()); +} diff --git a/GUI/View/Edit/DoubleSpinBox.h b/GUI/View/Edit/DoubleSpinBox.h index 05922f2f9c5..2eb15a12ef2 100644 --- a/GUI/View/Edit/DoubleSpinBox.h +++ b/GUI/View/Edit/DoubleSpinBox.h @@ -45,6 +45,11 @@ public: //! valueDescriptor().unit Unit baseUnit() const; + //! Update the shown value to the one contained in the value descriptor. + //! + //! No signal will be emitted if the new value has changed. + void updateValue(); + signals: //! Emitted whenever the value changes. //! diff --git a/GUI/View/SampleDesigner/FormLayouter.cpp b/GUI/View/SampleDesigner/FormLayouter.cpp index 183744a157a..1d5461ed0cb 100644 --- a/GUI/View/SampleDesigner/FormLayouter.cpp +++ b/GUI/View/SampleDesigner/FormLayouter.cpp @@ -159,7 +159,20 @@ int FormLayouter::addValue(const DoubleDescriptor& d) return m_formLayout->rowCount() - 1; } +int FormLayouter::addValue(const DoubleDescriptor& d, function<void(double)> onValueChange) +{ + insertValue(m_formLayout->rowCount(), d, onValueChange); + return m_formLayout->rowCount() - 1; +} + void FormLayouter::insertValue(int row, const DoubleDescriptor& d) +{ + auto* ec = m_ec; // to allow copy-capture in the following lambda + insertValue(row, d, [ec, d](double newValue) { ec->setDouble(newValue, d); }); +} + +void FormLayouter::insertValue(int row, const DoubleDescriptor& d, + function<void(double)> onValueChange) { auto labelText = d.label; if (!labelText.endsWith(":")) @@ -170,9 +183,7 @@ void FormLayouter::insertValue(int row, const DoubleDescriptor& d) label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); auto* editor = new DoubleSpinBox(m_formLayout->parentWidget(), d); - auto* ec = m_ec; // to allow copy-capture in the following lambda - QObject::connect(editor, &DoubleSpinBox::baseValueChanged, - [ec, d](double newValue) { ec->setDouble(newValue, d); }); + QObject::connect(editor, &DoubleSpinBox::baseValueChanged, onValueChange); label->setBuddy(editor); diff --git a/GUI/View/SampleDesigner/FormLayouter.h b/GUI/View/SampleDesigner/FormLayouter.h index 72da21ba360..23475231ed5 100644 --- a/GUI/View/SampleDesigner/FormLayouter.h +++ b/GUI/View/SampleDesigner/FormLayouter.h @@ -93,9 +93,17 @@ public: //! to the SampleEditorController which has been overhanded in the constructor of this //! FormLayouter. It is connected to SampleEditorController::setDouble(). If a different method //! should be called (e.g. for a special undo functionality), this method is not sufficient. It - //! would have to be done "manually". Returns the newly added row. + //! would have to be done "manually" or with the overload which takes a slot (see below). + //! Returns the newly added row. int addValue(const DoubleDescriptor& d); + //! Adds a row with a bold printed label and a DoubleSpinBox. + //! + //! Same as above, but the called slot in case of a value change has to be overhanded. + //! Use this only if the standard (calling SampleEditorController::setDouble()) is not + //! sufficient. + int addValue(const DoubleDescriptor& d, function<void(double)> onValueChange); + //! Adds a row with a bold printed label and a QSpinBox. //! //! Right now in the sample model there is no uint value which has a unit, therefore no unit @@ -108,6 +116,11 @@ public: //! Same functionality as addValue(), please read there. void insertValue(int row, const DoubleDescriptor& d); + //! Inserts a row with a bold printed label and a DoubleSpinBox. + //! + //! Same functionality as addValue(), please read there. + void insertValue(int row, const DoubleDescriptor& d, function<void(double)> onValueChange); + //! Adds a row with a bold printed label and a set of DoubleDescriptors. //! //! The label describes the set of the Descriptors and is located in the first column of the diff --git a/GUI/View/SampleDesigner/InterferenceForm.cpp b/GUI/View/SampleDesigner/InterferenceForm.cpp index ae5859a154f..a92374c7d64 100644 --- a/GUI/View/SampleDesigner/InterferenceForm.cpp +++ b/GUI/View/SampleDesigner/InterferenceForm.cpp @@ -66,6 +66,16 @@ void InterferenceForm::createInterferenceWidgets() { FormLayouter layouter(this, m_ec); auto* interference = m_layoutItem->interference().currentItem(); + + // Some values in interference settings affect the total density in the particle layout. To + // provide all the updating (data & UI), the method + // SampleEditorController::setDensityRelatedValueValue has to be called (instead of + // SampleEditorController::setDouble). For this we have the following lambda to add a value: + const auto addDensityRelatedValue = [&](DoubleDescriptor d) { + layouter.addValue( + d, [=](double newValue) { m_ec->setDensityRelatedValue(interference, newValue, d); }); + }; + if (auto* itf = dynamic_cast<Interference1DLatticeItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->length()); @@ -81,6 +91,7 @@ void InterferenceForm::createInterferenceWidgets() } else if (auto* itf = dynamic_cast<InterferenceHardDiskItem*>(interference)) { layouter.addValue(itf->positionVariance()); layouter.addValue(itf->radius()); + addDensityRelatedValue(itf->density()); } // #baLayerEditor implement missing interference function types } diff --git a/GUI/View/SampleDesigner/ParticleLayoutForm.cpp b/GUI/View/SampleDesigner/ParticleLayoutForm.cpp index 074d026f3e0..2bd268b4892 100644 --- a/GUI/View/SampleDesigner/ParticleLayoutForm.cpp +++ b/GUI/View/SampleDesigner/ParticleLayoutForm.cpp @@ -109,3 +109,8 @@ void ParticleLayoutForm::updateDensityEnabling() m_totalDensitySpinBox->setEnabled(enableTotalDensityInParticleLayout); } + +void ParticleLayoutForm::updateDensityValue() +{ + m_totalDensitySpinBox->updateValue(); +} diff --git a/GUI/View/SampleDesigner/ParticleLayoutForm.h b/GUI/View/SampleDesigner/ParticleLayoutForm.h index 9f04171613a..b49067d7dc7 100644 --- a/GUI/View/SampleDesigner/ParticleLayoutForm.h +++ b/GUI/View/SampleDesigner/ParticleLayoutForm.h @@ -45,6 +45,11 @@ public: //! the property shown in the particle layout shall be disabled. void updateDensityEnabling(); + //! Update the shown density value. + //! + //! This does not update any internal values, it only refreshes the shown value. + void updateDensityValue(); + private: QFormLayout* m_layout; ParticleLayoutItem* m_layoutItem; diff --git a/GUI/View/SampleDesigner/SampleEditorController.cpp b/GUI/View/SampleDesigner/SampleEditorController.cpp index b5f29975760..3806e49097c 100644 --- a/GUI/View/SampleDesigner/SampleEditorController.cpp +++ b/GUI/View/SampleDesigner/SampleEditorController.cpp @@ -13,6 +13,7 @@ // ************************************************************************************************ #include "GUI/View/SampleDesigner/SampleEditorController.h" +#include "GUI/Model/Sample/InterferenceItems.h" #include "GUI/Model/Sample/LayerItem.h" #include "GUI/Model/Sample/MesoCrystalItem.h" #include "GUI/Model/Sample/MultiLayerItem.h" @@ -309,6 +310,26 @@ void SampleEditorController::setMaterialValue(ItemWithMaterial* item, double new c->updateValues(); } +void SampleEditorController::setDensityRelatedValue(InterferenceItem* interferenceItem, + double newValue, DoubleDescriptor d) +{ + setDouble(newValue, d); + + // -- notify the containing particle layout about changed value + auto* particlelayoutItem = dynamic_cast<ParticleLayoutItem*>(interferenceItem->parent()); + if (!particlelayoutItem) + return; + particlelayoutItem->updateDensityValue(); + + // -- notify the containing particle layout UI about changed value + ASSERT(m_multiLayerForm); + for (auto* c : m_multiLayerForm->findChildren<ParticleLayoutForm*>()) + if (c->layoutItem() == particlelayoutItem) { + c->updateDensityValue(); + break; + } +} + void SampleEditorController::onStartingToMoveLayer() { ASSERT(m_multiLayerForm); diff --git a/GUI/View/SampleDesigner/SampleEditorController.h b/GUI/View/SampleDesigner/SampleEditorController.h index d8ab9b2dc68..545e157880a 100644 --- a/GUI/View/SampleDesigner/SampleEditorController.h +++ b/GUI/View/SampleDesigner/SampleEditorController.h @@ -33,6 +33,7 @@ class SelectionContainerForm; class AbstractSelectionDescriptor; class InterferenceForm; class SessionItem; +class InterferenceItem; //! Class to modify a sample from the layer oriented sample editor. //! @@ -82,6 +83,15 @@ public: void selectMaterial(ItemWithMaterial* item, const QString& newMaterialIdentifier); void setMaterialValue(ItemWithMaterial* item, double newValue, DoubleDescriptor d); + //! Set an interference function's value which affects the total particle density of the + //! containing particle layout. + //! + //! Some values in interference settings affect the total density in the particle layout which + //! contains this interference function. Call this method to provide all the related updating + //! (data & UI). + void setDensityRelatedValue(InterferenceItem* interferenceItem, double newValue, + DoubleDescriptor d); + void onStartingToMoveLayer(); void onStoppedToMoveLayer(QWidget* widgetToMove, QWidget* moveAboveThisWidget); -- GitLab