Skip to content
Snippets Groups Projects
SampleForm.cpp 6.56 KiB
Newer Older
  • Learn to ignore specific revisions
  • //  ************************************************************************************************
    //
    //  BornAgain: simulate and fit reflection and scattering
    //
    
    //! @file      GUI/View/Sample/SampleForm.cpp
    
    //! @brief     Implements class SampleForm.
    
    //!
    //! @homepage  http://www.bornagainproject.org
    //! @license   GNU General Public License v3 or higher (see COPYING)
    //! @copyright Forschungszentrum Jülich GmbH 2021
    //! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
    //
    //  ************************************************************************************************
    
    
    #include "GUI/View/Sample/SampleForm.h"
    
    #include "GUI/Model/Sample/SampleItem.h"
    
    #include "GUI/View/Sample/CompoundForm.h"
    #include "GUI/View/Sample/CoreAndShellForm.h"
    #include "GUI/View/Sample/HeinzFormLayout.h"
    #include "GUI/View/Sample/LayerForm.h"
    #include "GUI/View/Sample/MesocrystalForm.h"
    #include "GUI/View/Sample/ParticleForm.h"
    #include "GUI/View/Sample/ParticleLayoutForm.h"
    #include "GUI/View/Sample/SampleEditorController.h"
    
    #include "GUI/View/Tool/ActionFactory.h"
    
    #include "GUI/View/Tool/LayoutUtil.h"
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    #include "GUI/View/Widget/ApplicationSettings.h"
    #include "GUI/View/Widget/GroupBoxes.h"
    
    #include <QBoxLayout>
    
    #include <QLineEdit>
    #include <QTextEdit>
    
    
    namespace {
    
    //! Widget with a button to add a layer (the "add layer" buttons shown between layers)
    class AddLayerWidget : public QWidget {
    public:
        AddLayerWidget(QWidget* parent, LayerItem* layer, SampleEditorController* ec)
    
            : QWidget(parent)
            , m_layer(layer)
    
            auto* l = new QHBoxLayout(this);
    
            l->setContentsMargins(0, 0, 0, 0);
    
            auto* btn = new QPushButton("Add layer", this);
            l->addStretch();
            l->addWidget(btn);
            l->addStretch();
    
            connect(btn, &QPushButton::clicked, [=] { ec->addLayerItem(layer); });
    
    SampleForm::SampleForm(SampleItem* sampleItem, SampleEditorController* ec)
    
        : m_layout(new QVBoxLayout(this))
        , m_sampleItem(sampleItem)
    
    {
        setAttribute(Qt::WA_StyledBackground, true);
    
    
        m_layout->setAlignment(Qt::AlignTop);
    
    
        auto* summary = new CollapsibleGroupBox("Summary and layer-independent parameters", this,
                                                sampleItem->expandInfo);
    
        m_layout->addWidget(summary, 0, Qt::AlignTop);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        summary->setObjectName("SampleSummary");
    
    
        auto* gLayout = new HeinzFormLayout(ec);
        summary->body()->setLayout(gLayout);
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        auto* nameEdit = new QLineEdit;
    
        gLayout->addBoldRow("Name:", nameEdit);
    
        nameEdit->setText(sampleItem->sampleName());
    
        nameEdit->setFixedWidth(585);
    
        connect(nameEdit, &QLineEdit::textEdited, ec, &SampleEditorController::setSampleName);
    
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        auto* descriptionEdit = new QTextEdit;
    
        gLayout->addBoldRow("Description:", descriptionEdit);
    
        descriptionEdit->setFixedWidth(585);
    
        descriptionEdit->setFixedHeight(60);
    
        descriptionEdit->setAcceptRichText(false);
        descriptionEdit->setTabChangesFocus(true);
    
        descriptionEdit->setPlainText(sampleItem->description());
    
        connect(descriptionEdit, &QTextEdit::textChanged, [this, descriptionEdit] {
    
            m_ec->setSampleDescription(descriptionEdit->toPlainText());
        });
    
        gLayout->addValue(sampleItem->crossCorrLength());
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        // Processing external field is not implemented yet, so temporary disable it (see issue #654)
    
        // m_layout->addVector(sampleItem->externalField(), false);
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        auto* showInRealspaceAction = ActionFactory::createShowInRealspaceAction(
    
            this, "sample", [this] { m_ec->requestViewInRealspace(m_sampleItem); });
    
        summary->addTitleAction(showInRealspaceAction);
    
        for (auto* layer : sampleItem->layerItems()) {
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
            m_layout->addWidget(new AddLayerWidget(this, layer, m_ec), 0, Qt::AlignTop);
            m_layout->addWidget(new LayerForm(this, layer, m_ec), 0, Qt::AlignTop);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        m_layout->addWidget(new AddLayerWidget(this, nullptr, m_ec), 0, Qt::AlignTop);
    
        m_layout->setSizeConstraint(QLayout::SetMinimumSize);
    }
    
    
    void SampleForm::onLayerAdded(LayerItem* layerItem)
    
        const int rowInMultiLayer = m_sampleItem->layerItems().indexOf(layerItem);
    
    
        const int rowInLayout = rowInMultiLayer * 2 + 1;
    
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        m_layout->insertWidget(rowInLayout, new LayerForm(this, layerItem, m_ec), 0, Qt::AlignTop);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        m_layout->insertWidget(rowInLayout, new AddLayerWidget(this, layerItem, m_ec), 0, Qt::AlignTop);
    
    void SampleForm::onLayerMoved(LayerItem* layerItem)
    
    {
        LayerForm* wl = nullptr;
        AddLayerWidget* al = nullptr;
        for (int index = 0; index < m_layout->count(); index++) {
    
            if (auto* w = dynamic_cast<AddLayerWidget*>(m_layout->itemAt(index)->widget()))
    
                if (w->m_layer == layerItem) {
                    al = w;
                    m_layout->takeAt(index);
                    break;
                }
        }
    
        for (int index = 0; index < m_layout->count(); index++) {
    
            if (auto* w = dynamic_cast<LayerForm*>(m_layout->itemAt(index)->widget()))
    
                if (w->layerItem() == layerItem) {
                    wl = w;
                    m_layout->takeAt(index);
                    break;
                }
        }
    
    
        const int rowInMultiLayer = m_sampleItem->layerItems().indexOf(layerItem);
    
        const int rowInLayout = rowInMultiLayer * 2 + 1;
    
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        m_layout->insertWidget(rowInLayout, wl, 0, Qt::AlignTop);
    
    Mikhail Svechnikov's avatar
    Mikhail Svechnikov committed
        m_layout->insertWidget(rowInLayout, al, 0, Qt::AlignTop);
    
    void SampleForm::onAboutToRemoveLayer(LayerItem* layerItem)
    
    {
        LayerForm* layerForm = nullptr;
        AddLayerWidget* addLayerWidget = nullptr;
    
        for (auto* c : findChildren<QWidget*>()) {
            if (auto* w = dynamic_cast<AddLayerWidget*>(c))
    
                if (w->m_layer == layerItem)
                    addLayerWidget = w;
    
    
            if (auto* w = dynamic_cast<LayerForm*>(c)) {
    
                    layerForm = w;
            }
        }
    
        if (layerForm) {
            // delete editors which are subscribed to SessionItems
    
            GUI::Util::Layout::clearLayout(layerForm->layout());
    
            layerForm->hide();
            layerForm->setParent(nullptr); // so it is not findable in update routines
            layerForm->deleteLater();      // delete later (this is the sender)
        }
    
    
        delete addLayerWidget;
    
    LayerForm* SampleForm::findNextLayerForm(QWidget* w)
    
    {
        while (w != nullptr && dynamic_cast<LayerForm*>(w) == nullptr) {
    
            const auto index = m_layout->indexOf(w);
    
            if (index + 1 < m_layout->count())
                w = m_layout->itemAt(index + 1)->widget();
    
            else
                return nullptr;