From 380b939897cdc39192fff4f6df3d0c2766da8549 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 28 Aug 2017 15:22:43 +0200 Subject: [PATCH] #1767 Add UI for selection of subset of time steps --- .../ProjectDataModel/RimEclipseResultCase.cpp | 16 +- .../ProjectDataModel/RimTimeStepFilter.cpp | 300 ++++++++++++++++-- .../ProjectDataModel/RimTimeStepFilter.h | 56 +++- 3 files changed, 324 insertions(+), 48 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index 393514703c..74e4922d27 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -146,31 +146,27 @@ bool RimEclipseResultCase::importGridAndResultMetaData(bool showTimeStepFilter) // Show GUI to select time steps - RimTimeStepFilter myTimeStepFilter; - myTimeStepFilter.setCustomTimeSteps(timeSteps); + m_timeStepFilter->setTimeStepsFromFile(timeSteps); - caf::PdmUiPropertyViewDialog propertyDialog(NULL, &myTimeStepFilter, "Time Step Filter", "", QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - propertyDialog.resize(QSize(400, 200)); + caf::PdmUiPropertyViewDialog propertyDialog(NULL, m_timeStepFilter, "Time Step Filter", "", QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + propertyDialog.resize(QSize(400, 600)); if (propertyDialog.exec() != QDialog::Accepted) { return false; } + m_timeStepFilter->clearTimeStepsFromFile(); + // Set cursor in wait state to continue display of progress dialog including // wait cursor QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - - m_timeStepFilter->setSelectedTimeStepIndices(myTimeStepFilter.selectedTimeStepIndices()); } readerEclipseOutput->setFileDataAccess(restartDataAccess.p()); } - if (!m_timeStepFilter->selectedTimeStepIndices().empty()) - { - readerEclipseOutput->setTimeStepFilter(m_timeStepFilter->selectedTimeStepIndices()); - } + readerEclipseOutput->setTimeStepFilter(m_timeStepFilter->selectedTimeStepIndices()); cvf::ref eclipseCase = new RigEclipseCaseData; if (!readerEclipseOutput->open(caseFileName(), eclipseCase.p())) diff --git a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp index 407c69f5c2..bbabb4b574 100644 --- a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp @@ -18,12 +18,36 @@ #include "RimTimeStepFilter.h" -#include "RimCase.h" +#include "RifReaderEclipseOutput.h" + +#include "RimEclipseResultCase.h" +#include "RimReservoirCellResultsStorage.h" #include "RimTools.h" -#include +#include "cafPdmUiTextEditor.h" -CAF_PDM_SOURCE_INIT(RimTimeStepFilter, "TimeStepFilter"); +#include +#include "cafPdmUiPushButtonEditor.h" + +namespace caf { + + template<> + void caf::AppEnum< RimTimeStepFilter::TimeStepFilterTypeEnum >::setUp() + { + addItem(RimTimeStepFilter::TS_ALL, "TS_ALL", "All"); + addItem(RimTimeStepFilter::TS_INTERVAL_DAYS, "TS_INTERVAL_DAYS", "Skip by Days"); + addItem(RimTimeStepFilter::TS_INTERVAL_WEEKS, "TS_INTERVAL_WEEKS", "Skip by Weeks"); + addItem(RimTimeStepFilter::TS_INTERVAL_MONTHS, "TS_INTERVAL_MONTHS", "Skip by Months"); + addItem(RimTimeStepFilter::TS_INTERVAL_QUARTERS, "TS_INTERVAL_QUARTERS", "Skip by Quarters"); + addItem(RimTimeStepFilter::TS_INTERVAL_YEARS, "TS_INTERVAL_YEARS", "Skip by Years"); + + setDefault(RimTimeStepFilter::TS_ALL); + } + +} // End namespace caf + + +CAF_PDM_SOURCE_INIT(RimTimeStepFilter, "RimTimeStepFilter"); //-------------------------------------------------------------------------------------------------- /// @@ -32,15 +56,50 @@ RimTimeStepFilter::RimTimeStepFilter() { CAF_PDM_InitObject("Time Step Filter", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_selectedTimeStepIndices, "TimeStepIndicesToImport", "Values", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_selectedTimeStepIndices, "TimeStepIndicesToImport", "Values", "", "", ""); + + CAF_PDM_InitField(&m_firstTimeStep, "FirstTimeStep", 0, "First Time Step", "", "", ""); + CAF_PDM_InitField(&m_lastTimeStep, "LastTimeStep", 0, "Last Time Step", "", "", ""); + + caf::AppEnum< RimTimeStepFilter::TimeStepFilterTypeEnum > filterType = TS_ALL; + CAF_PDM_InitField(&m_filterType, "FilterType", filterType, "Filter type", "", "", ""); + + CAF_PDM_InitField(&m_interval, "Interval", 1, "Interval", "", "", ""); + + CAF_PDM_InitField(&m_filteredTimeStepsText, "FilteredTimeSteps", QString(), "Filtered TimeSteps", "", "", ""); + m_filteredTimeStepsText.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); + m_filteredTimeStepsText.uiCapability()->setUiReadOnly(true); + m_filteredTimeStepsText.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + m_filteredTimeStepsText.xmlCapability()->setIOReadable(false); + m_filteredTimeStepsText.xmlCapability()->setIOWritable(false); + + CAF_PDM_InitFieldNoDefault(&m_applyReloadOfCase, "ApplyReloadOfCase", "", "", "", ""); + m_applyReloadOfCase.xmlCapability()->setIOWritable(false); + m_applyReloadOfCase.xmlCapability()->setIOReadable(false); + m_applyReloadOfCase.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); + m_applyReloadOfCase.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::LEFT); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimTimeStepFilter::setCustomTimeSteps(const std::vector& timeSteps) +void RimTimeStepFilter::setTimeStepsFromFile(const std::vector& timeSteps) { - m_customTimeSteps = timeSteps; + m_timeStepsFromFile = timeSteps; + + m_lastTimeStep = static_cast(timeSteps.size()) - 1; + + updateSelectedTimeStepIndices(); + updateDerivedData(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::clearTimeStepsFromFile() +{ + m_timeStepsFromFile.clear(); } //-------------------------------------------------------------------------------------------------- @@ -50,10 +109,10 @@ std::vector RimTimeStepFilter::selectedTimeStepIndices() const { std::vector indices; - // Convert vector from int to size_t + // Convert vector from int to size_t for (auto intValue : m_selectedTimeStepIndices.v()) { - indices.push_back(intValue); + indices.push_back(intValue); } return indices; @@ -62,13 +121,26 @@ std::vector RimTimeStepFilter::selectedTimeStepIndices() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimTimeStepFilter::setSelectedTimeStepIndices(const std::vector& indices) +void RimTimeStepFilter::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - m_selectedTimeStepIndices.v().clear(); + RimEclipseResultCase* rimEclipseResultCase = parentEclipseResultCase(); - for (auto sizetValue : indices) + if (changedField == &m_applyReloadOfCase) { - m_selectedTimeStepIndices.v().push_back(static_cast(sizetValue)); + if (rimEclipseResultCase) + { + rimEclipseResultCase->reloadDataAndUpdate(); + } + + return; + } + + updateSelectedTimeStepIndices(); + updateDerivedData(); + + if (rimEclipseResultCase) + { + rimEclipseResultCase->updateConnectedEditors(); } } @@ -79,29 +151,197 @@ QList RimTimeStepFilter::calculateValueOptions(const caf { QList optionItems; - if (fieldNeedingOptions == &m_selectedTimeStepIndices) + if (fieldNeedingOptions == &m_firstTimeStep || + fieldNeedingOptions == &m_lastTimeStep) { - RimCase* rimCase = nullptr; - this->firstAncestorOrThisOfType(rimCase); - if (rimCase) - { - QStringList timeSteps = rimCase->timeStepStrings(); + std::vector timeSteps = allTimeSteps(); - for (int i = 0; i < timeSteps.size(); i++) - { - optionItems.push_back(caf::PdmOptionItemInfo(timeSteps[i], static_cast(i))); - } - } - else - { - QString formatString = RimTools::createTimeFormatStringFromDates(m_customTimeSteps); + QString formatString = RimTools::createTimeFormatStringFromDates(timeSteps); - for (size_t i = 0; i < m_customTimeSteps.size(); i++) - { - optionItems.push_back(caf::PdmOptionItemInfo(m_customTimeSteps[i].toString(formatString), static_cast(i))); - } + for (size_t i = 0; i < timeSteps.size(); i++) + { + optionItems.push_back(caf::PdmOptionItemInfo(timeSteps[i].toString(formatString), static_cast(i))); } } return optionItems; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) +{ + if (field == &m_applyReloadOfCase) + { + caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast(attribute); + if (attrib) + { + attrib->m_buttonText = "Reload Case"; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimTimeStepFilter::filteredTimeStepsAsText() const +{ + QString text; + + std::vector timeSteps = allTimeSteps(); + + QString formatString = RimTools::createTimeFormatStringFromDates(timeSteps); + + for (auto index : m_selectedTimeStepIndices.v()) + { + QString stepText = timeSteps[static_cast(index)].toString(formatString); + text += stepText; + text += "\n"; + } + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::updateDerivedData() +{ + m_filteredTimeStepsText = filteredTimeStepsAsText(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::updateSelectedTimeStepIndices() +{ + m_selectedTimeStepIndices = selectedTimeStepIndicesFromUi(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimTimeStepFilter::allTimeSteps() const +{ + RimEclipseResultCase* rimEclipseResultCase = parentEclipseResultCase(); + if (rimEclipseResultCase && rimEclipseResultCase->results(RiaDefines::MATRIX_MODEL)) + { + const RifReaderEclipseOutput* rifReaderOutput = dynamic_cast(rimEclipseResultCase->results(RiaDefines::MATRIX_MODEL)->readerInterface()); + if (rifReaderOutput) + { + return rifReaderOutput->allTimeSteps(); + } + } + + return m_timeStepsFromFile; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimTimeStepFilter::selectedTimeStepIndicesFromUi() const +{ + std::vector indices; + + if (m_filterType == TS_ALL) + { + for (int i = m_firstTimeStep; i <= m_lastTimeStep; i++) + { + indices.push_back(i); + } + } + else + { + int intervalFactor = 1; + + if (m_filterType == TS_INTERVAL_WEEKS) + { + intervalFactor = 7; + } + else if (m_filterType == TS_INTERVAL_MONTHS) + { + intervalFactor = 30; + } + else if (m_filterType == TS_INTERVAL_QUARTERS) + { + intervalFactor = 90; + } + else if (m_filterType == TS_INTERVAL_YEARS) + { + intervalFactor = 365; + } + + int daysToSkip = m_interval * intervalFactor; + + + std::vector timeSteps = allTimeSteps(); + + indices.push_back(m_firstTimeStep); + QDateTime d = timeSteps[m_firstTimeStep].addDays(daysToSkip); + + for (int i = m_firstTimeStep + 1; i <= m_lastTimeStep; i++) + { + if (timeSteps[i] > d) + { + d = d.addDays(daysToSkip); + indices.push_back(i); + } + } + } + + return indices; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::updateFieldVisibility() +{ + if (m_filterType == TS_ALL) + { + m_interval.uiCapability()->setUiHidden(true); + } + else + { + m_interval.uiCapability()->setUiHidden(false); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseResultCase* RimTimeStepFilter::parentEclipseResultCase() const +{ + RimEclipseResultCase* rimEclipseResultCase = nullptr; + this->firstAncestorOrThisOfType(rimEclipseResultCase); + + return rimEclipseResultCase; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&m_firstTimeStep); + uiOrdering.add(&m_lastTimeStep); + uiOrdering.add(&m_filterType); + uiOrdering.add(&m_interval); + + if (m_timeStepsFromFile.size() == 0) + { + uiOrdering.add(&m_applyReloadOfCase); + } + + QString displayUiName = QString("Filtered Time Steps (%1)").arg(m_selectedTimeStepIndices().size()); + + caf::PdmUiGroup* group = uiOrdering.addNewGroupWithKeyword(displayUiName, "FilteredTimeStepKeyword"); + group->add(&m_filteredTimeStepsText); + group->setCollapsedByDefault(true); + + updateDerivedData(); + updateFieldVisibility(); + + uiOrdering.skipRemainingFields(); +} diff --git a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h index 03fa166b3e..e457366aff 100644 --- a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h +++ b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h @@ -24,6 +24,7 @@ #include class QDateTime; +class RimEclipseResultCase; //-------------------------------------------------------------------------------------------------- /// @@ -31,18 +32,57 @@ class QDateTime; class RimTimeStepFilter : public caf::PdmObject { CAF_PDM_HEADER_INIT; + +public: + enum TimeStepFilterTypeEnum + { + TS_ALL, + TS_INTERVAL_DAYS, + TS_INTERVAL_WEEKS, + TS_INTERVAL_MONTHS, + TS_INTERVAL_QUARTERS, + TS_INTERVAL_YEARS + }; + public: RimTimeStepFilter(); - void setCustomTimeSteps(const std::vector& timeSteps); - - std::vector selectedTimeStepIndices() const; - void setSelectedTimeStepIndices(const std::vector& indices); + void setTimeStepsFromFile(const std::vector& timeSteps); + void clearTimeStepsFromFile(); -private: - virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override; + std::vector selectedTimeStepIndices() const; private: - caf::PdmField< std::vector > m_selectedTimeStepIndices; - std::vector m_customTimeSteps; + QString filteredTimeStepsAsText() const; + + void updateDerivedData(); + void updateSelectedTimeStepIndices(); + + std::vector allTimeSteps() const; + std::vector selectedTimeStepIndicesFromUi() const; + + void updateFieldVisibility(); + + RimEclipseResultCase* parentEclipseResultCase() const; + + // PDM overrides + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override; + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; + +private: + caf::PdmField< std::vector > m_selectedTimeStepIndices; + + caf::PdmField< caf::AppEnum< TimeStepFilterTypeEnum > > m_filterType; + + caf::PdmField m_firstTimeStep; + caf::PdmField m_lastTimeStep; + caf::PdmField m_interval; + + caf::PdmField m_filteredTimeStepsText; + + caf::PdmField m_applyReloadOfCase; + + std::vector m_timeStepsFromFile; };