From c33c06810e9afdec5c0dcbcffd8a5345e7a41d35 Mon Sep 17 00:00:00 2001 From: Walter Van Herck <w.van.herck@fz-juelich.de> Date: Fri, 22 Feb 2013 13:56:34 +0100 Subject: [PATCH] Added appropriate behavior for InstrumentView (implemented signal/slots) --- Core/Tools/inc/RealParameterWrapper.h | 1 + GUI/coregui/Models/SimulationDataModel.cpp | 9 + GUI/coregui/Models/SimulationDataModel.h | 3 + GUI/coregui/Views/InstrumentView.cpp | 269 +++++++++++++++++++-- GUI/coregui/Views/InstrumentView.h | 43 +++- GUI/coregui/mainwindow/mainwindow.cpp | 18 +- GUI/coregui/mainwindow/mainwindow.h | 8 +- 7 files changed, 316 insertions(+), 35 deletions(-) diff --git a/Core/Tools/inc/RealParameterWrapper.h b/Core/Tools/inc/RealParameterWrapper.h index e006c2ee68b..a26f1def622 100644 --- a/Core/Tools/inc/RealParameterWrapper.h +++ b/Core/Tools/inc/RealParameterWrapper.h @@ -58,6 +58,7 @@ public: //! throw exception if parameter was not initialized with proper value void checkNull() const { if(isNull()) throw NullPointerException("RealParameterWrapper::getValue() -> Attempt to access uninitialised pointer."); } + //! print the parameter's address to an output stream friend std::ostream &operator<<(std::ostream &ostr, const RealParameterWrapper &p) { ostr << p.m_data; return ostr; } private: //! swap function diff --git a/GUI/coregui/Models/SimulationDataModel.cpp b/GUI/coregui/Models/SimulationDataModel.cpp index 465ffa362a6..edfe48695d5 100644 --- a/GUI/coregui/Models/SimulationDataModel.cpp +++ b/GUI/coregui/Models/SimulationDataModel.cpp @@ -27,6 +27,15 @@ void SimulationDataModel::addInstrument(QString name, Instrument *p_instrument) } } +void SimulationDataModel::changeInstrument(QString name, Instrument *p_instrument) +{ + if (!m_instruments.contains(name)) { + return; + } + delete m_instruments[name]; + m_instruments[name] = p_instrument; +} + void SimulationDataModel::addSimulationParameters(QString name, SimulationParameters *p_simulation_parameters) { if (!m_simulation_parameters.contains(name)) { diff --git a/GUI/coregui/Models/SimulationDataModel.h b/GUI/coregui/Models/SimulationDataModel.h index 6cc9d7fb90c..68b93ae760c 100644 --- a/GUI/coregui/Models/SimulationDataModel.h +++ b/GUI/coregui/Models/SimulationDataModel.h @@ -59,6 +59,9 @@ public: //! add instrument to list void addInstrument(QString name, Instrument *p_instrument); + //! replace instrument with given name + void changeInstrument(QString name, Instrument *p_instrument); + //! add simulation parameters to list void addSimulationParameters(QString name, SimulationParameters *p_simulation_parameters); private: diff --git a/GUI/coregui/Views/InstrumentView.cpp b/GUI/coregui/Views/InstrumentView.cpp index 0388ae693aa..e42237e5d12 100644 --- a/GUI/coregui/Views/InstrumentView.cpp +++ b/GUI/coregui/Views/InstrumentView.cpp @@ -1,48 +1,83 @@ #include "InstrumentView.h" +#include "SimulationDataModel.h" +#include "Units.h" +#include "ExperimentConstants.h" + +#include <boost/lexical_cast.hpp> + #include <QGroupBox> #include <QPushButton> #include <QVBoxLayout> #include <QComboBox> +#include <QPushButton> #include <QLabel> #include <QGridLayout> #include <QLineEdit> #include <QCheckBox> #include <QDoubleSpinBox> +#include <QInputDialog> +#include <QMessageBox> -InstrumentManager::InstrumentManager(QWidget *parent) +InstrumentView::InstrumentView(SimulationDataModel *p_simulation_data_model, QWidget *parent) : QWidget(parent) + , mp_simulation_data_model(p_simulation_data_model) + , mp_cached_instrument(0) { // selection of instrument by name QGroupBox *instrumentListGroup = new QGroupBox(tr("Instrument List")); // instrument combo box QLabel *nameLabel = new QLabel(tr("Select Instrument:")); - QComboBox *instrumentBox = new QComboBox; - instrumentBox->addItem(tr("Default GISAXS")); + instrumentBox = new QComboBox; + if (parent) { + instrumentBox->addItems(mp_simulation_data_model->getInstrumentList().keys()); + } + addInstrumentButton = new QPushButton(tr("Add...")); + saveInstrumentButton = new QPushButton(tr("Save")); + saveInstrumentButton->setEnabled(false); // layout - QHBoxLayout *instrumentListLayout = new QHBoxLayout; - instrumentListLayout->addWidget(nameLabel); - instrumentListLayout->addWidget(instrumentBox); + QGridLayout *instrumentListLayout = new QGridLayout; + instrumentListLayout->addWidget(nameLabel, 0, 0); + instrumentListLayout->addWidget(instrumentBox, 0, 1); + QHBoxLayout *addAndSaveButtonLayout = new QHBoxLayout; + addAndSaveButtonLayout->addWidget(saveInstrumentButton); + addAndSaveButtonLayout->addWidget(addInstrumentButton); + instrumentListLayout->addLayout(addAndSaveButtonLayout, 1, 1); instrumentListGroup->setLayout(instrumentListLayout); // beam parameters QGroupBox *beamParamsGroup = new QGroupBox(tr("Beam Parameters")); // intensity QLabel *beamIntensityLabel = new QLabel(tr("Intensity (1/s):")); - QDoubleSpinBox *beamIntensityEdit = new QDoubleSpinBox; + beamIntensityEdit = new QLineEdit; + // wavelength + QLabel *beamWavelengthLabel = new QLabel(tr("Wavelength (nanometer):")); + beamWavelengthEdit = new QDoubleSpinBox; + beamWavelengthEdit->setSingleStep(0.1); + beamWavelengthEdit->setDecimals(3); + beamWavelengthEdit->setMaximum(100.); // incoming angles QLabel *beamAlphaInLabel = new QLabel(tr("Inclination Angle (degrees):")); - QDoubleSpinBox *beamAlphaInEdit = new QDoubleSpinBox; + beamAlphaInEdit = new QDoubleSpinBox; + beamAlphaInEdit->setSingleStep(0.01); + beamAlphaInEdit->setDecimals(5); + beamAlphaInEdit->setMaximum(90.); QLabel *beamPhiInLabel = new QLabel(tr("Azimuthal Angle (degrees):")); - QDoubleSpinBox *beamPhiInEdit = new QDoubleSpinBox; + beamPhiInEdit = new QDoubleSpinBox; + beamPhiInEdit->setSingleStep(0.01); + beamPhiInEdit->setDecimals(5); + beamPhiInEdit->setMinimum(-90.); + beamPhiInEdit->setMaximum(90.); // layout QGridLayout *beamParamsLayout = new QGridLayout; beamParamsLayout->addWidget(beamIntensityLabel, 0, 0); beamParamsLayout->addWidget(beamIntensityEdit, 0, 1); - beamParamsLayout->addWidget(beamAlphaInLabel, 1, 0); - beamParamsLayout->addWidget(beamAlphaInEdit, 1, 1); - beamParamsLayout->addWidget(beamPhiInLabel, 2, 0); - beamParamsLayout->addWidget(beamPhiInEdit, 2, 1); + beamParamsLayout->addWidget(beamWavelengthLabel, 1, 0); + beamParamsLayout->addWidget(beamWavelengthEdit, 1, 1); + beamParamsLayout->addWidget(beamAlphaInLabel, 2, 0); + beamParamsLayout->addWidget(beamAlphaInEdit, 2, 1); + beamParamsLayout->addWidget(beamPhiInLabel, 3, 0); + beamParamsLayout->addWidget(beamPhiInEdit, 3, 1); beamParamsGroup->setLayout(beamParamsLayout); // detector parameters @@ -55,14 +90,32 @@ InstrumentManager::InstrumentManager(QWidget *parent) QLabel *detectorAlphaRangeLabel = new QLabel(tr("Inclination Range (degrees):")); QLabel *detectorPhiRangeLabel = new QLabel(tr("Azimuthal Range (degrees):")); // range input edits - QDoubleSpinBox *detectorAlphaStartEdit = new QDoubleSpinBox; - QDoubleSpinBox *detectorAlphaEndEdit = new QDoubleSpinBox; - QSpinBox *detectorAlphaValuesEdit = new QSpinBox; - QDoubleSpinBox *detectorPhiStartEdit = new QDoubleSpinBox; - QDoubleSpinBox *detectorPhiEndEdit = new QDoubleSpinBox; - QSpinBox *detectorPhiValuesEdit = new QSpinBox; + detectorAlphaStartEdit = new QDoubleSpinBox; + detectorAlphaStartEdit->setSingleStep(0.01); + detectorAlphaStartEdit->setMinimum(-90.0); + detectorAlphaStartEdit->setMaximum(90.0); + detectorAlphaStartEdit->setDecimals(5); + detectorAlphaEndEdit = new QDoubleSpinBox; + detectorAlphaEndEdit->setSingleStep(0.01); + detectorAlphaEndEdit->setMinimum(-90.0); + detectorAlphaEndEdit->setMaximum(90.0); + detectorAlphaEndEdit->setDecimals(5); + detectorAlphaValuesEdit = new QSpinBox; + detectorAlphaValuesEdit->setMaximum(1000000); + detectorPhiStartEdit = new QDoubleSpinBox; + detectorPhiStartEdit->setSingleStep(0.01); + detectorPhiStartEdit->setMinimum(-90.0); + detectorPhiStartEdit->setMaximum(90.0); + detectorPhiStartEdit->setDecimals(5); + detectorPhiEndEdit = new QDoubleSpinBox; + detectorPhiEndEdit->setSingleStep(0.01); + detectorPhiEndEdit->setMinimum(-90.0); + detectorPhiEndEdit->setMaximum(90.0); + detectorPhiEndEdit->setDecimals(5); + detectorPhiValuesEdit = new QSpinBox; + detectorPhiValuesEdit->setMaximum(1000000); // checkbox for IsGISAXS angle initialization - QCheckBox *detectorAnglesIsGISAXSBox = new QCheckBox(tr("IsGISAXS Angle Initialization")); + detectorAnglesIsGISAXSBox = new QCheckBox(tr("IsGISAXS Angle Initialization")); // layout QGridLayout *detectorParamsLayout = new QGridLayout; detectorParamsLayout->addWidget(startRangeLabel, 0, 1); @@ -87,5 +140,181 @@ InstrumentManager::InstrumentManager(QWidget *parent) mainLayout->addWidget(detectorParamsGroup); mainLayout->addStretch(); setLayout(mainLayout); + + // update edit boxes to reflect values for selected instrument + updateEditBoxes(); + + // connect signals with slots + connect(addInstrumentButton, SIGNAL(clicked()), this, SLOT(onAddInstrument())); + connect(saveInstrumentButton, SIGNAL(clicked()), this, SLOT(onSaveInstrument())); + connect(instrumentBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onInstrumentSelectionChanged(int))); + connect(beamIntensityEdit, SIGNAL(textEdited(QString)), this, SLOT(onInstrumentEntryChanged())); + connect(beamWavelengthEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(beamAlphaInEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(beamPhiInEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorAlphaStartEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorAlphaEndEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorAlphaValuesEdit, SIGNAL(valueChanged(int)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorPhiStartEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorPhiEndEdit, SIGNAL(valueChanged(double)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorPhiValuesEdit, SIGNAL(valueChanged(int)), this, SLOT(onInstrumentEntryChanged())); + connect(detectorAnglesIsGISAXSBox, SIGNAL(clicked()), this, SLOT(onInstrumentEntryChanged())); +} + +void InstrumentView::onAddInstrument() +{ + bool ok; + QString instrument_name = QInputDialog::getText(this, tr("New Instrument"), + tr("Instrument Name:"), QLineEdit::Normal, + tr("instrument"), &ok); + if (ok && !instrument_name.isEmpty()) { + if (mp_simulation_data_model->getInstrumentList().contains(instrument_name)) { + QMessageBox::warning(this, tr("Duplicate Instrument Name"), + tr("Instrument Name Already Exists.")); + return; + } + delete mp_cached_instrument; + QString selected_entry = instrumentBox->currentText(); + Instrument *p_current_instrument; + if ( (p_current_instrument = mp_simulation_data_model->getInstrumentList().value(selected_entry, 0)) ) { + mp_cached_instrument = new Instrument(*p_current_instrument); + } else { + mp_cached_instrument = new Instrument; + } + m_cached_name = instrument_name; + instrumentBox->addItem(m_cached_name); + int index = instrumentBox->findText(m_cached_name); + if (index != -1) { + instrumentBox->setCurrentIndex(index); + saveInstrumentButton->setEnabled(true); + updateEditBoxes(); + } + } } +void InstrumentView::onSaveInstrument() +{ + if (mp_cached_instrument) { + initInstrumentFromForm(mp_cached_instrument); + if (mp_simulation_data_model->getInstrumentList().contains(m_cached_name)) { + mp_simulation_data_model->changeInstrument(m_cached_name, mp_cached_instrument); + } else { + mp_simulation_data_model->addInstrument(m_cached_name, mp_cached_instrument); + } + mp_cached_instrument = 0; + } + saveInstrumentButton->setEnabled(false); +} + +void InstrumentView::onInstrumentSelectionChanged(int index) +{ + (void)index; + if (saveInstrumentButton->isEnabled()) { + QMessageBox unsaved_changes_box; + unsaved_changes_box.setText("There are unsaved changes to the current instrument."); + unsaved_changes_box.setInformativeText("Do you want to save your changes?"); + unsaved_changes_box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + unsaved_changes_box.setDefaultButton(QMessageBox::Save); + int ret = unsaved_changes_box.exec(); + switch (ret) { + case QMessageBox::Save: + // Save was clicked + onSaveInstrument(); + break; + case QMessageBox::Discard: + // Don't Save was clicked + delete mp_cached_instrument; + removeInstrumentName(m_cached_name); + m_cached_name.clear(); + saveInstrumentButton->setEnabled(false); + break; + case QMessageBox::Cancel: + // Cancel was clicked + return; + default: + // should never be reached + return; + } + } + updateEditBoxes(); +} + +void InstrumentView::onInstrumentEntryChanged() +{ + if (!mp_cached_instrument) { + mp_cached_instrument = new Instrument; + } + initInstrumentFromForm(mp_cached_instrument); + saveInstrumentButton->setEnabled(true); +} + +void InstrumentView::updateEditBoxes() +{ + if (saveInstrumentButton->isEnabled()) { + if (mp_cached_instrument) { + setToInstrumentData(mp_cached_instrument); + } else { + saveInstrumentButton->setEnabled(false); + } + } else { + m_cached_name = instrumentBox->currentText(); + Instrument *p_instrument; + if ( (p_instrument = mp_simulation_data_model->getInstrumentList().value(m_cached_name, 0)) ) { + setToInstrumentData(p_instrument); + } + } +} + +void InstrumentView::setToInstrumentData(Instrument *p_instrument) +{ + // beam data + QString intensity_string( boost::lexical_cast<std::string>(p_instrument->getIntensity()).c_str() ); + beamIntensityEdit->setText(intensity_string); + const cvector_t k_in = p_instrument->getBeam().getCentralK(); + kvector_t k_in_real(k_in.x().real(), k_in.y().real(), k_in.z().real()); + double wavelength = 2.0*M_PI/( k_in_real.mag() ); + beamWavelengthEdit->setValue(wavelength); + beamAlphaInEdit->setValue(90.0 - k_in_real.theta()/Units::degree); + beamPhiInEdit->setValue(k_in_real.phi()/Units::degree); + + // detector data + if (p_instrument->getDetectorDimension()==2) { + const IAxis &axis1 = p_instrument->getDetectorAxis(0); + detectorPhiStartEdit->setValue(axis1.getMin()/Units::degree); + detectorPhiEndEdit->setValue(axis1.getMax()/Units::degree); + detectorPhiValuesEdit->setValue(axis1.getSize()); + const IAxis &axis2 = p_instrument->getDetectorAxis(1); + detectorAlphaStartEdit->setValue(axis2.getMin()/Units::degree); + detectorAlphaEndEdit->setValue(axis2.getMax()/Units::degree); + detectorAlphaValuesEdit->setValue(axis2.getSize()); + } +} + +void InstrumentView::initInstrumentFromForm(Instrument *p_instrument) +{ + if (!p_instrument) return; + double intensity = beamIntensityEdit->text().toDouble(); + double lambda = beamWavelengthEdit->value(); + double alpha_i = beamAlphaInEdit->value()*Units::degree; + double phi_i = beamPhiInEdit->value()*Units::degree; + double alpha_f_min = detectorAlphaStartEdit->value()*Units::degree; + double alpha_f_max = detectorAlphaEndEdit->value()*Units::degree; + size_t alpha_f_n = (size_t)detectorAlphaValuesEdit->value(); + double phi_f_min = detectorPhiStartEdit->value()*Units::degree; + double phi_f_max = detectorPhiEndEdit->value()*Units::degree; + size_t phi_f_n = (size_t)detectorPhiValuesEdit->value(); + bool isgisaxs_axes = detectorAnglesIsGISAXSBox->isChecked(); + p_instrument->setBeamIntensity(intensity); + p_instrument->setBeamParameters(lambda, alpha_i, phi_i); + p_instrument->setDetectorParameters(phi_f_n, phi_f_min, phi_f_max, + alpha_f_n, alpha_f_min, alpha_f_max, + isgisaxs_axes); +} + +void InstrumentView::removeInstrumentName(QString name) +{ + int index = instrumentBox->findText(name); + if (index != -1) { + instrumentBox->removeItem(index); + } +} diff --git a/GUI/coregui/Views/InstrumentView.h b/GUI/coregui/Views/InstrumentView.h index ead45b95204..203b33a5939 100644 --- a/GUI/coregui/Views/InstrumentView.h +++ b/GUI/coregui/Views/InstrumentView.h @@ -3,11 +3,50 @@ #include <QWidget> +class SimulationDataModel; +class Instrument; +class QDoubleSpinBox; +class QComboBox; +class QPushButton; +class QLineEdit; +class QSpinBox; +class QCheckBox; -class InstrumentManager : public QWidget +class InstrumentView : public QWidget { + Q_OBJECT + public: - InstrumentManager(QWidget *parent = 0); + InstrumentView(SimulationDataModel *simulation_data_model, QWidget *parent = 0); + +public slots: + void onAddInstrument(); + void onSaveInstrument(); + void onInstrumentSelectionChanged(int index); + void onInstrumentEntryChanged(); +private: + void updateEditBoxes(); + void setToInstrumentData(Instrument *p_instrument); + void initInstrumentFromForm(Instrument *p_instrument); + void removeInstrumentName(QString name); + SimulationDataModel *mp_simulation_data_model; + Instrument *mp_cached_instrument; + QString m_cached_name; + // qt widgets: + QComboBox *instrumentBox; + QPushButton *addInstrumentButton; + QPushButton *saveInstrumentButton; + QLineEdit *beamIntensityEdit; + QDoubleSpinBox *beamWavelengthEdit; + QDoubleSpinBox *beamAlphaInEdit; + QDoubleSpinBox *beamPhiInEdit; + QDoubleSpinBox *detectorAlphaStartEdit; + QDoubleSpinBox *detectorAlphaEndEdit; + QSpinBox *detectorAlphaValuesEdit; + QDoubleSpinBox *detectorPhiStartEdit; + QDoubleSpinBox *detectorPhiEndEdit; + QSpinBox *detectorPhiValuesEdit; + QCheckBox *detectorAnglesIsGISAXSBox; }; #endif // INSTRMANAGER_H diff --git a/GUI/coregui/mainwindow/mainwindow.cpp b/GUI/coregui/mainwindow/mainwindow.cpp index 113b9dcf2c8..3005aefba14 100644 --- a/GUI/coregui/mainwindow/mainwindow.cpp +++ b/GUI/coregui/mainwindow/mainwindow.cpp @@ -26,8 +26,11 @@ MainWindow::MainWindow(QWidget *parent) , m_sampleView(0) , m_simulationView(0) , m_fitView(0) - , m_sim_data_model(0) + , mp_sim_data_model(0) { + // initialize simulation data model first: + initSimModel(); + QString baseName = QApplication::style()->objectName(); qApp->setStyle(new ManhattanStyle(baseName)); @@ -46,7 +49,7 @@ MainWindow::MainWindow(QWidget *parent) //m_tabWidget = new TaskSelectorWidget(this); m_tabWidget = new Manhattan::FancyTabWidget(this); m_welcomeView = new WelcomeManager(this); - m_instrumentView = new InstrumentManager(this); + m_instrumentView = new InstrumentView(mp_sim_data_model, this); m_sampleView = new SampleManager(this); m_simulationView = new SimulationManager(this); m_fitView = new FitManager(this); @@ -61,9 +64,6 @@ MainWindow::MainWindow(QWidget *parent) // m_tabWidget->statusBar()->setProperty("p_styled", true); setAcceptDrops(true); - - // initialize simulation data model - initSimModel(); } MainWindow::~MainWindow() @@ -72,9 +72,9 @@ MainWindow::~MainWindow() void MainWindow::initSimModel() { - if (m_sim_data_model) delete m_sim_data_model; - m_sim_data_model = new SimulationDataModel; - m_sim_data_model->addInstrument(tr("Default GISAS"), createDefaultInstrument()); + if (mp_sim_data_model) delete mp_sim_data_model; + mp_sim_data_model = new SimulationDataModel; + mp_sim_data_model->addInstrument(tr("Default GISAS"), createDefaultInstrument()); } Instrument *MainWindow::createDefaultInstrument() @@ -82,7 +82,7 @@ Instrument *MainWindow::createDefaultInstrument() Instrument *p_result = new Instrument; p_result->setBeamParameters(0.1*Units::nanometer, 0.4*Units::degree, 0.0); p_result->setBeamIntensity(1e7); - p_result->setDetectorParameters(100, 0.0, 3.0*Units::degree, + p_result->setDetectorParameters(100, 0.0, 6.0*Units::degree, 100, 0.0, 3.0*Units::degree); return p_result; } diff --git a/GUI/coregui/mainwindow/mainwindow.h b/GUI/coregui/mainwindow/mainwindow.h index 227f5e4d566..2010aa441d5 100644 --- a/GUI/coregui/mainwindow/mainwindow.h +++ b/GUI/coregui/mainwindow/mainwindow.h @@ -10,7 +10,7 @@ namespace Manhattan { class TaskSelectorWidget; class WelcomeManager; -class InstrumentManager; +class InstrumentView; class SampleManager; class SimulationManager; class FitManager; @@ -26,18 +26,18 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); - SimulationDataModel *getSimulationDataModel() { return m_sim_data_model; } + SimulationDataModel *getSimulationDataModel() { return mp_sim_data_model; } private: //TaskSelectorWidget *m_tabWidget; Manhattan::FancyTabWidget *m_tabWidget; WelcomeManager *m_welcomeView; - InstrumentManager *m_instrumentView; + InstrumentView *m_instrumentView; SampleManager *m_sampleView; SimulationManager *m_simulationView; FitManager * m_fitView; - SimulationDataModel *m_sim_data_model; + SimulationDataModel *mp_sim_data_model; // dummy simulation model initializer for test purposes void initSimModel(); // dummy instrument creator -- GitLab