#8310 Summary Plot Manager : Add data source filtering

This commit is contained in:
Magne Sjaastad 2021-11-19 14:53:01 +01:00
parent c945166e81
commit 5fcb81980d
17 changed files with 611 additions and 123 deletions

View File

@ -48,6 +48,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaValidRegExpValidator.h
${CMAKE_CURRENT_LIST_DIR}/RiaVec3Tools.h
${CMAKE_CURRENT_LIST_DIR}/RiaEnsembleNameTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryStringTools.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -93,6 +94,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaValidRegExpValidator.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaEnsembleNameTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaVec3Tools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryStringTools.cpp
)
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})

View File

@ -0,0 +1,110 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaSummaryStringTools.h"
#include "RiaLogging.h"
#include "RifEclipseSummaryAddress.h"
#include "RifSummaryReaderInterface.h"
#include "RimSummaryCase.h"
#include <QRegularExpression>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryStringTools::splitAddressFiltersInGridAndSummary( RimSummaryCase* summaryCase,
const QStringList& addressFilters,
QStringList* summaryAddressFilters,
QStringList* gridResultAddressFilters )
{
if ( summaryCase )
{
const std::set<RifEclipseSummaryAddress>& addrs = summaryCase->summaryReader()->allResultAddresses();
QRegularExpression gridAddressPattern( "^[A-Z]+:[0-9]+,[0-9]+,[0-9]+$" );
for ( int filterIdx = 0; filterIdx < addressFilters.size(); ++filterIdx )
{
const QString& address = addressFilters[filterIdx];
if ( hasFilterAnyMatch( address, addrs ) )
{
summaryAddressFilters->push_back( address );
}
else
{
if ( gridAddressPattern.match( address ).hasMatch() )
{
gridResultAddressFilters->push_back( address );
}
else
{
RiaLogging::warning( "No summary or restart vectors matched \"" + address + "\"" );
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaSummaryStringTools::hasFilterAnyMatch( const QString& curveFilter,
const std::set<RifEclipseSummaryAddress>& summaryAddresses )
{
for ( const auto& addr : summaryAddresses )
{
if ( addr.isUiTextMatchingFilterText( curveFilter ) ) return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
/// Sort filters into curve and data source filters
//--------------------------------------------------------------------------------------------------
void RiaSummaryStringTools::splitIntoAddressAndDataSourceFilters( const QStringList& filters,
const QStringList& dataSourceNames,
QStringList& addressFilters,
QStringList& dataSourceFilters )
{
for ( const auto& s : filters )
{
// Strip off realization filter from ensemble search string
QString pureDataSourceCandidate = s.left( s.indexOf( ':' ) );
bool foundDataSource = false;
QRegExp searcher( pureDataSourceCandidate, Qt::CaseInsensitive, QRegExp::WildcardUnix );
for ( const auto& ds : dataSourceNames )
{
if ( !foundDataSource && searcher.exactMatch( ds ) )
{
dataSourceFilters.push_back( s );
foundDataSource = true;
}
}
if ( !foundDataSource )
{
addressFilters.push_back( s );
}
}
}

View File

@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <set>
class RimSummaryCase;
class RifEclipseSummaryAddress;
class QString;
class QStringList;
//==================================================================================================
//
//==================================================================================================
class RiaSummaryStringTools
{
public:
static void splitAddressFiltersInGridAndSummary( RimSummaryCase* summaryCase,
const QStringList& addressFilters,
QStringList* summaryAddressFilters,
QStringList* gridResultAddressFilters );
static bool hasFilterAnyMatch( const QString& curveFilter, const std::set<RifEclipseSummaryAddress>& summaryAddresses );
static void splitIntoAddressAndDataSourceFilters( const QStringList& filters,
const QStringList& dataSourceNames,
QStringList& addressFilters,
QStringList& dataSourceFilters );
};

View File

@ -43,6 +43,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicSetSourceSteppingEnsembleCurveSetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicActivateCurveFilterInToolbarFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedSummaryFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicShowSummaryPlotManagerFeature.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -90,6 +91,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicSetSourceSteppingEnsembleCurveSetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicActivateCurveFilterInToolbarFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedSummaryFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicShowSummaryPlotManagerFeature.cpp
)
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -0,0 +1,55 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicShowSummaryPlotManagerFeature.h"
#include "RiaGuiApplication.h"
#include "RiuPlotMainWindow.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicShowSummaryPlotManagerFeature, "RicShowSummaryPlotManagerFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicShowSummaryPlotManagerFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowSummaryPlotManagerFeature::onActionTriggered( bool isChecked )
{
RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow();
if ( mpw )
{
mpw->showAndSetKeyboardFocusToSummaryPlotManager();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowSummaryPlotManagerFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Show Summary Plot Manager" );
applyShortcutWithHintToAction( actionToSetup, QKeySequence( tr( "Ctrl+K" ) ) );
}

View File

@ -0,0 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicShowSummaryPlotManagerFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -26,6 +26,7 @@
#include "RiaImportEclipseCaseTools.h"
#include "RiaLogging.h"
#include "RiaPreferencesSummary.h"
#include "RiaSummaryStringTools.h"
#include "RicCreateSummaryCaseCollectionFeature.h"
#include "RicImportGeneralDataFeature.h"
@ -351,7 +352,7 @@ void RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine( const QStrin
RimSummaryPlotCollection* sumPlotColl = RimProject::current()->mainPlotCollection()->summaryPlotCollection();
splitAddressFiltersInGridAndSummary( summaryCasesToUse[0],
RiaSummaryStringTools::splitAddressFiltersInGridAndSummary( summaryCasesToUse[0],
allCurveAddressFilters,
&summaryAddressFilters,
&gridResultAddressFilters );
@ -702,42 +703,6 @@ std::vector<RimSummaryPlot*> RicSummaryPlotFeatureImpl::createMultipleSummaryPlo
return newSummaryPlots;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSummaryPlotFeatureImpl::splitAddressFiltersInGridAndSummary( RimSummaryCase* summaryCase,
const QStringList& addressFilters,
QStringList* summaryAddressFilters,
QStringList* gridResultAddressFilters )
{
if ( summaryCase )
{
const std::set<RifEclipseSummaryAddress>& addrs = summaryCase->summaryReader()->allResultAddresses();
QRegularExpression gridAddressPattern( "^[A-Z]+:[0-9]+,[0-9]+,[0-9]+$" );
for ( int filterIdx = 0; filterIdx < addressFilters.size(); ++filterIdx )
{
const QString& address = addressFilters[filterIdx];
if ( hasFilterAnyMatch( address, addrs ) )
{
summaryAddressFilters->push_back( address );
}
else
{
if ( gridAddressPattern.match( address ).hasMatch() )
{
gridResultAddressFilters->push_back( address );
}
else
{
RiaLogging::warning( "No summary or restart vectors matched \"" + address + "\"" );
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -765,20 +730,6 @@ std::set<RifEclipseSummaryAddress>
return filteredAdressesFromCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicSummaryPlotFeatureImpl::hasFilterAnyMatch( const QString& curveFilter,
const std::set<RifEclipseSummaryAddress>& summaryAddresses )
{
for ( const auto& addr : summaryAddresses )
{
if ( addr.isUiTextMatchingFilterText( curveFilter ) ) return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -93,8 +93,6 @@ private:
static RimSummaryCurve* createCurve( RimSummaryCase* summaryCase, const RifEclipseSummaryAddress& address );
static bool hasFilterAnyMatch( const QString& curveFilter, const std::set<RifEclipseSummaryAddress>& summaryAddresses );
static RimSummaryCurve* createHistoryCurve( const RifEclipseSummaryAddress& addr, RimSummaryCase* summaryCasesToUse );
static std::vector<RimSummaryCurve*> addCurvesFromAddressFiltersToPlot( const QStringList& curveFilters,
@ -105,11 +103,6 @@ private:
static std::set<RifEclipseSummaryAddress>
applySummaryAddressFiltersToCases( const std::vector<RimSummaryCase*>& summaryCasesToUse,
const QStringList& summaryAddressFilters );
static void splitAddressFiltersInGridAndSummary( RimSummaryCase* summaryCase,
const QStringList& addressFilters,
QStringList* summaryAddressFilters,
QStringList* gridResultAddressFilters );
};
#include "RigEclipseResultAddress.h"

View File

@ -19,6 +19,8 @@
#include "RimSummaryPlotManager.h"
#include "RiaStdStringTools.h"
#include "RiaStringListSerializer.h"
#include "RiaSummaryStringTools.h"
#include "RiaSummaryTools.h"
#include "RifReaderEclipseSummary.h"
@ -35,9 +37,13 @@
#include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h"
#include "RiuPlotMainWindowTools.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiLabelEditor.h"
#include "cafPdmUiLineEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafSelectionManager.h"
@ -53,13 +59,18 @@ RimSummaryPlotManager::RimSummaryPlotManager()
CAF_PDM_InitObject( "Summary Plot Manager" );
CAF_PDM_InitFieldNoDefault( &m_summaryPlot, "SummaryPlot", "Summary Plot" );
CAF_PDM_InitFieldNoDefault( &m_curveFilterText, "CurveFilterText", "Curve Filter Text" );
CAF_PDM_InitFieldNoDefault( &m_curveCandidates, "CurveCandidates", "Candidates" );
CAF_PDM_InitFieldNoDefault( &m_filterText, "FilterText", "Filter Text" );
m_filterText.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_addressCandidates, "AddressCandidates", "Vectors" );
m_addressCandidates.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
CAF_PDM_InitFieldNoDefault( &m_dataSourceCandidates, "DataSourceCandidates", "Data Sources" );
m_dataSourceCandidates.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
CAF_PDM_InitField( &m_includeDiffCurves,
"IncludeDiffCurves",
true,
"Include Difference Curves",
false,
"Include Difference Vectors",
"",
"Difference between simulated and observed(history) curve",
"" );
@ -87,6 +98,14 @@ RimSummaryPlotManager::RimSummaryPlotManager()
m_labelB.xmlCapability()->disableIO();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotManager::setFocusToFilterText()
{
setFocusToEditorWidget( m_filterText.uiCapability() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -102,24 +121,28 @@ void RimSummaryPlotManager::fieldChangedByUi( const caf::PdmFieldHandle* changed
const QVariant& oldValue,
const QVariant& newValue )
{
if ( changedField == &m_curveFilterText || changedField == &m_includeDiffCurves )
if ( changedField == &m_summaryPlot || changedField == &m_filterText || changedField == &m_includeDiffCurves )
{
updateCurveCandidates();
updateDataSourceCandidates();
}
else if ( changedField == &m_pushButtonReplace )
{
replaceCurves();
m_pushButtonReplace = false;
updateFilterTextHistory();
}
else if ( changedField == &m_pushButtonNewPlot )
{
createNewPlot();
m_pushButtonNewPlot = false;
updateFilterTextHistory();
}
else if ( changedField == &m_pushButtonAppend )
{
appendCurves();
m_pushButtonAppend = false;
updateFilterTextHistory();
}
}
@ -136,6 +159,16 @@ QList<caf::PdmOptionItemInfo>
coll->summaryPlotItemInfos( &options );
}
if ( fieldNeedingOptions == &m_filterText )
{
RiaStringListSerializer stringListSerializer( curveFilterRecentlyUsedRegistryKey() );
for ( const auto& s : stringListSerializer.textStrings() )
{
options.push_back( caf::PdmOptionItemInfo( s, s ) );
}
}
return options;
}
@ -144,28 +177,97 @@ QList<caf::PdmOptionItemInfo>
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotManager::updateCurveCandidates()
{
m_curveCandidates.value().clear();
if ( !m_summaryPlot ) return;
auto curves = m_summaryPlot->summaryAndEnsembleCurves();
if ( curves.empty() ) return;
auto firstSource = curves.front()->summaryCaseY();
if ( !firstSource ) return;
std::set<RifEclipseSummaryAddress> addressesFromSources = addressesForSource( firstSource );
QStringList addressFilters = m_curveFilterText().split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
auto addresses = computeFilteredAddresses( addressFilters, addressesFromSources );
std::vector<QString> curveCandidates;
auto addresses = filteredAddresses();
for ( const auto& adr : addresses )
{
curveCandidates.push_back( QString::fromStdString( adr.uiText() ) );
}
m_curveCandidates = curveCandidates;
m_addressCandidates = curveCandidates;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotManager::updateDataSourceCandidates()
{
std::vector<QString> dataSourceDisplayNames;
std::vector<std::pair<QString, PdmObject*>> dataSourceCandidates = findDataSourceCandidates();
for ( const auto& candidate : dataSourceCandidates )
{
dataSourceDisplayNames.push_back( candidate.first );
}
m_dataSourceCandidates = dataSourceDisplayNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<QString, caf::PdmObject*>> RimSummaryPlotManager::findDataSourceCandidates() const
{
std::vector<std::pair<QString, PdmObject*>> candidates;
QStringList addressFilters;
QStringList dataSourceFilters;
splitIntoAddressAndDataSourceFilters( addressFilters, dataSourceFilters );
// If no filter on data source is specified, use wildcard to match all
if ( dataSourceFilters.empty() ) dataSourceFilters.push_back( "*" );
auto [summaryCases, ensembles] = allDataSourcesInProject();
for ( const auto& dsFilter : dataSourceFilters )
{
QString searchString = dsFilter.left( dsFilter.indexOf( ':' ) );
QRegExp searcher( searchString, Qt::CaseInsensitive, QRegExp::WildcardUnix );
for ( const auto& ensemble : ensembles )
{
auto ensembleName = ensemble->name();
if ( searcher.exactMatch( ensembleName ) )
{
if ( searchString == dsFilter )
{
// Match on ensemble name without realization filter
candidates.push_back( std::make_pair( ensembleName, ensemble ) );
}
else
{
// Match on subset of realisations in ensemble
QString realizationSearchString = dsFilter.right( dsFilter.size() - dsFilter.indexOf( ':' ) - 1 );
QRegExp realizationSearcher( realizationSearchString, Qt::CaseInsensitive, QRegExp::WildcardUnix );
for ( const auto& summaryCase : ensemble->allSummaryCases() )
{
auto realizationName = summaryCase->displayCaseName();
if ( realizationSearcher.exactMatch( realizationName ) )
{
QString displayName = ensembleName + ":" + realizationName;
candidates.push_back( std::make_pair( displayName, summaryCase ) );
}
}
}
}
}
for ( const auto& summaryCase : summaryCases )
{
auto summaryCaseName = summaryCase->displayCaseName();
if ( searcher.exactMatch( summaryCaseName ) )
{
candidates.push_back( std::make_pair( summaryCase->displayCaseName(), summaryCase ) );
}
}
}
return candidates;
}
//--------------------------------------------------------------------------------------------------
@ -203,23 +305,34 @@ void RimSummaryPlotManager::defineEditorAttribute( const caf::PdmFieldHandle* fi
caf::PdmUiEditorAttribute* attribute )
{
{
auto myAttr = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute );
if ( myAttr )
auto attr = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute );
if ( attr )
{
if ( field == &m_pushButtonReplace )
{
myAttr->m_buttonText = "Replace Curves \n(Ctrl + Enter)";
attr->m_buttonText = "Replace Curves \n(Ctrl + Enter)";
}
if ( field == &m_pushButtonNewPlot )
{
myAttr->m_buttonText = "Create New Plot \n(Alt + Enter)";
attr->m_buttonText = "Create New Plot \n(Alt + Enter)";
}
if ( field == &m_pushButtonAppend )
{
myAttr->m_buttonText = "Append Curves \n(Shift + Enter)";
attr->m_buttonText = "Append Curves \n(Shift + Enter)";
}
}
}
if ( field == &m_filterText )
{
auto attr = dynamic_cast<caf::PdmUiComboBoxEditorAttribute*>( attribute );
if ( attr )
{
attr->enableEditableContent = true;
attr->adjustWidthToContents = true;
attr->notifyWhenTextIsEdited = true;
}
}
}
//--------------------------------------------------------------------------------------------------
@ -229,15 +342,15 @@ void RimSummaryPlotManager::defineUiOrdering( QString uiConfigName, caf::PdmUiOr
{
uiOrdering.add( &m_summaryPlot );
// uiOrdering.add( &m_labelA );
uiOrdering.add( &m_includeDiffCurves );
uiOrdering.add( &m_curveFilterText );
uiOrdering.add( &m_curveCandidates );
uiOrdering.add( &m_filterText );
uiOrdering.add( &m_addressCandidates );
uiOrdering.add( &m_dataSourceCandidates, false );
uiOrdering.add( &m_labelB );
uiOrdering.add( &m_pushButtonAppend, { false } );
uiOrdering.add( &m_pushButtonAppend );
uiOrdering.add( &m_pushButtonReplace, { false } );
uiOrdering.add( &m_labelB, { false } );
uiOrdering.add( &m_pushButtonNewPlot, { false } );
}
@ -260,6 +373,8 @@ void RimSummaryPlotManager::replaceCurves()
destinationPlot->deleteAllSummaryCurves();
destinationPlot->ensembleCurveSetCollection()->deleteAllCurveSets();
RiuPlotMainWindowTools::selectAsCurrentItem( destinationPlot );
appendCurvesToPlot( destinationPlot );
}
@ -292,6 +407,11 @@ bool RimSummaryPlotManager::eventFilter( QObject* obj, QEvent* event )
replaceCurves();
else if ( mods & Qt::AltModifier )
createNewPlot();
else if ( mods == Qt::NoModifier )
{
updateCurveCandidates();
updateDataSourceCandidates();
}
}
}
@ -301,7 +421,8 @@ bool RimSummaryPlotManager::eventFilter( QObject* obj, QEvent* event )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<std::vector<RimSummaryCase*>, std::vector<RimSummaryCaseCollection*>> RimSummaryPlotManager::dataSources() const
std::pair<std::vector<RimSummaryCase*>, std::vector<RimSummaryCaseCollection*>>
RimSummaryPlotManager::allDataSourcesInProject() const
{
auto sumCaseMainColl = RiaSummaryTools::summaryCaseMainCollection();
@ -324,8 +445,18 @@ void RimSummaryPlotManager::updateUiFromSelection()
if ( m_summaryPlot != summaryPlot )
{
m_summaryPlot = summaryPlot;
updateConnectedEditors();
if ( summaryPlot )
{
updateCurveCandidates();
updateDataSourceCandidates();
}
else
{
std::vector<QString> tmp;
m_addressCandidates = tmp;
m_dataSourceCandidates = tmp;
}
updateConnectedEditors();
}
}
@ -334,24 +465,25 @@ void RimSummaryPlotManager::updateUiFromSelection()
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RimSummaryPlotManager::filteredAddresses()
{
auto [summaryCases, ensembles] = dataSources();
std::set<RifEclipseSummaryAddress> allAddressesFromSource;
std::vector<RimSummaryCase*> summaryCases;
std::vector<RimSummaryCaseCollection*> ensembles;
findFilteredSummaryCasesAndEnsembles( summaryCases, ensembles );
std::set<RifEclipseSummaryAddress> nativeAddresses;
if ( !summaryCases.empty() )
{
allAddressesFromSource = addressesForSource( summaryCases.front() );
nativeAddresses = addressesForSource( summaryCases.front() );
}
else if ( !ensembles.empty() )
{
allAddressesFromSource = addressesForSource( ensembles.front() );
nativeAddresses = addressesForSource( ensembles.front() );
}
if ( allAddressesFromSource.empty() ) return {};
if ( nativeAddresses.empty() ) return {};
QStringList allCurveAddressFilters = m_curveFilterText().split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
QStringList allCurveAddressFilters = m_filterText().split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
return computeFilteredAddresses( allCurveAddressFilters, allAddressesFromSource );
return computeFilteredAddresses( allCurveAddressFilters, nativeAddresses );
}
//--------------------------------------------------------------------------------------------------
@ -437,7 +569,9 @@ void RimSummaryPlotManager::appendCurvesToPlot( RimSummaryPlot* destinationPlot
{
CAF_ASSERT( destinationPlot );
auto [summaryCases, ensembles] = dataSources();
std::vector<RimSummaryCase*> summaryCases;
std::vector<RimSummaryCaseCollection*> ensembles;
findFilteredSummaryCasesAndEnsembles( summaryCases, ensembles );
std::set<RifEclipseSummaryAddress> filteredAddressesFromSource = filteredAddresses();
appendCurvesToPlot( destinationPlot, filteredAddressesFromSource, summaryCases, ensembles );
@ -447,7 +581,21 @@ void RimSummaryPlotManager::appendCurvesToPlot( RimSummaryPlot* destinationPlot
RiaSummaryTools::summaryPlotCollection()->updateConnectedEditors();
setFocusToEditorWidget( m_curveFilterText.uiCapability() );
updateFilterTextHistory();
m_filterText.uiCapability()->updateConnectedEditors();
setFocusToFilterText();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotManager::updateFilterTextHistory()
{
RiaStringListSerializer stringListSerializer( curveFilterRecentlyUsedRegistryKey() );
int maxItemCount = 10;
stringListSerializer.addString( m_filterText, maxItemCount );
}
//--------------------------------------------------------------------------------------------------
@ -472,3 +620,61 @@ void RimSummaryPlotManager::setFocusToEditorWidget( caf::PdmUiFieldHandle* uiFie
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotManager::splitIntoAddressAndDataSourceFilters( QStringList& addressFilters,
QStringList& dataSourceFilters ) const
{
QStringList filterItems = m_filterText().split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
auto [summaryCases, ensembles] = allDataSourcesInProject();
QStringList dataSourceNames;
for ( const auto& summaryCase : summaryCases )
{
dataSourceNames.push_back( summaryCase->displayCaseName() );
}
for ( const auto& ensemble : ensembles )
{
dataSourceNames.push_back( ensemble->name() );
}
RiaSummaryStringTools::splitIntoAddressAndDataSourceFilters( filterItems,
dataSourceNames,
addressFilters,
dataSourceFilters );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlotManager::findFilteredSummaryCasesAndEnsembles( std::vector<RimSummaryCase*>& summaryCases,
std::vector<RimSummaryCaseCollection*>& ensembles ) const
{
auto filteredDataSources = findDataSourceCandidates();
for ( const auto& ds : filteredDataSources )
{
auto summaryCase = dynamic_cast<RimSummaryCase*>( ds.second );
if ( summaryCase )
{
summaryCases.push_back( summaryCase );
}
auto ensemble = dynamic_cast<RimSummaryCaseCollection*>( ds.second );
if ( ensemble )
{
ensembles.push_back( ensemble );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryPlotManager::curveFilterRecentlyUsedRegistryKey()
{
return "SummaryPlotManagerCurveFilterStrings";
}

View File

@ -39,6 +39,8 @@ class RimSummaryPlotManager : public QObject, public caf::PdmObject, public caf:
public:
RimSummaryPlotManager();
void setFocusToFilterText();
private:
void appendCurves();
void replaceCurves();
@ -60,15 +62,19 @@ private:
bool eventFilter( QObject* obj, QEvent* event ) override;
void updateCurveCandidates();
void updateDataSourceCandidates();
std::vector<std::pair<QString, caf::PdmObject*>> findDataSourceCandidates() const;
std::set<RifEclipseSummaryAddress> computeFilteredAddresses( const QStringList& textFilters,
const std::set<RifEclipseSummaryAddress>& sourceAddresses );
std::pair<std::vector<RimSummaryCase*>, std::vector<RimSummaryCaseCollection*>> dataSources() const;
std::pair<std::vector<RimSummaryCase*>, std::vector<RimSummaryCaseCollection*>> allDataSourcesInProject() const;
void updateUiFromSelection();
std::set<RifEclipseSummaryAddress> filteredAddresses();
void appendCurvesToPlot( RimSummaryPlot* destinationPlot );
void updateFilterTextHistory();
// Static helper functions
static std::set<RifEclipseSummaryAddress> addressesForSource( caf::PdmObject* summarySource );
@ -83,11 +89,18 @@ private:
static void setFocusToEditorWidget( caf::PdmUiFieldHandle* uiFieldHandle );
void splitIntoAddressAndDataSourceFilters( QStringList& addressFilters, QStringList& dataSourceFilters ) const;
void findFilteredSummaryCasesAndEnsembles( std::vector<RimSummaryCase*>& summaryCases,
std::vector<RimSummaryCaseCollection*>& ensembles ) const;
static QString curveFilterRecentlyUsedRegistryKey();
private:
caf::PdmPtrField<RimSummaryPlot*> m_summaryPlot;
caf::PdmField<QString> m_curveFilterText;
caf::PdmField<std::vector<QString>> m_curveCandidates;
caf::PdmField<QString> m_filterText;
caf::PdmField<std::vector<QString>> m_addressCandidates;
caf::PdmField<std::vector<QString>> m_dataSourceCandidates;
caf::PdmField<bool> m_includeDiffCurves;

View File

@ -81,6 +81,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/StructGridInterface-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/opm-summary-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseTextFileReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaSummaryStringTools-Test.cpp
)
if(RESINSIGHT_ENABLE_GRPC)

View File

@ -0,0 +1,52 @@
#include "gtest/gtest.h"
#include "RiaSummaryStringTools.h"
#include <QString>
#include <QStringList>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaSummaryStringToolsTest, ParseNumbers )
{
QString wellFilter = "wopt:op_*";
QString fieldFilter = "fopt";
QStringList dataSourceNames = { "iter-1", "iter-22", "real-10", "real-11" };
{
QString dataSourceFilter = "iter-1";
QStringList arguments = { wellFilter, fieldFilter, dataSourceFilter };
QStringList addressFilters;
QStringList dataSourceFilters;
RiaSummaryStringTools::splitIntoAddressAndDataSourceFilters( arguments,
dataSourceNames,
addressFilters,
dataSourceFilters );
EXPECT_TRUE( addressFilters[0] == wellFilter );
EXPECT_TRUE( addressFilters[1] == fieldFilter );
EXPECT_TRUE( dataSourceFilters[0] == dataSourceFilter );
}
{
QString dataSourceFilter = "iter-22:real-2*";
QStringList arguments = { wellFilter, fieldFilter, dataSourceFilter };
QStringList addressFilters;
QStringList dataSourceFilters;
RiaSummaryStringTools::splitIntoAddressAndDataSourceFilters( arguments,
dataSourceNames,
addressFilters,
dataSourceFilters );
EXPECT_TRUE( addressFilters[0] == wellFilter );
EXPECT_TRUE( addressFilters[1] == fieldFilter );
EXPECT_TRUE( dataSourceFilters[0] == dataSourceFilter );
}
}

View File

@ -103,9 +103,9 @@ QString RiuDockWidgetTools::undoStackName()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuDockWidgetTools::summaryCurveManagerName()
QString RiuDockWidgetTools::summaryPlotManagerName()
{
return "dockSummaryCurveManager";
return "dockSummaryPlotManager";
}
//--------------------------------------------------------------------------------------------------

View File

@ -46,7 +46,7 @@ public:
static QString messagesName();
static QString mohrsCirclePlotName();
static QString undoStackName();
static QString summaryCurveManagerName();
static QString summaryPlotManagerName();
static QString plotMainWindowProjectTreeName();
static QString plotMainWindowPropertyEditorName();
@ -66,9 +66,9 @@ public:
static void setDockWidgetVisibility( const QObject* parent, const QString& dockWidgetName, bool isVisible );
static void applyDockWidgetVisibilities( const QObject* parent, const QMap<QString, QVariant>& visibilityMap );
static QDockWidget* findDockWidget( const QObject* parent, const QString& dockWidgetName );
private:
static QMap<QString, QVariant> widgetVisibilitiesForEclipse();
static QMap<QString, QVariant> widgetVisibilitiesForGeoMech();
static QDockWidget* findDockWidget( const QObject* parent, const QString& dockWidgetName );
};

View File

@ -106,7 +106,7 @@ RiuPlotMainWindow::RiuPlotMainWindow()
//--------------------------------------------------------------------------------------------------
RiuPlotMainWindow::~RiuPlotMainWindow()
{
m_summaryCurveManagerView->showProperties( nullptr );
m_summaryPlotManagerView->showProperties( nullptr );
setPdmRoot( nullptr );
}
@ -502,17 +502,17 @@ void RiuPlotMainWindow::createDockPanels()
}
{
QDockWidget* dockWidget = new QDockWidget( "Curve Manager", this );
dockWidget->setObjectName( RiuDockWidgetTools::summaryCurveManagerName() );
QDockWidget* dockWidget = new QDockWidget( "Plot Manager", this );
dockWidget->setObjectName( RiuDockWidgetTools::summaryPlotManagerName() );
m_summaryCurveManagerView = new caf::PdmUiPropertyView( dockWidget );
m_summaryPlotManagerView = new caf::PdmUiPropertyView( dockWidget );
auto curveManager = std::make_unique<RimSummaryPlotManager>();
m_summaryCurveManagerView->showProperties( curveManager.get() );
m_summaryCurveManagerView->installEventFilter( curveManager.get() );
m_summaryCurveManager = std::move( curveManager );
auto plotManager = std::make_unique<RimSummaryPlotManager>();
m_summaryPlotManagerView->showProperties( plotManager.get() );
m_summaryPlotManagerView->installEventFilter( plotManager.get() );
m_summaryPlotManager = std::move( plotManager );
dockWidget->setWidget( m_summaryCurveManagerView );
dockWidget->setWidget( m_summaryPlotManagerView );
addDockWidget( Qt::BottomDockWidgetArea, dockWidget );
dockWidget->hide();
}
@ -751,6 +751,24 @@ RiuMessagePanel* RiuPlotMainWindow::messagePanel()
return m_messagePanel;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPlotMainWindow::showAndSetKeyboardFocusToSummaryPlotManager()
{
auto dockWidget = RiuDockWidgetTools::findDockWidget( this, RiuDockWidgetTools::summaryPlotManagerName() );
if ( dockWidget )
{
dockWidget->setVisible( true );
auto sumPlotManager = dynamic_cast<RimSummaryPlotManager*>( m_summaryPlotManager.get() );
if ( sumPlotManager )
{
sumPlotManager->setFocusToFilterText();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -94,6 +94,8 @@ public:
RiuMessagePanel* messagePanel();
void showAndSetKeyboardFocusToSummaryPlotManager();
protected:
void closeEvent( QCloseEvent* event ) override;
void keyPressEvent( QKeyEvent* ) override;
@ -137,11 +139,11 @@ private:
std::unique_ptr<caf::PdmUiDragDropInterface> m_dragDropInterface;
caf::PdmUiPropertyView* m_pdmUiPropertyView;
caf::PdmUiPropertyView* m_summaryCurveManagerView;
caf::PdmUiPropertyView* m_summaryPlotManagerView;
QPointer<RicSummaryPlotEditorDialog> m_summaryCurveCreatorDialog;
QPointer<RicSummaryCurveCalculatorDialog> m_summaryCurveCalculatorDialog;
std::unique_ptr<caf::PdmObject> m_summaryCurveManager;
std::unique_ptr<caf::PdmObject> m_summaryPlotManager;
std::vector<QWidget*> m_temporaryWidgets;
};

View File

@ -494,6 +494,9 @@ QWidget* PdmUiComboBoxEditor::createEditorWidget( QWidget* parent )
connect( m_comboBox, SIGNAL( activated( int ) ), this, SLOT( slotIndexActivated( int ) ) );
// Forward focus event to combo box editor
m_placeholder->setFocusProxy( m_comboBox );
return m_placeholder;
}