diff --git a/ApplicationLibCode/Commands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/CMakeLists_files.cmake index be2b342e52..b3ce72161b 100644 --- a/ApplicationLibCode/Commands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/CMakeLists_files.cmake @@ -94,6 +94,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicExportSummaryCalculationExpressionsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCalculationExpressionsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicImportWellLogCsvFileFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicNewViewForGridEnsembleFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -191,6 +192,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicExportSummaryCalculationExpressionsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCalculationExpressionsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicImportWellLogCsvFileFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewViewForGridEnsembleFeature.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/Commands/RicNewViewForGridEnsembleFeature.cpp b/ApplicationLibCode/Commands/RicNewViewForGridEnsembleFeature.cpp new file mode 100644 index 0000000000..4b82118d80 --- /dev/null +++ b/ApplicationLibCode/Commands/RicNewViewForGridEnsembleFeature.cpp @@ -0,0 +1,134 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewViewForGridEnsembleFeature.h" + +#include "RiaLogging.h" + +#include "Rim3dView.h" +#include "RimEclipseCase.h" +#include "RimEclipseCaseEnsemble.h" +#include "RimEclipseContourMapView.h" +#include "RimEclipseView.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechView.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT( RicNewViewForGridEnsembleFeature, "RicNewViewForGridEnsembleFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewViewForGridEnsembleFeature::addView( RimEclipseCaseEnsemble* eclipseCaseEnsemble ) +{ + std::vector cases = eclipseCaseEnsemble->cases(); + if ( cases.empty() ) return; + + bool addToViews = false; + RimEclipseView* newView = cases[0]->createAndAddReservoirView( addToViews ); + + if ( newView ) + { + eclipseCaseEnsemble->addView( newView ); + eclipseCaseEnsemble->updateConnectedEditors(); + + Riu3DMainWindowTools::setExpanded( newView ); + + // Select the new view to make sure RiaApplication::setActiveReservoirView() is called + Riu3DMainWindowTools::selectAsCurrentItem( newView ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewViewForGridEnsembleFeature::isCommandEnabled() const +{ + return selectedEclipseCaseEnsemble() != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewViewForGridEnsembleFeature::onActionTriggered( bool isChecked ) +{ + RimEclipseCaseEnsemble* eclipseCaseEnsemble = selectedEclipseCaseEnsemble(); + addView( eclipseCaseEnsemble ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewViewForGridEnsembleFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "New View" ); + actionToSetup->setIcon( QIcon( ":/3DView16x16.png" ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +// Rim3dView* RicNewViewForGridEnsembleFeature::createReservoirView( RimEclipseCase* eclipseCase, RimGeoMechCase* geomCase ) +// { +// RimGridView* insertedView = nullptr; + +// if ( eclipseCase ) +// { +// insertedView = eclipseCase->createAndAddReservoirView(); +// } +// else if ( geomCase ) +// { +// insertedView = geomCase->createAndAddReservoirView(); +// } + +// // Must be run before buildViewItems, as wells are created in this function +// if ( insertedView ) insertedView->loadDataAndUpdate(); + +// if ( eclipseCase ) +// { +// eclipseCase->updateConnectedEditors(); +// } + +// if ( geomCase ) +// { +// geomCase->updateConnectedEditors(); +// } + +// return insertedView; +// } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCaseEnsemble* RicNewViewForGridEnsembleFeature::selectedEclipseCaseEnsemble() +{ + std::vector selection; + caf::SelectionManager::instance()->objectsByType( &selection ); + + if ( !selection.empty() ) + { + return selection[0]; + } + + return nullptr; +} diff --git a/ApplicationLibCode/Commands/RicNewViewForGridEnsembleFeature.h b/ApplicationLibCode/Commands/RicNewViewForGridEnsembleFeature.h new file mode 100644 index 0000000000..4e03d25847 --- /dev/null +++ b/ApplicationLibCode/Commands/RicNewViewForGridEnsembleFeature.h @@ -0,0 +1,42 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RimEclipseCaseEnsemble; +class RimEclipseView; + +//================================================================================================== +/// +//================================================================================================== +class RicNewViewForGridEnsembleFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +public: + static void addView( RimEclipseCaseEnsemble* eclipseCaseEnsemble ); + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + + static RimEclipseCaseEnsemble* selectedEclipseCaseEnsemble(); +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 32e4f3a61f..e12fc89337 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -49,6 +49,7 @@ #include "RimCustomObjectiveFunctionCollection.h" #include "RimEclipseCase.h" #include "RimEclipseCaseCollection.h" +#include "RimEclipseCaseEnsemble.h" #include "RimEclipseCellColors.h" #include "RimEclipseContourMapView.h" #include "RimEclipseContourMapViewCollection.h" @@ -272,6 +273,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "Separator"; menuBuilder << "RicNewStatisticsCaseFeature"; } + else if ( dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicNewViewForGridEnsembleFeature"; + } else if ( dynamic_cast( firstUiItem ) ) { menuBuilder << "RicImportGeoMechCaseFeature"; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp index 6f60b58228..e5dcfae10c 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp @@ -291,7 +291,7 @@ void RimEclipseCase::initAfterRead() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimEclipseView* RimEclipseCase::createAndAddReservoirView() +RimEclipseView* RimEclipseCase::createAndAddReservoirView( bool addToViews ) { RimEclipseView* rimEclipseView = new RimEclipseView(); @@ -313,7 +313,10 @@ RimEclipseView* RimEclipseCase::createAndAddReservoirView() caf::PdmDocument::updateUiIconStateRecursively( rimEclipseView ); - reservoirViews().push_back( rimEclipseView ); + if ( addToViews ) + { + reservoirViews().push_back( rimEclipseView ); + } return rimEclipseView; } diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.h b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.h index d5ace3d6b0..9f55dc1ba2 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.h @@ -91,7 +91,7 @@ class RimEclipseCase : public RimCase RimReservoirCellResultsStorage* resultsStorage( RiaDefines::PorosityModelType porosityModel ); const RimReservoirCellResultsStorage* resultsStorage( RiaDefines::PorosityModelType porosityModel ) const; - RimEclipseView* createAndAddReservoirView(); + RimEclipseView* createAndAddReservoirView( bool addToViews = true ); RimEclipseView* createCopyAndAddView( const RimEclipseView* sourceView ); const RigVirtualPerforationTransmissibilities* computeAndGetVirtualPerforationTransmissibilities(); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.cpp index 230fe2150e..134dd84059 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.cpp @@ -23,6 +23,7 @@ #include "RimEclipseCase.h" #include "RimEclipseCellColors.h" #include "RimEclipseResultCase.h" +#include "RimEclipseView.h" #include "cafPdmFieldScriptingCapability.h" #include "cafPdmObjectScriptingCapability.h" @@ -46,6 +47,10 @@ RimEclipseCaseEnsemble::RimEclipseCaseEnsemble() m_caseCollection->uiCapability()->setUiName( "Cases" ); m_caseCollection->uiCapability()->setUiIconFromResourceString( ":/Cases16x16.png" ); + CAF_PDM_InitFieldNoDefault( &m_selectedCase, "SelectedCase", "Selected Case" ); + + CAF_PDM_InitFieldNoDefault( &m_views, "Views", "Views" ); + setDeletable( true ); } @@ -99,3 +104,56 @@ bool RimEclipseCaseEnsemble::contains( RimEclipseCase* reservoir ) const return false; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimEclipseCaseEnsemble::cases() const +{ + return m_caseCollection->reservoirs.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCaseEnsemble::addView( RimEclipseView* view ) +{ + m_views.push_back( view ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimEclipseCaseEnsemble::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options; + + if ( fieldNeedingOptions == &m_selectedCase ) + { + for ( auto eclCase : cases() ) + { + options.push_back( caf::PdmOptionItemInfo( eclCase->caseUserDescription(), eclCase, false, eclCase->uiIconProvider() ) ); + } + + return options; + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseCaseEnsemble::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_selectedCase ) + { + for ( auto view : m_views ) + { + view->setEclipseCase( m_selectedCase() ); + view->loadDataAndUpdate(); + view->updateGridBoxData(); + view->updateAnnotationItems(); + } + } +} diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.h b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.h index 6239dc0a63..1b78c1ad1b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCaseEnsemble.h @@ -20,11 +20,14 @@ #include "RimNamedObject.h" +#include "cafPdmChildArrayField.h" #include "cafPdmChildField.h" #include "cafPdmField.h" +#include "cafPdmPtrField.h" class RimCaseCollection; class RimEclipseCase; +class RimEclipseView; //================================================================================================== // @@ -43,7 +46,17 @@ class RimEclipseCaseEnsemble : public RimNamedObject void removeCase( RimEclipseCase* reservoir ); bool contains( RimEclipseCase* reservoir ) const; + std::vector cases() const; + + void addView( RimEclipseView* view ); + +protected: + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + private: - caf::PdmField m_groupId; - caf::PdmChildField m_caseCollection; + caf::PdmField m_groupId; + caf::PdmChildField m_caseCollection; + caf::PdmChildArrayField m_views; + caf::PdmPtrField m_selectedCase; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp index ea63ec6231..25ec87e12c 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -769,15 +769,15 @@ QList RimEclipseResultDefinition::calculateValueOptions( { options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) ); - auto eclipseCase = firstAncestorOrThisOfTypeAsserted(); - if ( eclipseCase && eclipseCase->eclipseCaseData() && eclipseCase->eclipseCaseData()->mainGrid() ) + auto currentCase = eclipseCase(); + if ( currentCase && currentCase->eclipseCaseData() && currentCase->eclipseCaseData()->mainGrid() ) { RimProject* proj = RimProject::current(); std::vector allCases = proj->eclipseCases(); for ( RimEclipseCase* otherCase : allCases ) { - if ( otherCase == eclipseCase ) continue; + if ( otherCase == currentCase ) continue; if ( otherCase->eclipseCaseData() && otherCase->eclipseCaseData()->mainGrid() ) { @@ -792,7 +792,7 @@ QList RimEclipseResultDefinition::calculateValueOptions( } else if ( fieldNeedingOptions == &m_timeLapseBaseTimestep ) { - RimEclipseCase* currentCase = firstAncestorOrThisOfTypeAsserted(); + RimEclipseCase* currentCase = eclipseCase(); RimEclipseCase* baseCase = currentCase; if ( m_differenceCase ) diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 00483713dd..2fad58d95f 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -1257,11 +1257,9 @@ QString RimEclipseView::createAutoName() const QStringList generatedAutoTags; - RimCase* ownerCase = firstAncestorOrThisOfTypeAsserted(); - - if ( nameConfig()->addCaseName() ) + if ( nameConfig()->addCaseName() && ownerCase() ) { - generatedAutoTags.push_back( ownerCase->caseUserDescription() ); + generatedAutoTags.push_back( ownerCase()->caseUserDescription() ); } if ( nameConfig()->addProperty() )