From 7cf24d02ff60d5eb21951efa5cc6654d1b8e680b Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 2 Sep 2020 15:04:48 +0200 Subject: [PATCH] #6367 Improve the way we automatically name ensembles and cases --- .../Application/Tools/RiaFilePathTools.cpp | 171 +++++++++++++++++ .../Application/Tools/RiaFilePathTools.h | 6 + .../Application/Tools/RiaTextStringTools.cpp | 27 +++ .../Application/Tools/RiaTextStringTools.h | 2 + .../Commands/RicImportEnsembleFeature.cpp | 57 +++++- .../Commands/RicImportEnsembleFeature.h | 3 +- .../Commands/RicReplaceCaseFeature.cpp | 2 +- .../Commands/RicReplaceSummaryCaseFeature.cpp | 2 +- .../CorrelationPlots/RimCorrelationPlot.cpp | 3 +- .../Summary/RimCalculatedSummaryCase.cpp | 2 +- .../Summary/RimDerivedSummaryCase.cpp | 6 +- .../Summary/RimSummaryCase.cpp | 180 +++++++++--------- .../ProjectDataModel/Summary/RimSummaryCase.h | 27 ++- .../Summary/RimSummaryCaseCollection.cpp | 13 ++ .../Summary/RimSummaryCaseCollection.h | 5 + .../Summary/RimSummaryCaseMainCollection.cpp | 18 ++ .../Summary/RimSummaryCaseMainCollection.h | 2 + 17 files changed, 416 insertions(+), 110 deletions(-) diff --git a/ApplicationCode/Application/Tools/RiaFilePathTools.cpp b/ApplicationCode/Application/Tools/RiaFilePathTools.cpp index dbbcf4258a..d29e8d220a 100644 --- a/ApplicationCode/Application/Tools/RiaFilePathTools.cpp +++ b/ApplicationCode/Application/Tools/RiaFilePathTools.cpp @@ -19,7 +19,11 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaFilePathTools.h" + +#include "cafAssert.h" + #include + #include //-------------------------------------------------------------------------------------------------- @@ -173,3 +177,170 @@ QString RiaFilePathTools::rootSearchPathFromSearchFilter( const QString& searchF return pathPartList.join( separator() ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList RiaFilePathTools::splitPathIntoComponents( const QString& inputPath, bool splitExtensionIntoSeparateEntry ) +{ + auto path = QDir::cleanPath( inputPath ); + + QStringList components; + + QDir dir( path ); + + QFileInfo fileInfo( path ); + + if ( splitExtensionIntoSeparateEntry ) + { + QString extension = fileInfo.completeSuffix(); + path = path.replace( QString( ".%1" ).arg( extension ), "" ); + components.push_front( extension ); + components.push_front( fileInfo.baseName() ); + } + else + { + components.push_back( fileInfo.fileName() ); + } + + while ( dir.cdUp() ) + { + components.push_front( dir.dirName() ); + } + return components; +} + +struct PathNode +{ + QString name; + PathNode* parent; + std::list> children; + QString fileName; + + PathNode( const QString& name, PathNode* parent ) + : name( name ) + , parent( parent ) + { + } +}; + +void addToPathTree( PathNode* node, QStringList pathComponents, const QString& fileName ) +{ + CAF_ASSERT( node ); + if ( !pathComponents.empty() ) + { + QString pathComponent = pathComponents.front(); + pathComponents.pop_front(); + + for ( auto it = node->children.begin(); it != node->children.end(); ++it ) + { + if ( it->get()->name == pathComponent ) + { + addToPathTree( it->get(), pathComponents, fileName ); + return; + } + } + + node->children.push_back( std::make_unique( pathComponent, node ) ); + addToPathTree( node->children.back().get(), pathComponents, fileName ); + } + else + { + // Reached leaf, just set file name + node->fileName = fileName; + } +} + +void trimTree( PathNode* node ) +{ + if ( node->children.size() == 1u ) + { + // Unnecessary level. Remove it. + std::unique_ptr singleChildNode = std::move( node->children.front() ); + node->children.clear(); + node->children.swap( singleChildNode->children ); + node->fileName = singleChildNode->fileName; + + // Re-parent children + for ( auto it = node->children.begin(); it != node->children.end(); ++it ) + { + it->get()->parent = node; + } + trimTree( node ); + } + else + { + for ( auto it = node->children.begin(); it != node->children.end(); ++it ) + { + trimTree( it->get() ); + } + } +} + +void extractLeafNodes( PathNode* node, std::list* leafNodes ) +{ + if ( node->children.empty() ) + { + leafNodes->push_back( node ); + } + else + { + for ( auto it = node->children.begin(); it != node->children.end(); ++it ) + { + extractLeafNodes( it->get(), leafNodes ); + } + } +} + +void pathToNode( PathNode* node, QStringList* path ) +{ + CAF_ASSERT( path ); + + if ( node != nullptr ) + { + if ( !node->name.isEmpty() ) path->push_front( node->name ); + pathToNode( node->parent, path ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// Takes a list of file paths and returns a map with the key components that separate the path +/// from the others. +//-------------------------------------------------------------------------------------------------- +std::map RiaFilePathTools::keyPathComponentsForEachFilePath( const QStringList& filePaths ) +{ + std::map allComponents; + + std::multiset allPathComponents; + for ( auto fileName : filePaths ) + { + QStringList pathComponentsForFile = splitPathIntoComponents( fileName, true ); + allComponents[fileName] = pathComponentsForFile; + + for ( auto pathComponent : pathComponentsForFile ) + { + allPathComponents.insert( pathComponent ); + } + } + + auto topNode = std::make_unique( "", nullptr ); + + for ( auto keyComponentsPair : allComponents ) + { + addToPathTree( topNode.get(), keyComponentsPair.second, keyComponentsPair.first ); + } + + trimTree( topNode.get() ); + std::list leafNodes; + extractLeafNodes( topNode.get(), &leafNodes ); + + std::map keyComponents; + for ( PathNode* node : leafNodes ) + { + QStringList path; + pathToNode( node, &path ); + keyComponents[node->fileName] = path; + } + + return keyComponents; +} diff --git a/ApplicationCode/Application/Tools/RiaFilePathTools.h b/ApplicationCode/Application/Tools/RiaFilePathTools.h index 47122b3dcf..2f87756914 100644 --- a/ApplicationCode/Application/Tools/RiaFilePathTools.h +++ b/ApplicationCode/Application/Tools/RiaFilePathTools.h @@ -22,6 +22,8 @@ #include #include +#include +#include #include //================================================================================================== @@ -41,4 +43,8 @@ public: static std::pair toFolderAndFileName( const QString& absFileName ); static QString removeDuplicatePathSeparators( const QString& path ); static QString rootSearchPathFromSearchFilter( const QString& searchFilter ); + + static QStringList splitPathIntoComponents( const QString& path, bool splitExtensionIntoSeparateEntry = false ); + + static std::map keyPathComponentsForEachFilePath( const QStringList& filePaths ); }; diff --git a/ApplicationCode/Application/Tools/RiaTextStringTools.cpp b/ApplicationCode/Application/Tools/RiaTextStringTools.cpp index 261a997519..d87167391b 100644 --- a/ApplicationCode/Application/Tools/RiaTextStringTools.cpp +++ b/ApplicationCode/Application/Tools/RiaTextStringTools.cpp @@ -20,6 +20,7 @@ #include #include +#include //-------------------------------------------------------------------------------------------------- /// @@ -55,3 +56,29 @@ QString RiaTextStringTools::trimAndRemoveDoubleSpaces( const QString& s ) return trimmed; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiaTextStringTools::findCommonRoot( const QStringList& stringList ) +{ + QString root = stringList.front(); + for ( const auto& item : stringList ) + { + if ( root.length() > item.length() ) + { + root.truncate( item.length() ); + } + + for ( int i = 0; i < root.length(); ++i ) + { + if ( root[i] != item[i] ) + { + root.truncate( i ); + break; + } + } + } + + return root; +} diff --git a/ApplicationCode/Application/Tools/RiaTextStringTools.h b/ApplicationCode/Application/Tools/RiaTextStringTools.h index ec85197ed2..10d5829ae4 100644 --- a/ApplicationCode/Application/Tools/RiaTextStringTools.h +++ b/ApplicationCode/Application/Tools/RiaTextStringTools.h @@ -19,6 +19,7 @@ #pragma once class QString; +class QStringList; //-------------------------------------------------------------------------------------------------- /// @@ -27,4 +28,5 @@ namespace RiaTextStringTools { bool compare( const QString& expected, const QString& actual ); QString trimAndRemoveDoubleSpaces( const QString& s ); +QString findCommonRoot( const QStringList& stringList ); } // namespace RiaTextStringTools diff --git a/ApplicationCode/Commands/RicImportEnsembleFeature.cpp b/ApplicationCode/Commands/RicImportEnsembleFeature.cpp index 83c9532964..bd3fac871a 100644 --- a/ApplicationCode/Commands/RicImportEnsembleFeature.cpp +++ b/ApplicationCode/Commands/RicImportEnsembleFeature.cpp @@ -19,7 +19,9 @@ #include "RicImportEnsembleFeature.h" #include "RiaApplication.h" +#include "RiaFilePathTools.h" #include "RiaPreferences.h" +#include "RiaTextStringTools.h" #include "RicCreateSummaryCaseCollectionFeature.h" #include "RicImportSummaryCasesFeature.h" @@ -44,8 +46,13 @@ #include "SummaryPlotCommands/RicNewSummaryPlotFeature.h" #include +#include +#include #include #include +#include + +#include CAF_CMD_SOURCE_INIT( RicImportEnsembleFeature, "RicImportEnsembleFeature" ); @@ -69,7 +76,14 @@ void RicImportEnsembleFeature::onActionTriggered( bool isChecked ) if ( fileNames.isEmpty() ) return; - QString ensembleName = askForEnsembleName(); + QString root = commonRoot( fileNames ); + + QRegularExpression trimRe( "[^a-zA-Z0-9]+$" ); + QString trimmedRoot = root.replace( trimRe, "" ); + QString suggestion = trimmedRoot; + if ( suggestion.isEmpty() ) suggestion = "Ensemble"; + + QString ensembleName = askForEnsembleName( trimmedRoot ); if ( ensembleName.isEmpty() ) return; std::vector cases; @@ -79,6 +93,11 @@ void RicImportEnsembleFeature::onActionTriggered( bool isChecked ) RimSummaryCaseCollection* ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases( cases, ensembleName, true ); + for ( auto summaryCase : ensemble->allSummaryCases() ) + { + summaryCase->updateAutoShortName(); + } + if ( ensemble ) { RicNewSummaryEnsembleCurveSetFeature::createPlotForCurveSetsAndUpdate( {ensemble} ); @@ -105,21 +124,45 @@ void RicImportEnsembleFeature::setupActionLook( QAction* actionToSetup ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RicImportEnsembleFeature::askForEnsembleName() +QString RicImportEnsembleFeature::askForEnsembleName( const QString& suggestion ) { RimProject* project = RimProject::current(); std::vector groups = project->summaryGroups(); - int ensembleCount = std::count_if( groups.begin(), groups.end(), []( RimSummaryCaseCollection* group ) { - return group->isEnsemble(); - } ); - ensembleCount += 1; + int ensemblesStartingWithRoot = + std::count_if( groups.begin(), groups.end(), [suggestion]( RimSummaryCaseCollection* group ) { + return group->isEnsemble() && group->name().startsWith( suggestion ); + } ); QInputDialog dialog; dialog.setInputMode( QInputDialog::TextInput ); dialog.setWindowTitle( "Ensemble Name" ); dialog.setLabelText( "Ensemble Name" ); - dialog.setTextValue( QString( "Ensemble %1" ).arg( ensembleCount ) ); + if ( ensemblesStartingWithRoot > 0 ) + { + dialog.setTextValue( QString( "%1 %2" ).arg( suggestion ).arg( ensemblesStartingWithRoot + 1 ) ); + } + else + { + dialog.setTextValue( suggestion ); + } + dialog.resize( 300, 50 ); dialog.exec(); return dialog.result() == QDialog::Accepted ? dialog.textValue() : QString( "" ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicImportEnsembleFeature::commonRoot( const QStringList& fileList ) +{ + QStringList fileNameList; + for ( auto filePath : fileList ) + { + QFileInfo fileInfo( filePath ); + QString fileNameWithoutExt = fileInfo.baseName(); + fileNameList.push_back( fileNameWithoutExt ); + } + QString root = RiaTextStringTools::findCommonRoot( fileNameList ); + return root; +} diff --git a/ApplicationCode/Commands/RicImportEnsembleFeature.h b/ApplicationCode/Commands/RicImportEnsembleFeature.h index 7c773b1b3b..83e1ff1a7f 100644 --- a/ApplicationCode/Commands/RicImportEnsembleFeature.h +++ b/ApplicationCode/Commands/RicImportEnsembleFeature.h @@ -39,5 +39,6 @@ protected: void onActionTriggered( bool isChecked ) override; void setupActionLook( QAction* actionToSetup ) override; - QString askForEnsembleName(); + QString askForEnsembleName( const QString& suggestion ); + QString commonRoot( const QStringList& fileList ); }; diff --git a/ApplicationCode/Commands/RicReplaceCaseFeature.cpp b/ApplicationCode/Commands/RicReplaceCaseFeature.cpp index cdd02fdc5d..e7e4a8e257 100644 --- a/ApplicationCode/Commands/RicReplaceCaseFeature.cpp +++ b/ApplicationCode/Commands/RicReplaceCaseFeature.cpp @@ -106,7 +106,7 @@ void RicReplaceCaseFeature::onActionTriggered( bool isChecked ) if ( gridSummaryCase ) { gridSummaryCase->setAssociatedEclipseCase( selectedCase ); - gridSummaryCase->resetAutoShortName(); + gridSummaryCase->updateAutoShortName(); gridSummaryCase->createSummaryReaderInterface(); gridSummaryCase->createRftReaderInterface(); diff --git a/ApplicationCode/Commands/RicReplaceSummaryCaseFeature.cpp b/ApplicationCode/Commands/RicReplaceSummaryCaseFeature.cpp index aff1d458f2..06acb00271 100644 --- a/ApplicationCode/Commands/RicReplaceSummaryCaseFeature.cpp +++ b/ApplicationCode/Commands/RicReplaceSummaryCaseFeature.cpp @@ -69,7 +69,7 @@ void RicReplaceSummaryCaseFeature::onActionTriggered( bool isChecked ) QString oldSummaryHeaderFilename = summaryCase->summaryHeaderFilename(); summaryCase->setSummaryHeaderFileName( fileNames[0] ); - summaryCase->resetAutoShortName(); + summaryCase->updateAutoShortName(); summaryCase->createSummaryReaderInterface(); summaryCase->createRftReaderInterface(); RiaLogging::info( QString( "Replaced summary data for %1" ).arg( oldSummaryHeaderFilename ) ); diff --git a/ApplicationCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlot.cpp b/ApplicationCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlot.cpp index c844bc7b88..aec816bd89 100644 --- a/ApplicationCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlot.cpp @@ -274,7 +274,8 @@ void RimCorrelationPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chart { double value = m_showAbsoluteValues() ? std::abs( parameterCorrPair.second ) : parameterCorrPair.second; double sortValue = m_sortByAbsoluteValues() ? std::abs( value ) : value; - QString barText = QString( "%1 (%2)" ).arg( parameterCorrPair.first.name ).arg( parameterCorrPair.second ); + QString barText = + QString( "%1 (%2)" ).arg( parameterCorrPair.first.name ).arg( parameterCorrPair.second, 5, 'f', 2 ); QString majorText = "", medText = "", minText = "", legendText = barText; chartBuilder.addBarEntry( majorText, medText, minText, sortValue, legendText, barText, value ); } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimCalculatedSummaryCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimCalculatedSummaryCase.cpp index c7c7492c66..cff0436631 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimCalculatedSummaryCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimCalculatedSummaryCase.cpp @@ -31,7 +31,7 @@ RimCalculatedSummaryCase::RimCalculatedSummaryCase() CAF_PDM_InitObject( "Calculated", ":/SummaryCase48x48.png", "", "" ); m_calculatedCurveReader = nullptr; - m_shortName = "Calculated"; + m_displayName = "Calculated"; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimDerivedSummaryCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimDerivedSummaryCase.cpp index da7d7f7d24..64fbc77b76 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimDerivedSummaryCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimDerivedSummaryCase.cpp @@ -272,7 +272,7 @@ std::pair, std::vector> //-------------------------------------------------------------------------------------------------- QString RimDerivedSummaryCase::caseName() const { - return m_shortName; + return m_displayName; } //-------------------------------------------------------------------------------------------------- @@ -413,7 +413,7 @@ void RimDerivedSummaryCase::updateDisplayNameFromCases() QString name = operatorText + QString( "(%1 , %2)" ).arg( case1Name, case2Name ); - m_shortName = name; + m_displayName = name; } //-------------------------------------------------------------------------------------------------- @@ -422,7 +422,7 @@ void RimDerivedSummaryCase::updateDisplayNameFromCases() void RimDerivedSummaryCase::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { // Base class - uiOrdering.add( &m_shortName ); + uiOrdering.add( &m_displayName ); uiOrdering.add( &m_summaryCase1 ); uiOrdering.add( &m_operator ); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.cpp index e1fb8796b3..408a439d88 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.cpp @@ -18,18 +18,15 @@ #include "RimSummaryCase.h" +#include "RiaFilePathTools.h" #include "RiaSummaryTools.h" #include "RicfCommandObject.h" #include "RifSummaryReaderInterface.h" #include "RimMainPlotCollection.h" -#include "RimObservedDataCollection.h" -#include "RimObservedSummaryData.h" -#include "RimOilField.h" #include "RimProject.h" #include "RimSummaryCaseCollection.h" -#include "RimSummaryCaseMainCollection.h" #include "RimSummaryPlotCollection.h" #include "cafPdmFieldScriptingCapability.h" @@ -37,20 +34,36 @@ #include "cvfAssert.h" #include +#include CAF_PDM_ABSTRACT_SOURCE_INIT( RimSummaryCase, "SummaryCase" ); -const QString RimSummaryCase::DEFAULT_DISPLAY_NAME = "Display Name"; +namespace caf +{ +template <> +void AppEnum::setUp() +{ + addItem( RimSummaryCase::DisplayName::FULL_CASE_NAME, "FULL_CASE_NAME", "Full Case Name" ); + addItem( RimSummaryCase::DisplayName::SHORT_CASE_NAME, "SHORT_CASE_NAME", "Shortened Case Name" ); + addItem( RimSummaryCase::DisplayName::CUSTOM, "CUSTOM_NAME", "Custom Name" ); + setDefault( RimSummaryCase::DisplayName::SHORT_CASE_NAME ); +} +} // namespace caf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryCase::RimSummaryCase() + : nameChanged( this ) { CAF_PDM_InitScriptableObject( "Summary Case", ":/SummaryCase16x16.png", "", "The Base Class for all Summary Cases" ); - CAF_PDM_InitScriptableField( &m_shortName, "ShortName", QString( "Display Name" ), DEFAULT_DISPLAY_NAME, "", "", "" ); - CAF_PDM_InitScriptableField( &m_useAutoShortName, "AutoShortyName", false, "Use Auto Display Name", "", "", "" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_displayName, "ShortName", "Display Name", "", "", "" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_displayNameOption, "NameSetting", "Name Setting", "", "", "" ); + + CAF_PDM_InitScriptableField( &m_useAutoShortName_OBSOLETE, "AutoShortyName", false, "Use Auto Display Name", "", "", "" ); + m_useAutoShortName_OBSOLETE.xmlCapability()->setIOWritable( false ); + m_useAutoShortName_OBSOLETE.uiCapability()->setUiHidden( true ); CAF_PDM_InitScriptableFieldNoDefault( &m_summaryHeaderFilename, "SummaryHeaderFilename", "Summary Header File", "", "", "" ); m_summaryHeaderFilename.uiCapability()->setUiReadOnly( true ); @@ -92,7 +105,7 @@ void RimSummaryCase::setSummaryHeaderFileName( const QString& fileName ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimSummaryCase::isObservedData() +bool RimSummaryCase::isObservedData() const { return m_isObservedData; } @@ -136,10 +149,10 @@ RimSummaryCaseCollection* RimSummaryCase::ensemble() const //-------------------------------------------------------------------------------------------------- void RimSummaryCase::copyFrom( const RimSummaryCase& rhs ) { - m_shortName = rhs.m_shortName; - m_useAutoShortName = rhs.m_useAutoShortName; - m_summaryHeaderFilename = rhs.m_summaryHeaderFilename; - m_isObservedData = rhs.m_isObservedData; + m_displayName = rhs.m_displayName; + m_useAutoShortName_OBSOLETE = rhs.m_useAutoShortName_OBSOLETE; + m_summaryHeaderFilename = rhs.m_summaryHeaderFilename; + m_isObservedData = rhs.m_isObservedData; this->updateTreeItemName(); this->updateOptionSensitivity(); @@ -160,18 +173,17 @@ void RimSummaryCase::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { - if ( changedField == &m_useAutoShortName ) + if ( changedField == &m_displayNameOption ) { - this->updateAutoShortName(); + updateAutoShortName(); + nameChanged.send(); } - else if ( changedField == &m_shortName ) + else if ( changedField == &m_displayName ) { updateTreeItemName(); + nameChanged.send(); } - RimSummaryPlotCollection* summaryPlotColl = RiaSummaryTools::summaryPlotCollection(); - summaryPlotColl->updateSummaryNameHasChanged(); - updateOptionSensitivity(); } @@ -180,7 +192,7 @@ void RimSummaryCase::fieldChangedByUi( const caf::PdmFieldHandle* changedField, //-------------------------------------------------------------------------------------------------- void RimSummaryCase::updateOptionSensitivity() { - m_shortName.uiCapability()->setUiReadOnly( m_useAutoShortName ); + m_displayName.uiCapability()->setUiReadOnly( m_displayNameOption != DisplayName::CUSTOM ); } //-------------------------------------------------------------------------------------------------- @@ -212,10 +224,7 @@ void RimSummaryCase::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin //-------------------------------------------------------------------------------------------------- void RimSummaryCase::updateTreeItemName() { - if ( caseName() != displayCaseName() ) - this->setUiName( caseName() + " (" + displayCaseName() + ")" ); - else - this->setUiName( caseName() ); + this->setUiName( displayCaseName() ); } //-------------------------------------------------------------------------------------------------- @@ -223,7 +232,7 @@ void RimSummaryCase::updateTreeItemName() //-------------------------------------------------------------------------------------------------- QString RimSummaryCase::displayCaseName() const { - return m_shortName(); + return m_displayName(); } //-------------------------------------------------------------------------------------------------- @@ -257,6 +266,11 @@ void RimSummaryCase::initAfterRead() RimProject::current()->assignCaseIdToSummaryCase( this ); } + if ( m_useAutoShortName_OBSOLETE ) + { + m_displayNameOption = DisplayName::SHORT_CASE_NAME; + } + updateOptionSensitivity(); } @@ -265,70 +279,69 @@ void RimSummaryCase::initAfterRead() //-------------------------------------------------------------------------------------------------- QString RimSummaryCase::uniqueShortNameForCase( RimSummaryCase* summaryCase ) { - RimOilField* oilField = nullptr; - summaryCase->firstAncestorOrThisOfType( oilField ); - CVF_ASSERT( oilField ); + QString ensembleName; + std::vector summaryCases; - std::set allAutoShortNames; - - std::vector allCases = oilField->summaryCaseMainCollection->allSummaryCases(); - std::vector observedDataCases = oilField->observedDataCollection->allObservedSummaryData(); - - for ( auto observedData : observedDataCases ) + auto ensemble = summaryCase->ensemble(); + if ( ensemble ) { - allCases.push_back( observedData ); - } - - for ( RimSummaryCase* sumCase : allCases ) - { - if ( sumCase && sumCase != summaryCase ) - { - allAutoShortNames.insert( sumCase->displayCaseName() ); - } - } - - bool foundUnique = false; - - QString caseName = summaryCase->caseName(); - QString shortName; - - if ( caseName.size() > 2 ) - { - QString candidate; - candidate += caseName[0]; - - for ( int i = 1; i < caseName.size(); ++i ) - { - if ( allAutoShortNames.count( candidate + caseName[i] ) == 0 ) - { - shortName = candidate + caseName[i]; - foundUnique = true; - break; - } - } + summaryCases = ensemble->allSummaryCases(); } else { - shortName = caseName.left( 2 ); - if ( allAutoShortNames.count( shortName ) == 0 ) - { - foundUnique = true; - } + RimProject::current()->descendantsIncludingThisOfType( summaryCases ); } - int autoNumber = 0; + QRegularExpression trimRe( "^[^a-zA-Z0-9]+" ); - while ( !foundUnique ) + QStringList summaryFilePaths; + summaryFilePaths.push_back( summaryCase->summaryHeaderFilename() ); + + for ( auto otherSummaryCase : summaryCases ) { - QString candidate = shortName + QString::number( autoNumber++ ); - if ( allAutoShortNames.count( candidate ) == 0 ) + if ( otherSummaryCase != summaryCase ) { - shortName = candidate; - foundUnique = true; + summaryFilePaths.push_back( otherSummaryCase->summaryHeaderFilename() ); } } - return shortName; + std::map keyFileComponentsForAllFiles = + RiaFilePathTools::keyPathComponentsForEachFilePath( summaryFilePaths ); + + QStringList keyFileComponents = keyFileComponentsForAllFiles[summaryCase->summaryHeaderFilename()]; + CAF_ASSERT( !keyFileComponents.empty() ); + + if ( !ensembleName.isEmpty() ) + { + for ( auto& component : keyFileComponents ) + { + component = component.replace( ensembleName, "" ); + component = component.replace( trimRe, "" ); + } + } + + QStringList shortNameComponents; + QRegularExpression numberRe( "[0-9]+" ); + for ( auto keyComponent : keyFileComponents ) + { + QStringList subComponents; + QString numberGroup = numberRe.match( keyComponent ).captured(); + if ( !numberGroup.isEmpty() ) + { + keyComponent = keyComponent.replace( numberGroup, "" ); + + QString stem = keyComponent.left( 2 ); + if ( !stem.isEmpty() ) subComponents.push_back( stem ); + subComponents.push_back( numberGroup ); + } + else + { + subComponents.push_back( keyComponent.left( 4 ) ); + } + + shortNameComponents.push_back( subComponents.join( "-" ) ); + } + return shortNameComponents.join( "," ); } //-------------------------------------------------------------------------------------------------- @@ -336,27 +349,18 @@ QString RimSummaryCase::uniqueShortNameForCase( RimSummaryCase* summaryCase ) //-------------------------------------------------------------------------------------------------- void RimSummaryCase::updateAutoShortName() { - if ( m_useAutoShortName ) + if ( m_displayNameOption == DisplayName::FULL_CASE_NAME ) { - m_shortName = RimSummaryCase::uniqueShortNameForCase( this ); + m_displayName = caseName(); } - else if ( m_shortName() == DEFAULT_DISPLAY_NAME ) + else if ( m_displayNameOption == DisplayName::SHORT_CASE_NAME ) { - m_shortName = caseName(); + m_displayName = RimSummaryCase::uniqueShortNameForCase( this ); } updateTreeItemName(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryCase::resetAutoShortName() -{ - m_shortName = DEFAULT_DISPLAY_NAME; - updateAutoShortName(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h index 942764690a..ac8a64969d 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCase.h @@ -40,6 +40,17 @@ class RimSummaryCase : public caf::PdmObject { CAF_PDM_HEADER_INIT; +public: + caf::Signal<> nameChanged; + + enum class DisplayName + { + FULL_CASE_NAME, + SHORT_CASE_NAME, + CUSTOM + }; + using DisplayNameEnum = caf::AppEnum; + public: RimSummaryCase(); ~RimSummaryCase() override; @@ -53,7 +64,6 @@ public: RiaEclipseUnitTools::UnitSystemType unitsSystem(); void updateAutoShortName(); - void resetAutoShortName(); void updateOptionSensitivity(); virtual void createSummaryReaderInterface() = 0; @@ -66,7 +76,7 @@ public: void setSummaryHeaderFileName( const QString& fileName ); - bool isObservedData(); + bool isObservedData() const; void setCaseRealizationParameters( const std::shared_ptr& crlParameters ); std::shared_ptr caseRealizationParameters() const; @@ -88,13 +98,16 @@ private: static QString uniqueShortNameForCase( RimSummaryCase* summaryCase ); protected: - caf::PdmField m_shortName; - caf::PdmField m_useAutoShortName; - caf::PdmField m_summaryHeaderFilename; - bool m_isObservedData; - caf::PdmField m_caseId; + caf::PdmField m_displayName; + caf::PdmField m_displayNameOption; + caf::PdmField m_summaryHeaderFilename; + + bool m_isObservedData; + caf::PdmField m_caseId; std::shared_ptr m_crlParameters; + caf::PdmField m_useAutoShortName_OBSOLETE; + static const QString DEFAULT_DISPLAY_NAME; }; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index f2227737a7..2ea7772c95 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -187,6 +187,7 @@ QString EnsembleParameter::uiName() const /// //-------------------------------------------------------------------------------------------------- RimSummaryCaseCollection::RimSummaryCaseCollection() + : caseNameChanged( this ) { CAF_PDM_InitScriptableObject( "Summary Case Group", ":/SummaryGroup16x16.png", "", "" ); @@ -227,6 +228,8 @@ RimSummaryCaseCollection::~RimSummaryCaseCollection() void RimSummaryCaseCollection::removeCase( RimSummaryCase* summaryCase ) { size_t caseCountBeforeRemove = m_cases.size(); + + summaryCase->nameChanged.disconnect( this ); m_cases.removeChildObject( summaryCase ); m_cachedSortedEnsembleParameters.clear(); @@ -245,6 +248,8 @@ void RimSummaryCaseCollection::removeCase( RimSummaryCase* summaryCase ) //-------------------------------------------------------------------------------------------------- void RimSummaryCaseCollection::addCase( RimSummaryCase* summaryCase, bool updateCurveSets ) { + summaryCase->nameChanged.connect( this, &RimSummaryCaseCollection::onCaseNameChanged ); + m_cases.push_back( summaryCase ); m_cachedSortedEnsembleParameters.clear(); @@ -982,6 +987,14 @@ void RimSummaryCaseCollection::fieldChangedByUi( const caf::PdmFieldHandle* chan } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryCaseCollection::onCaseNameChanged( const SignalEmitter* emitter ) +{ + caseNameChanged.send(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h index b76803d9cf..fd3c8b02b8 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h @@ -91,6 +91,9 @@ class RimSummaryCaseCollection : public caf::PdmObject { CAF_PDM_HEADER_INIT; +public: + caf::Signal<> caseNameChanged; + public: RimSummaryCaseCollection(); ~RimSummaryCaseCollection() override; @@ -146,6 +149,8 @@ private: void initAfterRead() override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void onCaseNameChanged( const SignalEmitter* emitter ); + protected: virtual void onLoadDataAndUpdate(); void updateReferringCurveSets(); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp index cbd1c64a21..c4bc76d9f1 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp @@ -17,6 +17,9 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimSummaryCaseMainCollection.h" +#include "RiaSummaryTools.h" +#include "RimSummaryPlotCollection.h" + #include "RifCaseRealizationParametersReader.h" #include "RifEclipseSummaryTools.h" #include "RifSummaryCaseRestartSelector.h" @@ -30,6 +33,7 @@ #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" #include "RimSummaryCurve.h" +#include "RimSummaryPlot.h" #include "cafProgressInfo.h" #include @@ -213,6 +217,7 @@ void RimSummaryCaseMainCollection::addCases( const std::vector void RimSummaryCaseMainCollection::addCase( RimSummaryCase* summaryCase ) { m_cases.push_back( summaryCase ); + summaryCase->nameChanged.connect( this, &RimSummaryCaseMainCollection::onCaseNameChanged ); } //-------------------------------------------------------------------------------------------------- @@ -235,7 +240,9 @@ void RimSummaryCaseMainCollection::removeCase( RimSummaryCase* summaryCase ) } } + summaryCase->nameChanged.disconnect( this ); m_cases.removeChildObject( summaryCase ); + for ( RimSummaryCaseCollection* summaryCaseCollection : m_caseCollections ) { summaryCaseCollection->removeCase( summaryCase ); @@ -285,6 +292,7 @@ RimSummaryCaseCollection* summaryCaseCollection->setAsEnsemble( isEnsemble ); + summaryCaseCollection->caseNameChanged.connect( this, &RimSummaryCaseMainCollection::onCaseNameChanged ); m_caseCollections.push_back( summaryCaseCollection ); return summaryCaseCollection; @@ -295,6 +303,7 @@ RimSummaryCaseCollection* //-------------------------------------------------------------------------------------------------- void RimSummaryCaseMainCollection::removeCaseCollection( RimSummaryCaseCollection* caseCollection ) { + caseCollection->caseNameChanged.disconnect( this ); m_caseCollections.removeChildObject( caseCollection ); } @@ -487,6 +496,15 @@ RimSummaryCaseCollection* RimSummaryCaseMainCollection::defaultAllocator() return new RimSummaryCaseCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryCaseMainCollection::onCaseNameChanged( const SignalEmitter* emitter ) +{ + RimSummaryPlotCollection* summaryPlotColl = RiaSummaryTools::summaryPlotCollection(); + summaryPlotColl->updateSummaryNameHasChanged(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.h index f51be0d645..8a061427e3 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.h @@ -78,6 +78,8 @@ private: static void reassignSummaryCurves( const RimGridSummaryCase* fromGridCase, RimFileSummaryCase* toFileCase ); static RimSummaryCaseCollection* defaultAllocator(); + void onCaseNameChanged( const SignalEmitter* emitter ); + private: caf::PdmChildArrayField m_cases; caf::PdmChildArrayField m_caseCollections;