diff --git a/GUI/Model/Data/DataItem.cpp b/GUI/Model/Data/DataItem.cpp index 526e1a6440daa8c4ad73b8e56f421cdda9600f96..ad8525c11c7188c1d649ba1af62c54b8a0675358 100644 --- a/GUI/Model/Data/DataItem.cpp +++ b/GUI/Model/Data/DataItem.cpp @@ -18,6 +18,7 @@ #include "Device/IO/IOFactory.h" #include "GUI/Model/Axis/AmplitudeAxisItem.h" #include "GUI/Model/Axis/BasicAxisItem.h" +#include "GUI/Support/Util/CoordName.h" #include "GUI/Support/Util/Error.h" #include "GUI/Support/Util/MessageService.h" #include "GUI/Support/XML/UtilXML.h" @@ -41,7 +42,7 @@ const QString y_axis_default_name = "Y [nbins]"; DataItem::DataItem(const QString& modelType) : TYPE(modelType) , m_fileName("undefined") - , m_axesUnits(ComboProperty::fromList({"nbins"})) + , m_currentCoord(Coords::NBINS) , m_xAxis(std::make_unique<BasicAxisItem>()) , m_yAxis(std::make_unique<AmplitudeAxisItem>()) , m_last_modified(QDateTime::currentDateTime()) @@ -230,25 +231,24 @@ void DataItem::copyXYRangesFromItem(DataItem* sourceItem) copyYRangeFromItem(sourceItem); } -QString DataItem::currentAxesUnits() const +Coords DataItem::currentCoord() const { - return m_axesUnits.currentValue(); + return m_currentCoord; } -void DataItem::setCurrentAxesUnits(const QString& units) +void DataItem::setCurrentCoord(Coords coord) { - m_axesUnits.setCurrentValue(units); - emit axesUnitsChanged(this); + m_currentCoord = coord; } -ComboProperty DataItem::axesUnitsCombo() const +QString DataItem::currentAxesUnits() const { - return m_axesUnits; + return GUI::Util::CoordName::nameFromCoord(m_currentCoord); } -void DataItem::setAxesUnitsCombo(const ComboProperty& unitsCombo) +void DataItem::setCurrentAxesUnits(const QString& units) { - m_axesUnits = unitsCombo; + m_currentCoord = GUI::Util::CoordName::coordFromName(units); emit axesUnitsChanged(this); } @@ -302,7 +302,7 @@ void DataItem::setAxesRangeToData() void DataItem::writeTo(QXmlStreamWriter* w) const { - XML::writeAttribute(w, XML::Attrib::version, uint(1)); + XML::writeAttribute(w, XML::Attrib::version, uint(2)); // file name w->writeStartElement(Tag::FileName); @@ -311,7 +311,7 @@ void DataItem::writeTo(QXmlStreamWriter* w) const // axes units w->writeStartElement(Tag::AxesUnits); - m_axesUnits.writeTo(w); + XML::writeAttribute(w, XML::Attrib::value, GUI::Util::CoordName::nameFromCoord(m_currentCoord)); w->writeEndElement(); // x axis @@ -328,7 +328,6 @@ void DataItem::writeTo(QXmlStreamWriter* w) const void DataItem::readFrom(QXmlStreamReader* r) { const uint version = XML::readUIntAttribute(r, XML::Attrib::version); - Q_UNUSED(version) while (r->readNextStartElement()) { QString tag = r->name().toString(); @@ -340,7 +339,14 @@ void DataItem::readFrom(QXmlStreamReader* r) // axes units } else if (tag == Tag::AxesUnits) { - m_axesUnits.readFrom(r); + QString axes_units; + if (version == 1) { + XML::readAttribute(r, XML::Attrib::name, &axes_units); + if (axes_units.isEmpty()) + axes_units = GUI::Util::CoordName::nameFromCoord(Coords::NBINS); + } else + XML::readAttribute(r, XML::Attrib::value, &axes_units); + m_currentCoord = GUI::Util::CoordName::coordFromName(axes_units); XML::gotoEndElementOfTag(r, tag); // x axis diff --git a/GUI/Model/Data/DataItem.h b/GUI/Model/Data/DataItem.h index 41ee9af0828a918c17615a3f95e6811f92eece00..23e73df06420aae6e1af0efa8f41bb44ce52f4ce 100644 --- a/GUI/Model/Data/DataItem.h +++ b/GUI/Model/Data/DataItem.h @@ -15,6 +15,7 @@ #ifndef BORNAGAIN_GUI_MODEL_DATA_DATAITEM_H #define BORNAGAIN_GUI_MODEL_DATA_DATAITEM_H +#include "Device/Coord/Tags.h" #include "GUI/Model/Data/ComboProperty.h" #include <QDateTime> #include <mutex> @@ -93,10 +94,10 @@ public: void copyXYRangesFromItem(DataItem* sourceItem); // Axes units + Coords currentCoord() const; + void setCurrentCoord(Coords coord); QString currentAxesUnits() const; void setCurrentAxesUnits(const QString& units); - ComboProperty axesUnitsCombo() const; - void setAxesUnitsCombo(const ComboProperty& unitsCombo); //! Updates data on the change of axes units virtual void updateCoords(const ICoordSystem& converter) = 0; @@ -145,7 +146,7 @@ protected: QString m_fileName; QString m_fileDir; - ComboProperty m_axesUnits; + Coords m_currentCoord; std::unique_ptr<BasicAxisItem> m_xAxis; std::unique_ptr<AmplitudeAxisItem> m_yAxis; diff --git a/GUI/Model/Data/DataItemUtil.cpp b/GUI/Model/Data/DataItemUtil.cpp index 661e65d152e0212906f382d278a2402d3d0d5a91..ba7ba19e4795e4e9538a69b4a0c1bb838d20f95f 100644 --- a/GUI/Model/Data/DataItemUtil.cpp +++ b/GUI/Model/Data/DataItemUtil.cpp @@ -20,33 +20,25 @@ #include "GUI/Model/Data/DataItem.h" #include "GUI/Support/Util/CoordName.h" -namespace { - -//! Updates axes' titles -void updateAxesTitle(DataItem* intensityItem, const ICoordSystem& converter, Coords units) +void GUI::Model::DataItemUtil::updateAxesTitle(DataItem* intensityItem, + const ICoordSystem& converter, Coords units) { intensityItem->setXaxisTitle(QString::fromStdString(converter.nameOfAxis(0, units))); if (converter.rank() > 1) intensityItem->setYaxisTitle(QString::fromStdString(converter.nameOfAxis(1, units))); } - -ComboProperty availableUnits(const ICoordSystem& converter) +QStringList GUI::Model::DataItemUtil::availableUnits(const ICoordSystem& converter) { - ComboProperty result; + QStringList result; for (auto units : converter.availableUnits()) { auto unit_name = GUI::Util::CoordName::nameFromCoord(units); if (!unit_name.isEmpty()) result << unit_name; } - - result.setCurrentValue(GUI::Util::CoordName::nameFromCoord(converter.defaultUnits())); return result; } -} // namespace - - //! Updates axes of Datafield in IntensityData item to correspond with axes units selection. //! InstrumentItem is used to get domain's detector map for given units. @@ -57,7 +49,7 @@ void GUI::Model::DataItemUtil::updateDataAxes(DataItem* dataItem, const ICoordSy if (!oldData) return; - Coords axes_units = GUI::Util::CoordName::coordFromName(dataItem->currentAxesUnits()); + Coords axes_units = dataItem->currentCoord(); auto newData = std::make_unique<Datafield>(converter.convertedAxes(axes_units), oldData->flatVector(), oldData->errorSigmas()); @@ -67,29 +59,22 @@ void GUI::Model::DataItemUtil::updateDataAxes(DataItem* dataItem, const ICoordSy updateAxesTitle(dataItem, converter, axes_units); } -void GUI::Model::DataItemUtil::setDataItemCoords(DataItem* dataItem, const ICoordSystem& converter) -{ - ComboProperty combo = availableUnits(converter); - dataItem->setAxesUnitsCombo(combo); -} - void GUI::Model::DataItemUtil::createDefaultDetectorMap(DataItem* dataItem, const ICoordSystem& converter) { - auto output_data = std::make_unique<Datafield>(converter.defaultAxes()); + auto current_coord = dataItem->currentCoord(); + auto output_data = std::make_unique<Datafield>(converter.convertedAxes(current_coord)); dataItem->setDatafield(output_data.release()); - setDataItemCoords(dataItem, converter); - updateAxesTitle(dataItem, converter, converter.defaultUnits()); + updateAxesTitle(dataItem, converter, current_coord); } void GUI::Model::DataItemUtil::setResults(DataItem* dataItem, const SimulationResult& result) { + auto current_coord = dataItem->currentCoord(); if (dataItem->c_field() == nullptr) { const auto& converter = result.converter(); - GUI::Model::DataItemUtil::setDataItemCoords(dataItem, converter); - updateAxesTitle(dataItem, converter, converter.defaultUnits()); + updateAxesTitle(dataItem, converter, current_coord); } - auto selected_units = GUI::Util::CoordName::coordFromName(dataItem->currentAxesUnits()); dataItem->setDatafield( - new Datafield(result.converter().convertedAxes(selected_units), result.flatVector())); + new Datafield(result.converter().convertedAxes(current_coord), result.flatVector())); } diff --git a/GUI/Model/Data/DataItemUtil.h b/GUI/Model/Data/DataItemUtil.h index f390a5b5d7df3369807035b28930d006bb54d13b..609744f1c0a0407115f5fc751757c9e4ad75c055 100644 --- a/GUI/Model/Data/DataItemUtil.h +++ b/GUI/Model/Data/DataItemUtil.h @@ -27,11 +27,16 @@ class SimulationResult; namespace GUI::Model::DataItemUtil { -//! updates axes of Datafield in IntensityData item +//! Updates axes' titles +void updateAxesTitle(DataItem* intensityItem, const ICoordSystem& converter, Coords units); + +//! Updates axes of Datafield in IntensityData item void updateDataAxes(DataItem* dataItem, const ICoordSystem& converter); -void setDataItemCoords(DataItem* dataItem, const ICoordSystem& converter); +//! Available units for coordinate system +QStringList availableUnits(const ICoordSystem& converter); +//! Creates zero-value intensity map with given coordinate system void createDefaultDetectorMap(DataItem* dataItem, const ICoordSystem& converter); //! Sets simulation results into the DataItem diff --git a/GUI/Model/Data/IntensityDataItem.cpp b/GUI/Model/Data/IntensityDataItem.cpp index e2189d1e6b5d0cee5f00e83da266b80dd98c16e4..3387827c12acb202e7b63b419af26d480a1bbe9a 100644 --- a/GUI/Model/Data/IntensityDataItem.cpp +++ b/GUI/Model/Data/IntensityDataItem.cpp @@ -23,6 +23,7 @@ #include "GUI/Model/Data/MaskUnitsConverter.h" #include "GUI/Model/Data/ProjectionItems.h" #include "GUI/Support/IO/ImportDataInfo.h" +#include "GUI/Support/Util/CoordName.h" #include "GUI/Support/Util/Error.h" #include "GUI/Support/Util/QCP_Util.h" #include <qcustomplot.h> @@ -222,9 +223,9 @@ std::vector<int> IntensityDataItem::shape() const void IntensityDataItem::reset(ImportDataInfo data) { - ASSERT(data.unitsLabel() == "nbins"); - ComboProperty combo = ComboProperty() << data.unitsLabel(); - setAxesUnitsCombo(combo); + ASSERT(data.unitsLabel() == GUI::Util::CoordName::nameFromCoord(Coords::NBINS)); + setCurrentAxesUnits(data.unitsLabel()); + setXaxisTitle(data.axisLabel(0)); setYaxisTitle(data.axisLabel(1)); MaskUnitsConverter converter; diff --git a/GUI/Model/Data/SpecularDataItem.cpp b/GUI/Model/Data/SpecularDataItem.cpp index 2b490f74ec91cd844c2b57f1018f6f139e8b5e93..822ae7beb6c22a62a7bc1fff805febdb840fd6bb 100644 --- a/GUI/Model/Data/SpecularDataItem.cpp +++ b/GUI/Model/Data/SpecularDataItem.cpp @@ -122,8 +122,8 @@ std::vector<int> SpecularDataItem::shape() const void SpecularDataItem::reset(ImportDataInfo data) { - ComboProperty combo = ComboProperty() << data.unitsLabel(); - setAxesUnitsCombo(combo); + setCurrentAxesUnits(data.unitsLabel()); + setXaxisTitle(data.axisLabel(0)); setYaxisTitle(data.axisLabel(1)); setDatafield(std::move(data).intensityData().release()); diff --git a/GUI/Model/Device/RealItem.cpp b/GUI/Model/Device/RealItem.cpp index abe34125041ff0ef4df97c138142bcfae8badf14..9d84ccf4a879efbf3d0f274afab6b2523f964b0b 100644 --- a/GUI/Model/Device/RealItem.cpp +++ b/GUI/Model/Device/RealItem.cpp @@ -21,7 +21,6 @@ #include "GUI/Model/Data/ProjectionItems.h" #include "GUI/Model/Data/SpecularDataItem.h" #include "GUI/Model/Device/InstrumentItems.h" -#include "GUI/Model/Device/InstrumentModel.h" #include "GUI/Support/IO/AbstractDataLoader1D.h" #include "GUI/Support/IO/DataLoaders1D.h" #include "GUI/Support/IO/ImportDataInfo.h" @@ -220,6 +219,11 @@ QString RealItem::instrumentId() const return m_instrumentId; } +void RealItem::setInstrumentId(const QString& id) +{ + m_instrumentId = id; +} + void RealItem::linkToInstrument(const InstrumentItem* instrument) { if (instrument) { @@ -235,11 +239,6 @@ void RealItem::unlinkFromInstrument() updateToInstrument(nullptr); } -void RealItem::setInstrumentModel(InstrumentModel* instrumentModel) -{ - m_instrumentModel = instrumentModel; -} - bool RealItem::hasImportErrors() const { return (dataLoader() != nullptr) ? dataLoader()->numErrors() > 0 : false; @@ -413,7 +412,7 @@ void RealItem::writeTo(QXmlStreamWriter* w) const } } -void RealItem::readFrom(QXmlStreamReader* r, InstrumentItem* jobInstrument) +void RealItem::readFrom(QXmlStreamReader* r) { const uint version = XML::readUIntAttribute(r, XML::Attrib::version); Q_UNUSED(version) @@ -452,25 +451,11 @@ void RealItem::readFrom(QXmlStreamReader* r, InstrumentItem* jobInstrument) QString type; XML::readAttribute(r, XML::Attrib::type, &type); initFromType(type); - - // create axes units list from job's instrument or linked instrument - if (jobInstrument) { - const auto converter = jobInstrument->createCoordSystem(); - GUI::Model::DataItemUtil::setDataItemCoords(m_dataItem.get(), *converter); - } else if (!m_instrumentId.isEmpty()) { // read 'm_instrumentId' before - ASSERT(m_instrumentModel); - auto* instrument = m_instrumentModel->findInstrumentItemById(m_instrumentId); - ASSERT(instrument); - const auto converter = instrument->createCoordSystem(); - GUI::Model::DataItemUtil::setDataItemCoords(m_dataItem.get(), *converter); - } - m_dataItem->readFrom(r); XML::gotoEndElementOfTag(r, tag); // native data } else if (tag == Tag::NativeData) { - // TODO: do we need to create coordinates here? ASSERT(m_dataItem); // read 'm_dataItem' before initNativeData()->readFrom(r); XML::gotoEndElementOfTag(r, tag); @@ -517,7 +502,6 @@ QString RealItem::readDataFiles(const QString& projectDir, MessageService* messa void RealItem::copyTo(RealItem* const realdata_dst) const { - realdata_dst->setInstrumentModel(m_instrumentModel); GUI::Util::copyContents(this, realdata_dst); if (m_dataItem) @@ -577,9 +561,11 @@ void RealItem::updateToInstrument(const InstrumentItem* instrument) return; if (instrument) { - const auto converter = instrument->createCoordSystem(); - GUI::Model::DataItemUtil::setDataItemCoords(data_item, *converter); - dataItem()->updateCoords(*converter); + // To keep the same units after linking, just comment lines. + // To switch to certain units on linking, uncomment lines. + // dataItem()->setCurrentCoord(Coords::DEGREES); + // const auto converter = instrument->createCoordSystem(); + // dataItem()->updateCoords(*converter); return; } diff --git a/GUI/Model/Device/RealItem.h b/GUI/Model/Device/RealItem.h index 05d3140a81aa82298196c92993e5c5e8b0ec9a54..86e9c703f765742978bc3fa16e751ba4c4420a15 100644 --- a/GUI/Model/Device/RealItem.h +++ b/GUI/Model/Device/RealItem.h @@ -22,7 +22,6 @@ class Datafield; class DataItem; class ImportDataInfo; class InstrumentItem; -class InstrumentModel; class IntensityDataItem; class MaskContainerItem; class MessageService; @@ -87,11 +86,10 @@ public: // instrument QString instrumentId() const; + void setInstrumentId(const QString& id); void linkToInstrument(const InstrumentItem* instrument); void unlinkFromInstrument(); - void setInstrumentModel(InstrumentModel* instrumentModel); - // loader bool hasImportErrors() const; @@ -112,7 +110,7 @@ public: void deserializeBinaryData(const QByteArray& data); void writeTo(QXmlStreamWriter* w) const; - void readFrom(QXmlStreamReader* r, InstrumentItem* jobInstrument = nullptr); + void readFrom(QXmlStreamReader* r); void writeDataFiles(const QString& projectDir) const; QString readDataFiles(const QString& projectDir, MessageService* messageService); @@ -144,7 +142,6 @@ private: QString m_name; QString m_nativeDataUnits = "nbins"; QString m_presentationType; - InstrumentModel* m_instrumentModel = nullptr; // DataItem can be `IntensityDataItem` and `SpecularDataItem` (default `IntensityDataItem`). std::unique_ptr<DataItem> m_dataItem; diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp index 3d5a6792e653f290b1d2822f8443ed46520e0e65..17769a51ea145ade7e482ccf8528a4c86a278c0d 100644 --- a/GUI/Model/Job/JobItem.cpp +++ b/GUI/Model/Job/JobItem.cpp @@ -295,6 +295,13 @@ void JobItem::createSimulatedDataItem() { ASSERT(!simulatedDataItem()); m_simulatedDataItem.reset(createNewDataItem()); + + // Set default axes units for simulated data. + // Can be overriden by units from RealItem + if (isSpecularJob()) + m_simulatedDataItem->setCurrentCoord(Coords::QSPACE); + else + m_simulatedDataItem->setCurrentCoord(Coords::QSPACE); } IntensityDataItem* JobItem::intensityDataItem() @@ -312,10 +319,15 @@ DataItem* JobItem::createDiffDataItem() ASSERT(!diffDataItem()); m_diffDataItem.reset(createNewDataItem()); - // Immediately create coordinate system and axes units + // use the same axes units as for real data + ASSERT(m_realItem); + Coords coords = m_realItem->dataItem()->currentCoord(); + m_diffDataItem->setCurrentCoord(coords); + + // update axes labels const auto converter = instrumentItem()->createCoordSystem(); - GUI::Model::DataItemUtil::setDataItemCoords(diffDataItem(), *converter); - diffDataItem()->updateCoords(*converter); + ASSERT(converter); + GUI::Model::DataItemUtil::updateAxesTitle(diffDataItem(), *converter, coords); if (isSpecularJob()) dynamic_cast<SpecularDataItem*>(diffDataItem())->setDiffPlotStyle(); @@ -343,6 +355,10 @@ void JobItem::copyRealItemIntoJob(const RealItem* srcRealItem) // optional, but we don't need dataloader in job realItem()->setDataLoader(nullptr); + // override axes units of simulated data + ASSERT(m_simulatedDataItem); + m_simulatedDataItem->setCurrentCoord(m_realItem->dataItem()->currentCoord()); + if (isSpecularJob()) m_realItem->specularDataItem()->setRealPlotStyle(); } @@ -354,17 +370,27 @@ RealItem* JobItem::realItem() void JobItem::adjustReaDataToJobInstrument() { - // Link RealItem to the JobItem's instrument. - // (re-)Linking is necessary because of following reason - // 1) Copying of RealItem from RealModel on board of JobItem requires relink to the copied - // instrument - // 2) During relink all masks (if exists) will be converted to the default units of current - // detector - realItem()->linkToInstrument(instrumentItem()); + // update stored instrument id without updating rest of real data + realItem()->setInstrumentId(instrumentItem()->id()); if (instrumentItem()->is<GISASInstrumentItem>()) { + // Temporary conversion of real units to degrees before copying masks to instrument. + // It is not clear why we need to do this, but otherwise the result is incorrect. + // Seems that degrees are default units in detector, so we should use the same units here, + // but if we change 'converter->defaultUnits()' to, for example, radians, here we still + // should use 'Coords::DEGREES'. So the reason lies deeper. + Coords backup_coord = m_realItem->dataItem()->currentCoord(); + m_realItem->dataItem()->setCurrentCoord(Coords::DEGREES); + const auto converter = instrumentItem()->createCoordSystem(); + realItem()->dataItem()->updateCoords(*converter); + importMasksFromRealItem(); // Copy masks and ROI from RealItem on board of instrument. - cropRealData(); // Crop RealItem to the region of interest. + + // convert units back + m_realItem->dataItem()->setCurrentCoord(backup_coord); + realItem()->dataItem()->updateCoords(*converter); + + cropRealData(); // Crop RealItem to the region of interest. } } @@ -388,6 +414,8 @@ void JobItem::cropRealData() const auto converter = iiI->createCoordSystem(); ASSERT(converter); + + // (re)create zero-valued Datafield. Axes are derived from the current units GUI::Model::DataItemUtil::createDefaultDetectorMap(intensityItem, *converter); iiI->normalDetector()->iterateOverNonMaskedPoints([&](IDetector::const_iterator it) { @@ -584,9 +612,8 @@ void JobItem::readFrom(QXmlStreamReader* r) // real item } else if (tag == Tag::RealItem) { - ASSERT(instrumentItem()); // read 'm_instrument' before createRealItem(); - m_realItem->readFrom(r, instrumentItem()); + m_realItem->readFrom(r); createDiffDataItem()->copyXYRangesFromItem(m_realItem->dataItem()); if (isIntensityJob()) @@ -598,11 +625,7 @@ void JobItem::readFrom(QXmlStreamReader* r) // simulated data } else if (tag == Tag::SimulatedData) { - ASSERT(instrumentItem()); // read 'm_instrument' before createSimulatedDataItem(); - // create axes units list in data item before reading selected units - const auto converter = instrumentItem()->createCoordSystem(); - GUI::Model::DataItemUtil::setDataItemCoords(simulatedDataItem(), *converter); m_simulatedDataItem->readFrom(r); XML::gotoEndElementOfTag(r, tag); diff --git a/GUI/Model/Model/RealModel.cpp b/GUI/Model/Model/RealModel.cpp index 39759a3f74f6358a9a56ce90b6ab352a169ca356..6d6df155f7c93ed536e39fe1fb1eb96f0d901443 100644 --- a/GUI/Model/Model/RealModel.cpp +++ b/GUI/Model/Model/RealModel.cpp @@ -130,7 +130,6 @@ void RealModel::readDataFiles(const QString& projectDir, MessageService* message RealItem* RealModel::createRealItem() { auto realItem = std::make_unique<RealItem>(); - realItem->setInstrumentModel(m_instrumentModel); m_realItems.push_back(std::move(realItem)); return m_realItems.back().get(); } diff --git a/GUI/View/Common/DataPropertyWidget.cpp b/GUI/View/Common/DataPropertyWidget.cpp index d2fae627c0cb0e1e48288846aa4c2b33e3de60f0..0c1337871f998ef334bd88792ce21bc863169ece 100644 --- a/GUI/View/Common/DataPropertyWidget.cpp +++ b/GUI/View/Common/DataPropertyWidget.cpp @@ -16,8 +16,10 @@ #include "Base/Util/Assert.h" #include "Device/Coord/ICoordSystem.h" #include "GUI/Model/Data/DataItem.h" +#include "GUI/Model/Data/DataItemUtil.h" #include "GUI/Model/Device/InstrumentItems.h" #include "GUI/Model/Project/ProjectDocument.h" +#include "GUI/Support/Util/CoordName.h" #include <QFormLayout> DataPropertyWidget::DataPropertyWidget(QWidget* parent) @@ -41,19 +43,9 @@ void DataPropertyWidget::updateItemCoords(DataItem* item) if (!item) return; - InstrumentItem* instrument = nullptr; - if (jobItem()) - instrument = jobItem()->instrumentItem(); - else if (realItem()) { - ASSERT(gProjectDocument.has_value()); - instrument = gProjectDocument.value()->instrumentModel()->findInstrumentItemById( - realItem()->instrumentId()); - } else - ASSERT(false); - - if (instrument) { + if (instrumentItem()) { item->blockSignals(true); - const auto converter = instrument->createCoordSystem(); + const auto converter = instrumentItem()->createCoordSystem(); item->updateCoords(*converter); item->blockSignals(false); emit item->axesUnitsReplotRequested(); @@ -68,3 +60,30 @@ void DataPropertyWidget::updateUIValues() for (const auto& updater : m_updaters) updater(); } + +InstrumentItem* DataPropertyWidget::instrumentItem() +{ + if (jobItem()) + return jobItem()->instrumentItem(); + else if (realItem()) { + ASSERT(gProjectDocument.has_value()); + return gProjectDocument.value()->instrumentModel()->findInstrumentItemById( + realItem()->instrumentId()); + } else + ASSERT(false); + return nullptr; +} + +QStringList DataPropertyWidget::axesUnitsList() +{ + QStringList list; + if (!instrumentItem()) { + ASSERT(realItem()); + list << realItem()->dataItem()->currentAxesUnits(); + } else { + const auto converter = instrumentItem()->createCoordSystem(); + ASSERT(converter); + list = GUI::Model::DataItemUtil::availableUnits(*converter); + } + return list; +} diff --git a/GUI/View/Common/DataPropertyWidget.h b/GUI/View/Common/DataPropertyWidget.h index d3676b05eeb1008d582f8cbba1d18afc9d19c427..323b5023616898e5574f6ada3548707fc7b0735b 100644 --- a/GUI/View/Common/DataPropertyWidget.h +++ b/GUI/View/Common/DataPropertyWidget.h @@ -36,6 +36,9 @@ protected: void updateUIValues(); virtual void createPanelElements() = 0; + InstrumentItem* instrumentItem(); + QStringList axesUnitsList(); + QFormLayout* m_mainLayout; QList<std::function<void()>> m_updaters; diff --git a/GUI/View/Common/IntensityDataPropertyWidget.cpp b/GUI/View/Common/IntensityDataPropertyWidget.cpp index 9a906773276413b97b7430360aff079c18246599..2eeba28ba4838f23a36158d4d767967a45a80bac 100644 --- a/GUI/View/Common/IntensityDataPropertyWidget.cpp +++ b/GUI/View/Common/IntensityDataPropertyWidget.cpp @@ -50,16 +50,17 @@ void IntensityDataPropertyWidget::createPanelElements() GUI::Util::Layout::clearLayout(m_mainLayout); m_updaters.clear(); - m_mainLayout->addRow( - "Axes units:", - GUI::Util::createComboBox([=] { return currentIntensityDataItem()->axesUnitsCombo(); }, - [=](const QString& newVal) { - for (auto item : allIntensityDataItems()) - item->setCurrentAxesUnits(newVal); - emit axesRangeResetRequested(); - gProjectDocument.value()->setModified(); - }, - &m_updaters)); + m_mainLayout->addRow("Axes units:", + GUI::Util::createUnitsComboBox( + axesUnitsList(), + [=] { return currentIntensityDataItem()->currentAxesUnits(); }, + [=](const QString& newVal) { + for (auto item : allIntensityDataItems()) + item->setCurrentAxesUnits(newVal); + emit axesRangeResetRequested(); + gProjectDocument.value()->setModified(); + }, + &m_updaters)); m_mainLayout->addRow( "Color scheme:", diff --git a/GUI/View/Loaders/QREDataLoader.cpp b/GUI/View/Loaders/QREDataLoader.cpp index feebd126124ba70d2fb7ae8178add0fa3d139581..a6c803ac21d519ad8e47404173f04be7278258f1 100644 --- a/GUI/View/Loaders/QREDataLoader.cpp +++ b/GUI/View/Loaders/QREDataLoader.cpp @@ -564,16 +564,14 @@ void QREDataLoader::datafieldFromParsingResult(RealItem* item) const // -- Replacement of item->setImportData(std::move(data)); item->initNativeData(); - QString units_name = GUI::Util::CoordName::nameFromCoord(Coords::QSPACE); + // coords for data representation + Coords coord = Coords::QSPACE; // -- Replacement of specularItem->reset(std::move(data)); SpecularDataItem* specularItem = item->specularDataItem(); - ComboProperty combo = ComboProperty() << units_name; + specularItem->setCurrentCoord(coord); - specularItem->setAxesUnitsCombo(combo); - - const auto xAxisTitle = - QString::fromStdString(AngularReflectometryCoords::nameOfAxis0(Coords::QSPACE)); + const auto xAxisTitle = QString::fromStdString(AngularReflectometryCoords::nameOfAxis0(coord)); const auto* const yAxisTitle = "Signal [a.u.]"; // taken from ImportDataInfo::axisLabel specularItem->setXaxisTitle(xAxisTitle); @@ -581,7 +579,7 @@ void QREDataLoader::datafieldFromParsingResult(RealItem* item) const specularItem->setDatafield(oData); // takes ownership of odata specularItem->setAxesRangeToData(); - item->setNativeDataUnits(units_name); + item->setNativeDataUnits(GUI::Util::CoordName::nameFromCoord(coord)); item->setNativeDatafield(oData->clone()); // also takes ownership } diff --git a/GUI/View/Numeric/NumWidgetUtil.cpp b/GUI/View/Numeric/NumWidgetUtil.cpp index c6bfa45d5dfc79f7a58be0385feb8c084c16ba42..6e6e5f846ba084e2f82621498f1ee9316a5e2d7e 100644 --- a/GUI/View/Numeric/NumWidgetUtil.cpp +++ b/GUI/View/Numeric/NumWidgetUtil.cpp @@ -62,6 +62,28 @@ QComboBox* GUI::Util::createSafeComboBox(function<ComboProperty()> comboFunction return createComboBox(comboFunction, slot, updaters, tooltip, false); } +QComboBox* GUI::Util::createUnitsComboBox(const QStringList& list, function<QString()> currentUnits, + function<void(const QString&)> slot, + QList<std::function<void()>>* updaters, bool isScrollable) +{ + QComboBox* combo = new QComboBox; + combo->addItems(list); + combo->setMaxCount(list.size()); + combo->setCurrentText(currentUnits()); + + if (!isScrollable) + WheelEventEater::install(combo); + + QObject::connect(combo, &QComboBox::currentTextChanged, [=] { slot(combo->currentText()); }); + + if (updaters) + (*updaters) << [=]() { + QSignalBlocker b(combo); + combo->setCurrentText(currentUnits()); + }; + + return combo; +} DoubleSpinBox* GUI::Util::createDoubleSpinBoxRow(QFormLayout* parentLayout, DoubleProperty& d, function<void(double)> slot) diff --git a/GUI/View/Numeric/NumWidgetUtil.h b/GUI/View/Numeric/NumWidgetUtil.h index ab02b9c055a0b7950959cefbc04751852703d466..dcf32758810cdea9f2bc1c4318c9543be6965c6a 100644 --- a/GUI/View/Numeric/NumWidgetUtil.h +++ b/GUI/View/Numeric/NumWidgetUtil.h @@ -51,6 +51,11 @@ QComboBox* createSafeComboBox(std::function<ComboProperty()> comboFunction, QList<std::function<void()>>* updaters = nullptr, QString tooltip = ""); +QComboBox* createUnitsComboBox(const QStringList& list, std::function<QString()> currentUnits, + std::function<void(const QString&)> slot, + QList<std::function<void()>>* updaters = nullptr, + bool isScrollable = true); + //! Create a combo box with the information found in a selection property. //! //! The combo will be filled with the available options and will get the found tooltip. diff --git a/GUI/View/PlotSpecular/SpecularDataPropertyWidget.cpp b/GUI/View/PlotSpecular/SpecularDataPropertyWidget.cpp index 8e839373944c517491b1c04ffffe0d1931488d8c..9f99f20ecbf780da5601a43b6ae191a4a71e9756 100644 --- a/GUI/View/PlotSpecular/SpecularDataPropertyWidget.cpp +++ b/GUI/View/PlotSpecular/SpecularDataPropertyWidget.cpp @@ -42,16 +42,17 @@ void SpecularDataPropertyWidget::createPanelElements() GUI::Util::Layout::clearLayout(m_mainLayout); m_updaters.clear(); - m_mainLayout->addRow( - "Axes units:", - GUI::Util::createComboBox([=] { return currentSpecularDataItem()->axesUnitsCombo(); }, - [=](const QString& newVal) { - for (auto item : allSpecularDataItems()) - item->setCurrentAxesUnits(newVal); - emit axesRangeResetRequested(); - gProjectDocument.value()->setModified(); - }, - &m_updaters)); + m_mainLayout->addRow("Axes units:", + GUI::Util::createUnitsComboBox( + axesUnitsList(), + [=] { return currentSpecularDataItem()->currentAxesUnits(); }, + [=](const QString& newVal) { + for (auto item : allSpecularDataItems()) + item->setCurrentAxesUnits(newVal); + emit axesRangeResetRequested(); + gProjectDocument.value()->setModified(); + }, + &m_updaters)); // -- x-axis auto* xGroup = new QGroupBox("X axis", this);