Merge pull request #4647 from OPM/feature-#4583-summary-without-rft

Feature #4583 summary without rft
This commit is contained in:
Magne Sjaastad 2019-08-28 12:46:03 +02:00 committed by GitHub
commit 072c71d8c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1166 additions and 173 deletions

View File

@ -289,7 +289,7 @@ bool RiaApplication::openFile(const QString& fileName)
}
else if (fileType & RiaDefines::ANY_ECLIPSE_FILE)
{
loadingSucceded = RicImportGeneralDataFeature::openEclipseFilesFromFileNames(QStringList{fileName});
loadingSucceded = RicImportGeneralDataFeature::openEclipseFilesFromFileNames(QStringList{fileName}, true);
lastUsedDialogTag = RiaDefines::defaultDirectoryLabel(fileType);
}

View File

@ -259,7 +259,7 @@ RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments(cvf::Pr
{
QStringList fileNames = RicImportGeneralDataFeature::fileNamesFromCaseNames(cvfqt::Utils::toQStringList(o.values()));
RicImportGeneralDataFeature::OpenCaseResults results =
RicImportGeneralDataFeature::openEclipseFilesFromFileNames(fileNames);
RicImportGeneralDataFeature::openEclipseFilesFromFileNames(fileNames, true);
}
if (cvf::Option o = progOpt->option("commandFile"))

View File

@ -133,6 +133,7 @@
#ifdef USE_UNIT_TESTS
#include "gtest/gtest.h"
#endif // USE_UNIT_TESTS
#include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h"
namespace caf
{
@ -657,6 +658,11 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra
}
}
if (cvf::Option o = progOpt->option("summaryplot"))
{
RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine( cvfqt::Utils::toQStringList(o.values()));
}
QString projectFileName;
if (progOpt->hasOption("last"))
@ -777,7 +783,7 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra
QStringList fileNames = RicImportGeneralDataFeature::fileNamesFromCaseNames(cvfqt::Utils::toQStringList(o.values()));
RicImportGeneralDataFeature::OpenCaseResults results =
RicImportGeneralDataFeature::openEclipseFilesFromFileNames(fileNames);
RicImportGeneralDataFeature::openEclipseFilesFromFileNames(fileNames, true);
if (results && !results.eclipseSummaryFiles.empty())
{
getOrCreateAndShowMainPlotWindow();

View File

@ -72,6 +72,13 @@ bool RiaArgumentParser::parseArguments(cvf::ProgramOptions* progOpt)
progOpt->registerOption("server", "[<portnumber>]", "Launch as a GRPC server. Default port is 50051", cvf::ProgramOptions::SINGLE_VALUE);
progOpt->registerOption("startdir", "<folder>", "Set startup directory.\n", cvf::ProgramOptions::SINGLE_VALUE);
progOpt->registerOption("summaryplot",
"[<plotOptions>] <eclipsesummaryvectors> [<eclipsedatafiles>]",
"Creates a summary plot using all the <eclipsedatafiles>,"
"and all the summary vectors defined in <eclipsesummaryvectors>."
"Use --summaryplot -help to show a more detailed help text.\n",
cvf::ProgramOptions::OPTIONAL_MULTI_VALUE);
progOpt->registerOption("commandFile", "<commandfile>", "Execute the command file.", cvf::ProgramOptions::SINGLE_VALUE);
progOpt->registerOption("commandFileReplaceCases",
"[<caseId>] <caseListFile>",

View File

@ -42,7 +42,8 @@ CAF_CMD_SOURCE_INIT(RicImportGeneralDataFeature, "RicImportGeneralDataFeature");
///
//--------------------------------------------------------------------------------------------------
RicImportGeneralDataFeature::OpenCaseResults
RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringList& fileNames)
RicImportGeneralDataFeature::openEclipseFilesFromFileNames(const QStringList& fileNames,
bool doCreateDefaultPlot)
{
CVF_ASSERT(!fileNames.empty());
@ -89,7 +90,7 @@ RicImportGeneralDataFeature::OpenCaseResults
}
if (!eclipseSummaryFiles.empty())
{
if (!openSummaryCaseFromFileNames(eclipseSummaryFiles))
if (!openSummaryCaseFromFileNames(eclipseSummaryFiles, doCreateDefaultPlot))
{
return OpenCaseResults();
}
@ -200,7 +201,7 @@ void RicImportGeneralDataFeature::openFileDialog(ImportFileType fileTypes)
RiaApplication::instance()->setLastUsedDialogDirectory(defaultDirectoryLabel(ANY_ECLIPSE_FILE), fileNames.front());
}
if (!openEclipseFilesFromFileNames(fileNames))
if (!openEclipseFilesFromFileNames(fileNames, true))
{
RiaLogging::error(QString("Failed to open file names: %1").arg(fileNames.join(", ")));
}
@ -240,10 +241,11 @@ bool RicImportGeneralDataFeature::openInputEclipseCaseFromFileNames(const QStrin
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicImportGeneralDataFeature::openSummaryCaseFromFileNames(const QStringList& fileNames)
bool RicImportGeneralDataFeature::openSummaryCaseFromFileNames(const QStringList& fileNames,
bool doCreateDefaultPlot)
{
std::vector<RimSummaryCase*> newCases;
if (RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(fileNames, &newCases))
if (RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(fileNames, doCreateDefaultPlot, &newCases))
{
RicImportSummaryCasesFeature::addCasesToGroupIfRelevant(newCases);
for (const RimSummaryCase* newCase : newCases)

View File

@ -46,7 +46,8 @@ public:
}
};
static OpenCaseResults openEclipseFilesFromFileNames(const QStringList& fileNames);
static OpenCaseResults openEclipseFilesFromFileNames(const QStringList& fileNames,
bool doCreateDefaultPlot);
static QStringList fileNamesFromCaseNames(const QStringList& caseNames);
protected:
@ -60,6 +61,7 @@ protected:
static bool openEclipseCaseFromFileNames(const QStringList& fileNames);
static bool openInputEclipseCaseFromFileNames(const QStringList& fileNames);
static bool openSummaryCaseFromFileNames(const QStringList& fileNames);
static bool openSummaryCaseFromFileNames(const QStringList& fileNames,
bool doCreateDefaultPlot = true);
};

View File

@ -122,6 +122,7 @@ void RicImportSummaryCasesFeature::setupActionLook(QAction* actionToSetup)
///
//--------------------------------------------------------------------------------------------------
bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(const QStringList& fileNames,
bool doCreateDefaultPlot,
std::vector<RimSummaryCase*>* newCases)
{
RiaGuiApplication* app = RiaGuiApplication::instance();
@ -131,7 +132,7 @@ bool RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(const QStri
if (createSummaryCasesFromFiles(fileNames, cases))
{
addSummaryCases(*cases);
if (!cases->empty())
if (!cases->empty() && doCreateDefaultPlot)
{
RicSummaryPlotFeatureImpl::createDefaultSummaryPlot(cases->back());
}

View File

@ -38,7 +38,9 @@ class RicImportSummaryCasesFeature : public caf::CmdFeature
public:
RicImportSummaryCasesFeature() { }
static bool createAndAddSummaryCasesFromFiles(const QStringList& fileName, std::vector<RimSummaryCase*>* newCases = nullptr);
static bool createAndAddSummaryCasesFromFiles(const QStringList& fileName,
bool doCreateDefaultPlot,
std::vector<RimSummaryCase*>* newCases = nullptr);
static bool createSummaryCasesFromFiles(const QStringList& fileName, std::vector<RimSummaryCase*>* newCases, bool ensembleOrGroup = false);
static void addSummaryCases(const std::vector<RimSummaryCase*> cases);
static void addCasesToGroupIfRelevant(const std::vector<RimSummaryCase*> cases);

View File

@ -23,14 +23,39 @@
#include "RimSummaryPlotCollection.h"
#include "RimProject.h"
#include "RimMainPlotCollection.h"
#include "RimSummaryCase.h"
#include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuMainWindow.h"
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RiaEclipseFileNameTools.h"
#include "RiaDefines.h"
#include "RifSummaryReaderInterface.h"
#include "RimSummaryCase.h"
#include "RicImportGeneralDataFeature.h"
#include "RicCreateSummaryCaseCollectionFeature.h"
#include "RicImportSummaryCasesFeature.h"
#include <QStringList>
#include <QFileInfo>
#include <QRegularExpression>
#include "RiaImportEclipseCaseTools.h"
#include "RimEclipseCase.h"
#include "RimGridTimeHistoryCurve.h"
#include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h"
#include "RimEclipseResultCase.h"
#include "RimOilField.h"
#include "RimEclipseCaseCollection.h"
#include "RigEclipseResultAddress.h"
#include "RigEclipseCaseData.h"
#include "RigCaseCellResultsData.h"
//--------------------------------------------------------------------------------------------------
///
@ -91,33 +116,7 @@ std::vector<RimSummaryCurve*> RicSummaryPlotFeatureImpl::addDefaultCurvesToPlot(
QString curvesTextFilter = RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter;
QStringList curveFilters = curvesTextFilter.split(";", QString::SkipEmptyParts);
const std::set<RifEclipseSummaryAddress>& addrs = summaryCase->summaryReader()->allResultAddresses();
std::vector<RifEclipseSummaryAddress> curveAddressesToUse;
for (const auto & addr : addrs)
{
for (const QString& filter: curveFilters)
{
if ( addr.isUiTextMatchingFilterText(filter) )
{
curveAddressesToUse.push_back(addr);
}
}
}
for (const auto & addr : curveAddressesToUse)
{
RimSummaryCurve* newCurve = new RimSummaryCurve();
plot->addCurveNoUpdate(newCurve);
if (summaryCase)
{
newCurve->setSummaryCaseY(summaryCase);
}
newCurve->setSummaryAddressYAndApplyInterpolation(addr);
defaultCurves.push_back(newCurve);
}
return defaultCurves;
return addCurvesFromAddressFiltersToPlot(curveFilters, plot, summaryCase, false);
}
//--------------------------------------------------------------------------------------------------
@ -141,7 +140,7 @@ void RicSummaryPlotFeatureImpl::createDefaultSummaryPlot( RimSummaryCase* summar
{
RimSummaryPlotCollection* summaryPlotCollection = RiaApplication::instance()->project()->mainPlotCollection->summaryPlotCollection();
if (summaryPlotCollection && summaryCase)
if (summaryPlotCollection && summaryCase && !RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter().isEmpty())
{
auto plot = summaryPlotCollection->createSummaryPlotWithAutoTitle();
@ -160,4 +159,652 @@ void RicSummaryPlotFeatureImpl::createDefaultSummaryPlot( RimSummaryCase* summar
}
}
RimSummaryCurve* createHistoryCurve(const RifEclipseSummaryAddress& addr, RimSummaryCase* summaryCasesToUse)
{
RifEclipseSummaryAddress historyAddr = addr;
historyAddr.setQuantityName(historyAddr.quantityName() + "H");
if ( summaryCasesToUse->summaryReader()->allResultAddresses().count(historyAddr) )
{
RimSummaryCurve* historyCurve = new RimSummaryCurve();
historyCurve->setSummaryCaseY(summaryCasesToUse);
historyCurve->setSummaryAddressYAndApplyInterpolation(historyAddr);
return historyCurve;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RigGridCellResultAddress
{
public:
RigGridCellResultAddress()
: gridIndex(-1)
, i(-1)
, j(-1)
, k(-1)
{}
RigGridCellResultAddress(size_t gridIndex,
size_t i,
size_t j,
size_t k,
const RigEclipseResultAddress & eclipseResultAddress)
: gridIndex(gridIndex)
, i(i)
, j(j)
, k(k)
, eclipseResultAddress(eclipseResultAddress)
{}
// Using zero based ijk
size_t gridIndex;
size_t i;
size_t j;
size_t k;
RigEclipseResultAddress eclipseResultAddress;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigGridCellResultAddress> createGridCellAddressesFromFilter(const QString& text)
{
std::vector<RigGridCellResultAddress> addresses;
QStringList addressParts = text.split(":");
if (addressParts.size() > 1)
{
QString resultVarName = addressParts[0];
size_t gridIdx = 0;
if (addressParts.size() > 2)
{
gridIdx = addressParts[1].toULong();
}
QString ijkText = addressParts.back();
QStringList ijkTextParts = ijkText.split(",");
if (ijkTextParts.size() == 3)
{
bool isOk = true;
bool allOk = true;
size_t i = ijkTextParts[0].toULong(&isOk);
allOk &= isOk;
size_t j = ijkTextParts[1].toULong(&isOk);
allOk &= isOk;
size_t k = ijkTextParts[2].toULong(&isOk);
allOk &= isOk;
if (allOk)
{
addresses.emplace_back(RigGridCellResultAddress(gridIdx, i-1, j-1, k-1, RigEclipseResultAddress(resultVarName )));
}
}
}
return addresses;
}
std::vector<RimEclipseCase*> openEclipseCasesForCellPlotting(QStringList gridFileNames)
{
std::vector<RimEclipseCase*> openedCases;
RiaApplication* app = RiaApplication::instance();
RimProject* project = app->project();
RimEclipseCaseCollection* analysisModels = project->activeOilField()->analysisModels();
for ( const QString& fileName: gridFileNames )
{
QFileInfo gridFileInfo(fileName);
if (!gridFileInfo.exists()) continue;
QString caseName = gridFileInfo.completeBaseName();
RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase();
rimResultReservoir->setCaseInfo(caseName, fileName);
analysisModels->cases.push_back(rimResultReservoir);
if ( !rimResultReservoir->openReserviorCase() )
{
analysisModels->removeCaseFromAllGroups(rimResultReservoir);
delete rimResultReservoir;
continue;
}
else
{
openedCases.push_back(rimResultReservoir);
}
}
analysisModels->updateConnectedEditors();
return openedCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine(const QStringList & arguments)
{
// Split arguments in options, vectors and filenames
QStringList options;
QStringList allCurveAddressFilters;
QStringList summaryFileNames;
QStringList gridFileNames;
QString ensembleColoringParameter;
std::set<QString> validOptions = {"-help", "-h", "-nl", "-s", "-n", "-e", "-c", "-cl"};
for (int optionIdx = 0; optionIdx < arguments.size(); ++optionIdx)
{
if (arguments[optionIdx].startsWith("-"))
{
if (arguments[optionIdx] == "-help")
{
RiaApplication::instance()->showFormattedTextInMessageBoxOrConsole(
"The --summaryplot option has the following syntax:\n"
"\n"
"[<plotOptions>] <eclipsesummaryvectorfilters> [<eclipsedatafiles>]\n"
"\n"
"It Creates one summary plot for each of the the summary vectors matched by the <eclipsesummaryvectorfilters> using all the <eclipsedatafiles> in each plot.\n"
"The <eclipsesummaryvectorfilters> has the syntax <vectorname>[:<item>[:<subitem>[:i,j,k]]] and can be repeated.\n"
"Wildcards can also be used, eg. \"WOPT:*\" to select the total oil production from all the wells.\n"
"The <eclipsedatafiles> can be written with or without extension. Only the corresponding SMSPEC file will be opened for each case.\n"
"\n"
"The summary plot options are: \n"
" -help\t Show this help text and ignore the rest of the options.\n"
" -h\t Include history vectors. Will be read from the summary file if the vectors exist.\n"
" \t Only history vectors from the first summary case in the project will be included.\n"
" -nl\t Omit legend in plot.\n"
" -s\t Create only one plot including all the defined vectors and cases.\n"
" -n\t Scale all curves into the range 0.0-1.0. Useful when using -s.\n"
" -e\t Import all the cases as an ensemble, and create ensemble curves sets instead of single curves.\n"
" -c <parametername>\t Same as -e, but colors the curves by the ensemble parameter <parametername> . \n"
" -cl <parametername>\t Same as -c, but uses logarithmic legend.\n"
);
return;
}
if ( validOptions.count(arguments[optionIdx]) )
{
options.push_back(arguments[optionIdx]);
if ( arguments[optionIdx] == "-c" || arguments[optionIdx] == "-cl" )
{
optionIdx++;
if ( optionIdx < arguments.size() ) ensembleColoringParameter = arguments[optionIdx];
}
}
else
{
RiaLogging::error("The summaryplot option: \"" + arguments[optionIdx] + "\" is unknown.");
}
}
else
{
RiaEclipseFileNameTools nameTool(arguments[optionIdx]);
QString smSpecFileName = nameTool.findRelatedSummarySpecFile();
QString gridFileName = nameTool.findRelatedGridFile();
if (smSpecFileName != "" || gridFileName != "")
{
if (smSpecFileName != "") summaryFileNames.push_back(smSpecFileName);
if (gridFileName != "") gridFileNames.push_back(gridFileName);
}
else
{
allCurveAddressFilters.push_back(arguments[optionIdx]);
}
}
}
if ( allCurveAddressFilters.empty() )
{
RiaLogging::error("Needs at least one vector to create a plot.");
}
bool hideLegend = options.contains("-nl");
bool addHistoryCurves = options.contains("-h");
bool isNormalizedY = options.contains("-n");
bool isSinglePlot = options.contains("-s");
enum EnsembleColoringType { SINGLE_COLOR, PARAMETER, LOG_PARAMETER, NONE };
EnsembleColoringType ensembleColoringStyle = NONE;
{
int e_pos = options.lastIndexOf("-e");
int c_pos = options.lastIndexOf("-c");
int cl_pos = options.lastIndexOf("-cl");
int lastEnsembleOptionPos = -1;
if ( e_pos > lastEnsembleOptionPos ) { lastEnsembleOptionPos = e_pos ; ensembleColoringStyle = SINGLE_COLOR; }
if ( c_pos > lastEnsembleOptionPos ) { lastEnsembleOptionPos = c_pos ; ensembleColoringStyle = PARAMETER; }
if ( cl_pos > lastEnsembleOptionPos ) { lastEnsembleOptionPos = cl_pos ; ensembleColoringStyle = LOG_PARAMETER; }
}
bool isEnsembleMode = ensembleColoringStyle != NONE;
std::vector<RimSummaryCase*> summaryCasesToUse;
if ( summaryFileNames.size() )
{
RicImportSummaryCasesFeature::createSummaryCasesFromFiles(summaryFileNames, &summaryCasesToUse, isEnsembleMode);
RicImportSummaryCasesFeature::addSummaryCases(summaryCasesToUse);
RiaApplication::instance()->setLastUsedDialogDirectory(RiaDefines::defaultDirectoryLabel(RiaDefines::ECLIPSE_SUMMARY_FILE),
QFileInfo(summaryFileNames[0]).absolutePath());
}
// Sort in summary and grid curve addresses
QStringList gridResultAddressFilters;
QStringList summaryAddressFilters;
if ( summaryCasesToUse.size() )
{
const std::set<RifEclipseSummaryAddress>& addrs = summaryCasesToUse[0]->summaryReader()->allResultAddresses();
std::vector<bool> usedFilters;
std::set<RifEclipseSummaryAddress> setToInsertFilteredAddressesIn;
filteredSummaryAdressesFromCase(allCurveAddressFilters, addrs, &setToInsertFilteredAddressesIn, &usedFilters);
QRegularExpression gridAddressPattern("^[A-Z]+:[0-9]+,[0-9]+,[0-9]+$");
for ( int filterIdx = 0; filterIdx < allCurveAddressFilters.size(); ++filterIdx )
{
const QString& address = allCurveAddressFilters[filterIdx];
if ( usedFilters[filterIdx] )
{
summaryAddressFilters.push_back(address);
}
else
{
if ( gridAddressPattern.match(address).hasMatch() )
{
gridResultAddressFilters.push_back(address);
}
else
{
RiaLogging::warning("No summary or restart vectors matched \"" + address + "\"");
}
}
}
}
if ( summaryCasesToUse.size() )
{
if ( summaryAddressFilters.size() )
{
RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection();
RimSummaryPlot* lastPlotCreated = nullptr;
RimSummaryCaseCollection* ensemble = nullptr;
if ( isEnsembleMode ) ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases(summaryCasesToUse, "Ensemble", true);
if ( isSinglePlot )
{
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
if ( isEnsembleMode )
{
std::set<RifEclipseSummaryAddress> filteredAdressesFromCases = applySummaryAddressFiltersToCases(summaryCasesToUse,
summaryAddressFilters);
for ( const auto & addr : filteredAdressesFromCases )
{
RimEnsembleCurveSet* curveSet = new RimEnsembleCurveSet();
curveSet->setSummaryCaseCollection(ensemble);
curveSet->setSummaryAddress(addr);
if ( ensembleColoringStyle == PARAMETER || ensembleColoringStyle == LOG_PARAMETER )
{
curveSet->setColorMode(RimEnsembleCurveSet::BY_ENSEMBLE_PARAM);
curveSet->setEnsembleParameter(ensembleColoringParameter);
if ( ensembleColoringStyle == LOG_PARAMETER )
{
curveSet->legendConfig()->setMappingMode(RimRegularLegendConfig::LOG10_CONTINUOUS);
}
}
newPlot->ensembleCurveSetCollection()->addCurveSet(curveSet);
if ( addHistoryCurves )
{
RimSummaryCurve* historyCurve = createHistoryCurve(addr, summaryCasesToUse[0]);
if ( historyCurve ) newPlot->addCurveNoUpdate(historyCurve);
}
}
}
else
{
for ( RimSummaryCase* sumCase : summaryCasesToUse )
{
RicSummaryPlotFeatureImpl::addCurvesFromAddressFiltersToPlot(summaryAddressFilters, newPlot, sumCase, addHistoryCurves);
addHistoryCurves = false;
}
}
lastPlotCreated = newPlot;
newPlot->showLegend(!hideLegend);
newPlot->setNormalizationEnabled(isNormalizedY);
newPlot->applyDefaultCurveAppearances();
newPlot->loadDataAndUpdate();
sumPlotColl->updateConnectedEditors();
RiuPlotMainWindowTools::setExpanded(newPlot);
RiuPlotMainWindowTools::selectAsCurrentItem(newPlot);
}
else // Multiplot, one for each separate summary address
{
std::set<RifEclipseSummaryAddress> filteredAdressesFromCases = applySummaryAddressFiltersToCases(summaryCasesToUse,
summaryAddressFilters);
for ( const auto & addr : filteredAdressesFromCases )
{
std::vector<RimSummaryCurve*> createdCurves;
std::vector<RimEnsembleCurveSet*> createdEnsembleCurveSets;
if ( isEnsembleMode )
{
RimEnsembleCurveSet* curveSet = new RimEnsembleCurveSet();
curveSet->setSummaryCaseCollection(ensemble);
curveSet->setSummaryAddress(addr);
if ( ensembleColoringStyle == PARAMETER || ensembleColoringStyle == LOG_PARAMETER )
{
curveSet->setColorMode(RimEnsembleCurveSet::BY_ENSEMBLE_PARAM);
curveSet->setEnsembleParameter(ensembleColoringParameter);
if ( ensembleColoringStyle == LOG_PARAMETER )
{
curveSet->legendConfig()->setMappingMode(RimRegularLegendConfig::LOG10_CONTINUOUS);
}
}
createdEnsembleCurveSets.push_back(curveSet);
}
else
{
for ( RimSummaryCase* sumCase : summaryCasesToUse )
{
const std::set<RifEclipseSummaryAddress>& allAddrsInCase = sumCase->summaryReader()->allResultAddresses();
if ( allAddrsInCase.count(addr) )
{
RimSummaryCurve* newCurve = new RimSummaryCurve();
newCurve->setSummaryCaseY(sumCase);
newCurve->setSummaryAddressYAndApplyInterpolation(addr);
createdCurves.push_back(newCurve);
}
}
}
if ( addHistoryCurves )
{
RimSummaryCurve* historyCurve = createHistoryCurve(addr, summaryCasesToUse[0]);
if ( historyCurve ) createdCurves.push_back(historyCurve);
}
if ( createdCurves.size() || createdEnsembleCurveSets.size() )
{
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
for ( auto curve : createdCurves )
{
newPlot->addCurveNoUpdate(curve);
}
for ( auto curveSet: createdEnsembleCurveSets )
{
newPlot->ensembleCurveSetCollection()->addCurveSet(curveSet);
}
newPlot->showLegend(!hideLegend);
newPlot->setNormalizationEnabled(isNormalizedY);
newPlot->applyDefaultCurveAppearances();
newPlot->loadDataAndUpdate();
lastPlotCreated = newPlot;
}
}
}
sumPlotColl->updateConnectedEditors();
if ( lastPlotCreated )
{
RiuPlotMainWindowTools::setExpanded(lastPlotCreated);
RiuPlotMainWindowTools::selectAsCurrentItem(lastPlotCreated);
RiuPlotMainWindowTools::showPlotMainWindow();
RiuMainWindow::instance()->close();
}
}
// Grid Cell Result vectors
if ( gridResultAddressFilters.size() )
{
// Todo: Use identical grid case import if -e -c or -cl
std::vector<RimEclipseCase*> gridCasesToPlotFrom = openEclipseCasesForCellPlotting(gridFileNames);
RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection();
if ( isSinglePlot )
{
std::vector<RimGridTimeHistoryCurve*> createdCurves;
int curveColorIndex = 0;
for ( const QString& gridAddressFilter : gridResultAddressFilters )
{
std::vector<RigGridCellResultAddress> cellResAddrs = createGridCellAddressesFromFilter(gridAddressFilter);
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
{
for ( RimEclipseCase* eclCase: gridCasesToPlotFrom )
{
if (!(eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL) &&
eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->resultInfo(cellResAddr.eclipseResultAddress)) )
{
RiaLogging::warning("Could not find a restart result property with name: \"" + cellResAddr.eclipseResultAddress.m_resultName + "\"");
continue;
}
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
newCurve->setFromEclipseCellAndResult(eclCase,
cellResAddr.gridIndex,
cellResAddr.i,
cellResAddr.j,
cellResAddr.k,
cellResAddr.eclipseResultAddress);
newCurve->setLineThickness(2);
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable(curveColorIndex);
newCurve->setColor(curveColor);
if (!isEnsembleMode) ++curveColorIndex;
createdCurves.push_back(newCurve);
}
if (isEnsembleMode) ++curveColorIndex;
}
}
if ( createdCurves.size() )
{
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
for ( auto curve: createdCurves )
{
newPlot->addGridTimeHistoryCurve(curve);
}
newPlot->showLegend(!hideLegend);
newPlot->setNormalizationEnabled(isNormalizedY);
newPlot->loadDataAndUpdate();
}
}
else // Multiplot
{
int curveColorIndex = 0;
for ( const QString& gridAddressFilter : gridResultAddressFilters )
{
std::vector<RigGridCellResultAddress> cellResAddrs = createGridCellAddressesFromFilter(gridAddressFilter);
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
{
std::vector<RimGridTimeHistoryCurve*> createdCurves;
for ( RimEclipseCase* eclCase: gridCasesToPlotFrom )
{
if (!(eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL) &&
eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->resultInfo(cellResAddr.eclipseResultAddress)) )
{
RiaLogging::warning("Could not find a restart result property with name: \"" + cellResAddr.eclipseResultAddress.m_resultName + "\"");
continue;
}
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
newCurve->setFromEclipseCellAndResult(eclCase,
cellResAddr.gridIndex,
cellResAddr.i,
cellResAddr.j,
cellResAddr.k,
cellResAddr.eclipseResultAddress);
newCurve->setLineThickness(2);
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable(curveColorIndex);
newCurve->setColor(curveColor);
if (!isEnsembleMode) ++curveColorIndex;
createdCurves.push_back(newCurve);
}
if (isEnsembleMode) ++curveColorIndex;
if ( createdCurves.size() )
{
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
for (auto newCurve : createdCurves)
{
newPlot->addGridTimeHistoryCurve(newCurve);
}
newPlot->showLegend(!hideLegend);
newPlot->setNormalizationEnabled(isNormalizedY);
newPlot->loadDataAndUpdate();
}
}
}
}
sumPlotColl->updateConnectedEditors();
RiuPlotMainWindowTools::showPlotMainWindow();
RiuMainWindow::instance()->close();
}
}
else
{
RiaLogging::error("Needs at least one summary case to create a plot.");
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RicSummaryPlotFeatureImpl::applySummaryAddressFiltersToCases(const std::vector<RimSummaryCase *>& summaryCasesToUse,
const QStringList& summaryAddressFilters)
{
std::set<RifEclipseSummaryAddress> filteredAdressesFromCases;
for ( RimSummaryCase* sumCase : summaryCasesToUse )
{
const std::set<RifEclipseSummaryAddress>& addrs = sumCase->summaryReader()->allResultAddresses();
std::vector<bool> usedFilters;
filteredSummaryAdressesFromCase(summaryAddressFilters, addrs, &filteredAdressesFromCases, &usedFilters);
for ( int cfIdx = 0 ; cfIdx < usedFilters.size() ; ++cfIdx )
{
if ( !usedFilters[cfIdx] )
{
RiaLogging::warning("Vector filter \"" + summaryAddressFilters[cfIdx] + "\" did not match anything in case: \"" + sumCase->caseName() + "\"");
}
}
}
return filteredAdressesFromCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCurve*> RicSummaryPlotFeatureImpl::addCurvesFromAddressFiltersToPlot(const QStringList& curveFilters,
RimSummaryPlot* plot,
RimSummaryCase* summaryCase,
bool addHistoryCurves)
{
std::vector<RimSummaryCurve*> createdCurves;
std::set<RifEclipseSummaryAddress> curveAddressesToUse;
const std::set<RifEclipseSummaryAddress>& addrs = summaryCase->summaryReader()->allResultAddresses();
std::vector<bool> usedFilters;
filteredSummaryAdressesFromCase(curveFilters, addrs, &curveAddressesToUse, &usedFilters);
for (int cfIdx = 0 ; cfIdx < usedFilters.size() ; ++cfIdx)
{
if (!usedFilters[cfIdx])
{
RiaLogging::warning("Vector filter \"" + curveFilters[cfIdx] + "\" did not match anything in case: \"" + summaryCase->caseName() + "\"");
}
}
if (addHistoryCurves)
{
std::vector<RifEclipseSummaryAddress> historyAddressesToUse;
for (RifEclipseSummaryAddress historyAddr : curveAddressesToUse)
{
historyAddr.setQuantityName(historyAddr.quantityName() + "H");
if (addrs.count(historyAddr))
{
historyAddressesToUse.push_back(historyAddr);
}
}
curveAddressesToUse.insert( historyAddressesToUse.begin(), historyAddressesToUse.end() );
}
for (const auto & addr : curveAddressesToUse)
{
RimSummaryCurve* newCurve = new RimSummaryCurve();
plot->addCurveNoUpdate(newCurve);
if (summaryCase)
{
newCurve->setSummaryCaseY(summaryCase);
}
newCurve->setSummaryAddressYAndApplyInterpolation(addr);
createdCurves.push_back(newCurve);
}
return createdCurves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicSummaryPlotFeatureImpl::filteredSummaryAdressesFromCase(const QStringList& curveFilters,
const std::set<RifEclipseSummaryAddress>& allAddressesInCase,
std::set<RifEclipseSummaryAddress>* setToInsertFilteredAddressesIn,
std::vector<bool>* usedFilters)
{
int curveFilterCount = curveFilters.size();
usedFilters->clear();
usedFilters->resize(curveFilterCount, false);
for (const auto & addr : allAddressesInCase)
{
for (int cfIdx = 0 ; cfIdx < curveFilterCount ; ++cfIdx)
{
if ( addr.isUiTextMatchingFilterText( curveFilters[cfIdx]) )
{
setToInsertFilteredAddressesIn->insert(addr);
(*usedFilters)[cfIdx] = true;
}
}
}
}

View File

@ -23,6 +23,11 @@ class RimSummaryCase;
class RimSummaryPlotCollection;
#include <vector>
#include <set>
#include "RifEclipseSummaryAddress.h"
class QStringList;
class RicSummaryPlotFeatureImpl
{
@ -31,7 +36,20 @@ public:
static std::vector<RimSummaryCurve*> addDefaultCurvesToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase);
static void ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase);
static void createDefaultSummaryPlot(RimSummaryCase* summaryCase);
static void createSummaryPlotsFromArgumentLine(const QStringList & arguments);
private:
static std::vector<RimSummaryCurve*> addCurvesFromAddressFiltersToPlot(const QStringList& curveFilters,
RimSummaryPlot* plot,
RimSummaryCase* summaryCase,
bool addHistoryCurves);
static std::set<RifEclipseSummaryAddress> applySummaryAddressFiltersToCases(const std::vector<RimSummaryCase *>& summaryCasesToUse,
const QStringList& summaryAddressFilters);
static void filteredSummaryAdressesFromCase(const QStringList& curveFilters,
const std::set<RifEclipseSummaryAddress>& allAddressesInCase,
std::set<RifEclipseSummaryAddress>* setToInsertFilteredAddressesIn,
std::vector<bool>* usedFilters);
};

View File

@ -19,6 +19,8 @@
#include "RimEclipseGeometrySelectionItem.h"
#include "RigTimeHistoryResultAccessor.h"
#include "RigEclipseCaseData.h"
#include "RigGridBase.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
@ -61,6 +63,24 @@ void RimEclipseGeometrySelectionItem::setFromSelectionItem(const RiuEclipseSelec
m_eclipseCase = selectionItem->m_view->eclipseCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseGeometrySelectionItem::setFromCaseGridAndIJK(RimEclipseCase* eclipseCase,
size_t gridIndex,
size_t i,
size_t j,
size_t k)
{
m_eclipseCase = eclipseCase;
m_gridIndex = gridIndex;
size_t lgrCellIndex = eclipseCase->eclipseCaseData()->grid(gridIndex)->cellIndexFromIJK(i, j, k);
size_t reservoirCellIndex = eclipseCase->eclipseCaseData()->grid(gridIndex)->reservoirCellIndex(lgrCellIndex);
m_cellIndex = reservoirCellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -39,7 +39,11 @@ public:
~RimEclipseGeometrySelectionItem() override;
void setFromSelectionItem(const RiuEclipseSelectionItem* selectionItem);
void setFromCaseGridAndIJK(RimEclipseCase* eclipseCase,
size_t gridIndex,
size_t i,
size_t j,
size_t k);
QString geometrySelectionText() const override;
RimEclipseCase* eclipseCase() const;

View File

@ -31,6 +31,7 @@
#include "RigEclipseCaseData.h"
#include "RigFlowDiagResultAddress.h"
#include "RigFlowDiagResults.h"
#include "RigEclipseResultInfo.h"
#include "Rim3dView.h"
#include "Rim3dWellLogCurve.h"
@ -763,21 +764,32 @@ RigEclipseResultAddress RimEclipseResultDefinition::eclipseResultAddress() const
//--------------------------------------------------------------------------------------------------
void RimEclipseResultDefinition::setFromEclipseResultAddress(const RigEclipseResultAddress& address)
{
m_resultType = address.m_resultCatType;
m_resultVariable = address.m_resultName;
m_timeLapseBaseTimestep = address.m_timeLapseBaseFrameIdx;
RigEclipseResultAddress canonizedAddress = address;
if (address.hasDifferenceCase())
const RigCaseCellResultsData* gridCellResults = this->currentGridCellResults();
if (gridCellResults)
{
auto rinfo = gridCellResults->resultInfo(address);
if (rinfo) canonizedAddress = rinfo->eclipseResultAddress();
}
m_resultType = canonizedAddress.m_resultCatType;
m_resultVariable = canonizedAddress.m_resultName;
m_timeLapseBaseTimestep = canonizedAddress.m_timeLapseBaseFrameIdx;
if (canonizedAddress.hasDifferenceCase())
{
auto eclipseCases = RiaApplication::instance()->project()->eclipseCases();
for (RimEclipseCase* c : eclipseCases)
{
if (c && c->caseId() == address.m_differenceCaseId)
if (c && c->caseId() == canonizedAddress.m_differenceCaseId)
{
m_differenceCase = c;
}
}
}
this->updateUiFieldsFromActiveResult();
}
//--------------------------------------------------------------------------------------------------

View File

@ -135,6 +135,30 @@ void RimGridTimeHistoryCurve::setFromSelectionItem(const RiuSelectionItem* selec
updateResultDefinitionFromCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridTimeHistoryCurve::setFromEclipseCellAndResult(RimEclipseCase* eclCase,
size_t gridIdx,
size_t i,
size_t j,
size_t k,
const RigEclipseResultAddress& resAddr)
{
delete m_geometrySelectionItem();
delete m_eclipseResultDefinition();
delete m_geoMechResultDefinition();
m_eclipseResultDefinition = new RimEclipseResultDefinition;
m_eclipseResultDefinition->setEclipseCase(eclCase);
m_eclipseResultDefinition->setFromEclipseResultAddress(resAddr);
RimEclipseGeometrySelectionItem* geomSelectionItem = new RimEclipseGeometrySelectionItem;
m_geometrySelectionItem = geomSelectionItem;
geomSelectionItem->setFromCaseGridAndIJK(eclCase, gridIdx, i, j, k);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -190,6 +214,22 @@ std::vector<double> RimGridTimeHistoryCurve::yValues() const
}
}
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfTypeAsserted(plot);
bool isNormalized = plot->isNormalizationEnabled();
if (isNormalized)
{
auto minMaxPair = std::minmax_element(values.begin(), values.end());
double min = *minMaxPair.first;
double max = *minMaxPair.second;
double range = max - min;
for (double & v: values)
{
v = (v - min)/range;
}
}
return values;
}

View File

@ -36,6 +36,7 @@ class RimGeoMechGeometrySelectionItem;
class RimGeometrySelectionItem;
class RiuFemTimeHistoryResultAccessor;
class RiuSelectionItem;
class RigEclipseResultAddress;
//==================================================================================================
///
@ -51,6 +52,12 @@ public:
~RimGridTimeHistoryCurve() override;
void setFromSelectionItem(const RiuSelectionItem* selectionItem);
void setFromEclipseCellAndResult(RimEclipseCase* eclCase,
size_t gridIdx,
size_t i,
size_t j,
size_t k,
const RigEclipseResultAddress& resAddr);
RiaDefines::PlotAxis yAxis() const;
void setYAxis(RiaDefines::PlotAxis plotAxis);

View File

@ -426,6 +426,22 @@ RimEnsembleCurveSet::ColorMode RimEnsembleCurveSet::colorMode() const
return m_colorMode();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveSet::setColorMode(ColorMode mode)
{
m_colorMode = mode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveSet::setEnsembleParameter(const QString& parameterName)
{
m_ensembleParameter = parameterName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -97,6 +97,8 @@ public:
RimEnsembleCurveFilterCollection* filterCollection() const;
ColorMode colorMode() const;
void setColorMode(ColorMode mode);
void setEnsembleParameter(const QString& parameterName);
void updateEnsembleLegendItem();
EnsembleParameter::Type currentEnsembleParameterType() const;
static QString ensembleParameterUiName(const NameParameterPair& paramPair);

View File

@ -56,6 +56,7 @@
#include "qwt_plot.h"
#include <QMessageBox>
#include "cafPdmUiLineEditor.h"
CAF_PDM_SOURCE_INIT(RimSummaryCurve, "SummaryCurve");
@ -73,31 +74,21 @@ RimSummaryCurve::RimSummaryCurve()
m_yValuesSummaryCase.uiCapability()->setUiTreeChildrenHidden(true);
m_yValuesSummaryCase.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_yValuesSelectedVariableDisplayField, "SelectedVariableDisplayVar", "Vector", "", "", "");
m_yValuesSelectedVariableDisplayField.xmlCapability()->disableIO();
m_yValuesSelectedVariableDisplayField.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitFieldNoDefault(&m_yValuesSummaryAddressUiField, "SelectedVariableDisplayVar", "Vector", "", "", "");
m_yValuesSummaryAddressUiField.xmlCapability()->disableIO();
m_yValuesSummaryAddressUiField.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_yValuesSummaryFilter, "VarListFilter", "Filter", "", "", "");
m_yValuesSummaryFilter.uiCapability()->setUiTreeChildrenHidden(true);
m_yValuesSummaryFilter.uiCapability()->setUiHidden(true);
m_yValuesSummaryFilter = new RimSummaryFilter;
CAF_PDM_InitFieldNoDefault(&m_yValuesUiFilterResultSelection, "FilterResultSelection", "Filter Result", "", "", "");
m_yValuesUiFilterResultSelection.xmlCapability()->disableIO();
m_yValuesUiFilterResultSelection.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
m_yValuesUiFilterResultSelection.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_yValuesUiFilterResultSelection.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_yValuesCurveVariable, "SummaryAddress", "Summary Address", "", "", "");
m_yValuesCurveVariable.uiCapability()->setUiHidden(true);
m_yValuesCurveVariable.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_yValuesSummaryAddress, "SummaryAddress", "Summary Address", "", "", "");
m_yValuesSummaryAddress.uiCapability()->setUiHidden(true);
m_yValuesSummaryAddress.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_yPushButtonSelectSummaryAddress, "SelectAddress", "", "", "", "");
caf::PdmUiPushButtonEditor::configureEditorForField(&m_yPushButtonSelectSummaryAddress);
m_yPushButtonSelectSummaryAddress.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_yPushButtonSelectSummaryAddress = false;
m_yValuesCurveVariable = new RimSummaryAddress;
m_yValuesSummaryAddress = new RimSummaryAddress;
// X Values
@ -106,31 +97,23 @@ RimSummaryCurve::RimSummaryCurve()
m_xValuesSummaryCase.uiCapability()->setUiTreeChildrenHidden(true);
m_xValuesSummaryCase.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_xValuesSelectedVariableDisplayField, "SelectedVariableDisplayVarX", "Vector", "", "", "");
m_xValuesSelectedVariableDisplayField.xmlCapability()->disableIO();
m_xValuesSelectedVariableDisplayField.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitFieldNoDefault(&m_xValuesSummaryAddressUiField, "SelectedVariableDisplayVarX", "Vector", "", "", "");
m_xValuesSummaryAddressUiField.xmlCapability()->disableIO();
m_xValuesSummaryAddressUiField.uiCapability()->setUiEditorTypeName(caf::PdmUiLineEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_xValuesSummaryFilter, "VarListFilterX", "Filter", "", "", "");
m_xValuesSummaryFilter.uiCapability()->setUiTreeChildrenHidden(true);
m_xValuesSummaryFilter.uiCapability()->setUiHidden(true);
m_xValuesSummaryFilter = new RimSummaryFilter;
CAF_PDM_InitFieldNoDefault(&m_xValuesUiFilterResultSelection, "FilterResultSelectionX", "Filter Result", "", "", "");
m_xValuesUiFilterResultSelection.xmlCapability()->disableIO();
m_xValuesUiFilterResultSelection.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
m_xValuesUiFilterResultSelection.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_xValuesUiFilterResultSelection.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_xValuesCurveVariable, "SummaryAddressX", "Summary Address", "", "", "");
m_xValuesCurveVariable.uiCapability()->setUiHidden(true);
m_xValuesCurveVariable.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_xValuesSummaryAddress, "SummaryAddressX", "Summary Address", "", "", "");
m_xValuesSummaryAddress.uiCapability()->setUiHidden(true);
m_xValuesSummaryAddress.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_xPushButtonSelectSummaryAddress, "SelectAddressX", "", "", "", "");
caf::PdmUiPushButtonEditor::configureEditorForField(&m_xPushButtonSelectSummaryAddress);
m_xPushButtonSelectSummaryAddress.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_xPushButtonSelectSummaryAddress = false;
m_xValuesCurveVariable = new RimSummaryAddress;
m_xValuesSummaryAddress = new RimSummaryAddress;
// Other members
@ -148,6 +131,19 @@ RimSummaryCurve::RimSummaryCurve()
m_symbolSkipPixelDistance = 10.0f;
m_curveThickness = 2;
CAF_PDM_InitFieldNoDefault(&m_yValuesSummaryFilter_OBSOLETE, "VarListFilter", "Filter", "", "", "");
m_yValuesSummaryFilter_OBSOLETE.uiCapability()->setUiTreeChildrenHidden(true);
m_yValuesSummaryFilter_OBSOLETE.uiCapability()->setUiHidden(true);
m_yValuesSummaryFilter_OBSOLETE.xmlCapability()->setIOWritable(false);
m_yValuesSummaryFilter_OBSOLETE = new RimSummaryFilter;
CAF_PDM_InitFieldNoDefault(&m_xValuesSummaryFilter_OBSOLETE, "VarListFilterX", "Filter", "", "", "");
m_xValuesSummaryFilter_OBSOLETE.uiCapability()->setUiTreeChildrenHidden(true);
m_xValuesSummaryFilter_OBSOLETE.uiCapability()->setUiHidden(true);
m_xValuesSummaryFilter_OBSOLETE.xmlCapability()->setIOWritable(false);
m_xValuesSummaryFilter_OBSOLETE = new RimSummaryFilter;
}
//--------------------------------------------------------------------------------------------------
@ -183,7 +179,7 @@ RimSummaryCase* RimSummaryCurve::summaryCaseY() const
//--------------------------------------------------------------------------------------------------
RifEclipseSummaryAddress RimSummaryCurve::summaryAddressX() const
{
return m_xValuesCurveVariable->address();
return m_xValuesSummaryAddress->address();
}
//--------------------------------------------------------------------------------------------------
@ -191,7 +187,7 @@ RifEclipseSummaryAddress RimSummaryCurve::summaryAddressX() const
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::setSummaryAddressX(const RifEclipseSummaryAddress& address)
{
m_xValuesCurveVariable->setAddress(address);
m_xValuesSummaryAddress->setAddress(address);
// TODO: Should interpolation be computed similar to RimSummaryCurve::setSummaryAddressY
}
@ -201,7 +197,7 @@ void RimSummaryCurve::setSummaryAddressX(const RifEclipseSummaryAddress& address
//--------------------------------------------------------------------------------------------------
RifEclipseSummaryAddress RimSummaryCurve::summaryAddressY() const
{
return m_yValuesCurveVariable->address();
return m_yValuesSummaryAddress->address();
}
//--------------------------------------------------------------------------------------------------
@ -219,14 +215,12 @@ void RimSummaryCurve::setSummaryAddressYAndApplyInterpolation(const RifEclipseSu
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::setSummaryAddressY(const RifEclipseSummaryAddress& address)
{
if (m_yValuesCurveVariable->address() != address)
if (m_yValuesSummaryAddress->address() != address)
{
m_qwtPlotCurve->clearErrorBars();
}
m_yValuesCurveVariable->setAddress(address);
m_yValuesSummaryFilter->updateFromAddress(address);
m_yValuesSummaryAddress->setAddress(address);
}
//--------------------------------------------------------------------------------------------------
@ -262,9 +256,25 @@ std::vector<double> RimSummaryCurve::valuesY() const
if ( !reader ) return values;
RifEclipseSummaryAddress addr = m_yValuesCurveVariable()->address();
RifEclipseSummaryAddress addr = m_yValuesSummaryAddress()->address();
reader->values(addr, &values);
RimSummaryPlot* plot = nullptr;
firstAncestorOrThisOfTypeAsserted(plot);
bool isNormalized = plot->isNormalizationEnabled();
if (isNormalized)
{
auto minMaxPair = std::minmax_element(values.begin(), values.end());
double min = *minMaxPair.first;
double max = *minMaxPair.second;
double range = max - min;
for (double & v: values)
{
v = (v - min)/range;
}
}
return values;
}
@ -309,7 +319,7 @@ std::vector<double> RimSummaryCurve::valuesX() const
{
RifSummaryReaderInterface* reader = m_xValuesSummaryCase()->summaryReader();
RifEclipseSummaryAddress addr = m_xValuesCurveVariable()->address();
RifEclipseSummaryAddress addr = m_xValuesSummaryAddress()->address();
reader->values(addr, &values);
}
@ -326,7 +336,7 @@ const std::vector<time_t>& RimSummaryCurve::timeStepsY() const
if ( !reader ) return emptyVector;
RifEclipseSummaryAddress addr = m_yValuesCurveVariable()->address();
RifEclipseSummaryAddress addr = m_yValuesSummaryAddress()->address();
return reader->timeSteps(addr);
}
@ -390,15 +400,14 @@ QList<caf::PdmOptionItemInfo> RimSummaryCurve::calculateValueOptions(const caf::
options.push_front(caf::PdmOptionItemInfo("None", nullptr));
}
}
else if(fieldNeedingOptions == &m_yValuesUiFilterResultSelection)
else if (&m_yValuesSummaryAddressUiField == fieldNeedingOptions)
{
appendOptionItemsForSummaryAddresses(&options, m_yValuesSummaryCase(), m_yValuesSummaryFilter());
appendOptionItemsForSummaryAddresses(&options, m_yValuesSummaryCase(), nullptr);
}
else if (fieldNeedingOptions == &m_xValuesUiFilterResultSelection)
else if (&m_xValuesSummaryAddressUiField == fieldNeedingOptions)
{
appendOptionItemsForSummaryAddresses(&options, m_xValuesSummaryCase(), m_xValuesSummaryFilter());
appendOptionItemsForSummaryAddresses(&options, m_xValuesSummaryCase(), nullptr);
}
return options;
}
@ -411,18 +420,18 @@ QString RimSummaryCurve::createCurveAutoName()
firstAncestorOrThisOfTypeAsserted(plot);
const RimSummaryPlotNameHelper* nameHelper = plot->activePlotTitleHelperAllCurves();
QString curveName = m_curveNameConfig->curveNameY(m_yValuesCurveVariable->address(), nameHelper);
QString curveName = m_curveNameConfig->curveNameY(m_yValuesSummaryAddress->address(), nameHelper);
if (curveName.isEmpty())
{
curveName = m_curveNameConfig->curveNameY(m_yValuesCurveVariable->address(), nullptr);
curveName = m_curveNameConfig->curveNameY(m_yValuesSummaryAddress->address(), nullptr);
}
if (isCrossPlotCurve())
{
QString curveNameX = m_curveNameConfig->curveNameX(m_xValuesCurveVariable->address(), nameHelper);
QString curveNameX = m_curveNameConfig->curveNameX(m_xValuesSummaryAddress->address(), nameHelper);
if (curveNameX.isEmpty())
{
curveNameX = m_curveNameConfig->curveNameX(m_xValuesCurveVariable->address(), nullptr);
curveNameX = m_curveNameConfig->curveNameX(m_xValuesSummaryAddress->address(), nullptr);
}
if (!curveName.isEmpty() || !curveNameX.isEmpty())
@ -457,11 +466,8 @@ void RimSummaryCurve::onLoadDataAndUpdate(bool updateParentPlot)
{
this->RimPlotCurve::updateCurvePresentation(updateParentPlot);
m_yValuesSelectedVariableDisplayField = QString::fromStdString(m_yValuesCurveVariable->address().uiText());
m_yValuesUiFilterResultSelection = m_yValuesCurveVariable->address();
m_xValuesSelectedVariableDisplayField = QString::fromStdString(m_xValuesCurveVariable->address().uiText());
m_xValuesUiFilterResultSelection = m_xValuesCurveVariable->address();
m_yValuesSummaryAddressUiField = m_yValuesSummaryAddress->address();
m_xValuesSummaryAddressUiField = m_xValuesSummaryAddress->address();
updateConnectedEditors();
@ -616,7 +622,7 @@ void RimSummaryCurve::defineEditorAttribute(const caf::PdmFieldHandle* field, QS
caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*> (attribute);
if (attrib)
{
attrib->m_buttonText = "Vector Selection Dialog";
attrib->m_buttonText = "...";
}
}
}
@ -630,18 +636,12 @@ void RimSummaryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
{
QString curveDataGroupName = "Summary Vector";
if (isCrossPlotCurve()) curveDataGroupName += " Y";
if ( isCrossPlotCurve() ) curveDataGroupName += " Y";
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroupWithKeyword(curveDataGroupName, "Summary Vector Y");
curveDataGroup->add(&m_yValuesSummaryCase);
curveDataGroup->add(&m_yValuesSelectedVariableDisplayField);
curveDataGroup->add(&m_plotAxis);
curveDataGroup->add(&m_yPushButtonSelectSummaryAddress);
QString curveVarSelectionGroupName = "Vector Selection Filter Y";
caf::PdmUiGroup* curveVarSelectionGroup = curveDataGroup->addNewGroupWithKeyword("Vector Selection Filter", curveVarSelectionGroupName);
curveVarSelectionGroup->setCollapsedByDefault(true);
m_yValuesSummaryFilter->uiOrdering(uiConfigName, *curveVarSelectionGroup);
curveVarSelectionGroup->add(&m_yValuesUiFilterResultSelection);
curveDataGroup->add(&m_yValuesSummaryCase, { true, 3, 1 });
curveDataGroup->add(&m_yValuesSummaryAddressUiField, { true, 2, 1 });
curveDataGroup->add(&m_yPushButtonSelectSummaryAddress, { false, 1, 0 });
curveDataGroup->add(&m_plotAxis, { true, 3, 1 });
if (isCrossPlotCurve()) m_showErrorBars = false;
else curveDataGroup->add(&m_showErrorBars);
@ -650,14 +650,9 @@ void RimSummaryCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
if (isCrossPlotCurve())
{
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup("Summary Vector X");
curveDataGroup->add(&m_xValuesSummaryCase);
curveDataGroup->add(&m_xValuesSelectedVariableDisplayField);
curveDataGroup->add(&m_xPushButtonSelectSummaryAddress);
caf::PdmUiGroup* curveVarSelectionGroup = curveDataGroup->addNewGroupWithKeyword("Vector Selection Filter", "Vector Selection Filter X");
curveVarSelectionGroup->setCollapsedByDefault(true);
m_xValuesSummaryFilter->uiOrdering(uiConfigName, *curveVarSelectionGroup);
curveVarSelectionGroup->add(&m_xValuesUiFilterResultSelection);
curveDataGroup->add(&m_xValuesSummaryCase, { true, 3, 1 });
curveDataGroup->add(&m_xValuesSummaryAddressUiField, { true, 2, 1 });
curveDataGroup->add(&m_xPushButtonSelectSummaryAddress, { false, 1, 0});
}
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup("Appearance");
@ -774,7 +769,7 @@ void RimSummaryCurve::applyCurveAutoNameSettings(const RimSummaryCurveAutoName&
//--------------------------------------------------------------------------------------------------
QString RimSummaryCurve::curveExportDescription(const RifEclipseSummaryAddress& address) const
{
auto addr = address.isValid() ? address : m_yValuesCurveVariable->address();
auto addr = address.isValid() ? address : m_yValuesSummaryAddress->address();
RimEnsembleCurveSetCollection* coll;
firstAncestorOrThisOfType(coll);
@ -820,7 +815,7 @@ void RimSummaryCurve::setCurveAppearanceFromCaseType()
}
}
if (m_yValuesCurveVariable && m_yValuesCurveVariable->address().isHistoryQuantity())
if (m_yValuesSummaryAddress && m_yValuesSummaryAddress->address().isHistoryQuantity())
{
RiaPreferences* prefs = RiaApplication::instance()->preferences();
@ -850,7 +845,7 @@ void RimSummaryCurve::setCurveAppearanceFromCaseType()
void RimSummaryCurve::markCachedDataForPurge()
{
auto reader = valuesSummaryReaderY();
if(reader) reader->markForCachePurge(m_yValuesCurveVariable->address());
if(reader) reader->markForCachePurge(m_yValuesSummaryAddress->address());
}
//--------------------------------------------------------------------------------------------------
@ -875,22 +870,22 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
bool loadAndUpdate = false;
bool crossPlotTestForMatchingTimeSteps = false;
if(changedField == &m_yValuesUiFilterResultSelection)
if(changedField == &m_yValuesSummaryAddressUiField)
{
m_yValuesCurveVariable->setAddress(m_yValuesUiFilterResultSelection());
m_yValuesSummaryAddress->setAddress(m_yValuesSummaryAddressUiField());
this->calculateCurveInterpolationFromAddress();
loadAndUpdate = true;
}
else if (changedField == &m_xValuesUiFilterResultSelection)
else if(changedField == &m_xValuesSummaryAddressUiField)
{
m_xValuesCurveVariable->setAddress(m_xValuesUiFilterResultSelection());
m_xValuesSummaryAddress->setAddress(m_xValuesSummaryAddressUiField());
this->calculateCurveInterpolationFromAddress();
loadAndUpdate = true;
}
}
else if (&m_showCurve == changedField)
{
plot->updateAxes();
@ -927,7 +922,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
{
RiuSummaryCurveDefSelectionDialog dlg(nullptr);
RimSummaryCase* candidateCase = m_yValuesSummaryCase();
RifEclipseSummaryAddress candicateAddress = m_yValuesCurveVariable->address();
RifEclipseSummaryAddress candicateAddress = m_yValuesSummaryAddress->address();
if (candidateCase == nullptr)
{
@ -936,7 +931,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
if (!candicateAddress.isValid())
{
candicateAddress = m_xValuesCurveVariable->address();
candicateAddress = m_xValuesSummaryAddress->address();
}
dlg.hideEnsembles();
@ -948,7 +943,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
if (curveSelection.size() > 0)
{
m_yValuesSummaryCase = curveSelection[0].summaryCase();
m_yValuesCurveVariable->setAddress(curveSelection[0].summaryAddress());
m_yValuesSummaryAddress->setAddress(curveSelection[0].summaryAddress());
crossPlotTestForMatchingTimeSteps = true;
loadAndUpdate = true;
@ -961,7 +956,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
{
RiuSummaryCurveDefSelectionDialog dlg(nullptr);
RimSummaryCase* candidateCase = m_xValuesSummaryCase();
RifEclipseSummaryAddress candicateAddress = m_xValuesCurveVariable->address();
RifEclipseSummaryAddress candicateAddress = m_xValuesSummaryAddress->address();
if (candidateCase == nullptr)
{
@ -970,7 +965,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
if (!candicateAddress.isValid())
{
candicateAddress = m_yValuesCurveVariable->address();
candicateAddress = m_yValuesSummaryAddress->address();
}
dlg.hideEnsembles();
@ -982,7 +977,7 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
if (curveSelection.size() > 0)
{
m_xValuesSummaryCase = curveSelection[0].summaryCase();
m_xValuesCurveVariable->setAddress(curveSelection[0].summaryAddress());
m_xValuesSummaryAddress->setAddress(curveSelection[0].summaryAddress());
crossPlotTestForMatchingTimeSteps = true;
loadAndUpdate = true;
@ -1108,7 +1103,7 @@ const std::vector<time_t>& RimSummaryCurve::timeStepsX() const
if (!reader) return emptyVector;
RifEclipseSummaryAddress addr = m_xValuesCurveVariable()->address();
RifEclipseSummaryAddress addr = m_xValuesSummaryAddress()->address();
return reader->timeSteps(addr);
}
@ -1118,9 +1113,9 @@ const std::vector<time_t>& RimSummaryCurve::timeStepsX() const
//--------------------------------------------------------------------------------------------------
void RimSummaryCurve::calculateCurveInterpolationFromAddress()
{
if (m_yValuesCurveVariable())
if (m_yValuesSummaryAddress())
{
auto address = m_yValuesCurveVariable()->address();
auto address = m_yValuesSummaryAddress()->address();
if (address.hasAccumulatedData())
{
m_curveInterpolation = RiuQwtPlotCurve::INTERPOLATION_POINT_TO_POINT;

View File

@ -118,21 +118,22 @@ private:
private:
// Y values
caf::PdmPtrField<RimSummaryCase*> m_yValuesSummaryCase;
caf::PdmChildField<RimSummaryAddress*> m_yValuesCurveVariable;
caf::PdmField<QString> m_yValuesSelectedVariableDisplayField;
caf::PdmChildField<RimSummaryFilter*> m_yValuesSummaryFilter;
caf::PdmField<RifEclipseSummaryAddress> m_yValuesUiFilterResultSelection;
caf::PdmChildField<RimSummaryAddress*> m_yValuesSummaryAddress;
caf::PdmField<RifEclipseSummaryAddress> m_yValuesSummaryAddressUiField;
caf::PdmField<bool> m_yPushButtonSelectSummaryAddress;
// X values
caf::PdmPtrField<RimSummaryCase*> m_xValuesSummaryCase;
caf::PdmChildField<RimSummaryAddress*> m_xValuesCurveVariable;
caf::PdmField<QString> m_xValuesSelectedVariableDisplayField;
caf::PdmChildField<RimSummaryFilter*> m_xValuesSummaryFilter;
caf::PdmField<RifEclipseSummaryAddress> m_xValuesUiFilterResultSelection;
caf::PdmChildField<RimSummaryAddress*> m_xValuesSummaryAddress;
caf::PdmField<RifEclipseSummaryAddress> m_xValuesSummaryAddressUiField;
caf::PdmField<bool> m_xPushButtonSelectSummaryAddress;
caf::PdmChildField<RimSummaryCurveAutoName*> m_curveNameConfig;
caf::PdmField<caf::AppEnum< RiaDefines::PlotAxis>> m_plotAxis;
caf::PdmField<bool> m_isTopZWithinCategory;
// Obsolete fields
caf::PdmChildField<RimSummaryFilter*> m_yValuesSummaryFilter_OBSOLETE;
caf::PdmChildField<RimSummaryFilter*> m_xValuesSummaryFilter_OBSOLETE;
};

View File

@ -140,6 +140,9 @@ RimSummaryPlot::RimSummaryPlot()
CAF_PDM_InitField(&m_useAutoPlotTitle, "IsUsingAutoName", true, "Auto Name", "", "", "");
m_useAutoPlotTitle.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
CAF_PDM_InitField(&m_normalizeCurveYValues, "normalizeCurveYValues", false, "Normalize all curves", "", "", "");
m_normalizeCurveYValues.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
CAF_PDM_InitFieldNoDefault(&m_curveFilters_OBSOLETE, "SummaryCurveFilters", "", "", "", "");
m_curveFilters_OBSOLETE.uiCapability()->setUiTreeHidden(true);
@ -635,6 +638,22 @@ bool RimSummaryPlot::applyFontSize(RiaDefines::FontSettingType fontSettingType,
return anyChange;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::setNormalizationEnabled(bool enable)
{
m_normalizeCurveYValues = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryPlot::isNormalizationEnabled()
{
return m_normalizeCurveYValues();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1227,6 +1246,11 @@ void RimSummaryPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
c->updateCurveNameNoLegendUpdate();
}
}
if (changedField == &m_normalizeCurveYValues)
{
this->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
@ -1510,6 +1534,8 @@ void RimSummaryPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
uiOrdering.add(&m_legendFontSize);
}
uiOrdering.add(&m_normalizeCurveYValues);
m_userDefinedPlotTitle.uiCapability()->setUiReadOnly(m_useAutoPlotTitle);
uiOrdering.skipRemainingFields(true);
@ -1794,6 +1820,14 @@ caf::PdmObject* RimSummaryPlot::findRimPlotObjectFromQwtCurve(const QwtPlotCurve
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::showLegend(bool enable)
{
m_showLegend = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1809,7 +1843,8 @@ void RimSummaryPlot::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt
{
if (field == &m_showLegend ||
field == &m_showPlotTitle ||
field == &m_useAutoPlotTitle)
field == &m_useAutoPlotTitle ||
field == &m_normalizeCurveYValues)
{
caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast<caf::PdmUiCheckBoxEditorAttribute*>(attribute);
if (myAttr)

View File

@ -140,6 +140,9 @@ public:
bool hasCustomFontSizes(RiaDefines::FontSettingType fontSettingType, int defaultFontSize) const override;
bool applyFontSize(RiaDefines::FontSettingType fontSettingType, int oldFontSize, int fontSize, bool forceChange = false) override;
void setNormalizationEnabled(bool enable);
bool isNormalizationEnabled();
void showLegend(bool enable);
public:
// Rim2dPlotInterface overrides
void updateAxisScaling() override;
@ -194,6 +197,8 @@ private:
private:
caf::PdmField<bool> m_showPlotTitle;
caf::PdmField<bool> m_showLegend;
caf::PdmField<bool> m_normalizeCurveYValues;
caf::PdmField<int> m_legendFontSize;
caf::PdmField<bool> m_useAutoPlotTitle;

View File

@ -991,7 +991,13 @@ std::vector<RigEclipseResultAddress> RigCaseCellResultsData::existingResults() c
//--------------------------------------------------------------------------------------------------
const RigEclipseResultInfo* RigCaseCellResultsData::resultInfo(const RigEclipseResultAddress& resVarAddr) const
{
return &(m_resultInfos[findScalarResultIndexFromAddress(resVarAddr)]);
size_t index = findScalarResultIndexFromAddress(resVarAddr);
if (index < m_resultInfos.size())
{
return &(m_resultInfos[index]);
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------

View File

@ -22,6 +22,8 @@ public:
QVariant toUiBasedQVariant() const override;
private:
bool isQVariantDataEqual(const QVariant& oldUiBasedQVariant, const QVariant& newUiBasedQVariant) const override;
mutable QList<PdmOptionItemInfo> m_optionEntryCache;
private:

View File

@ -247,6 +247,15 @@ QVariant caf::PdmFieldUiCap<FieldType>::toUiBasedQVariant() const
return PdmUiFieldSpecialization<typename FieldType::FieldDataType>::convert(m_field->value());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template < typename FieldType>
bool caf::PdmFieldUiCap<FieldType>::isQVariantDataEqual(const QVariant& oldUiBasedQVariant, const QVariant& newUiBasedQVariant) const
{
return PdmUiFieldSpecialization<typename FieldType::FieldDataType>::isDataElementEqual(oldUiBasedQVariant, newUiBasedQVariant);
}
} // End of namespace caf

View File

@ -52,9 +52,8 @@ QList<caf::PdmOptionItemInfo> PdmUiFieldHandle::valueOptions(bool* useOptionsOnl
//--------------------------------------------------------------------------------------------------
void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const QVariant& newFieldValue)
{
// Todo : Should use a virtual version of isElementEqual. The variant != operation will not work on user types
if (oldFieldValue != newFieldValue)
if (!this->isQVariantDataEqual( oldFieldValue, newFieldValue))
{
PdmFieldHandle* fieldHandle = this->fieldHandle();
CAF_ASSERT(fieldHandle && fieldHandle->ownerObject());
@ -126,6 +125,15 @@ void PdmUiFieldHandle::setAutoAddingOptionFromValue(bool isAddingValue)
//--------------------------------------------------------------------------------------------------
void PdmUiFieldHandle::setValueFromUiEditor(const QVariant& uiValue) {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiFieldHandle::isQVariantDataEqual(const QVariant& oldUiBasedQVariant, const QVariant& newUiBasedQVariant) const
{
CAF_ASSERT(false);
return false;
}
//--------------------------------------------------------------------------------------------------
/// Implementation of uiCapability() defined in cafPdmFieldHandle.h
//--------------------------------------------------------------------------------------------------

View File

@ -31,6 +31,8 @@ private:
friend class PdmUiCommandSystemProxy;
friend class CmdFieldChangeExec;
virtual void setValueFromUiEditor(const QVariant& uiValue);
// This is needed to handle custom types in QVariants since operator == between QVariant does not work when they use custom types.
virtual bool isQVariantDataEqual(const QVariant& oldUiBasedQVariant, const QVariant& newUiBasedQVariant) const;
private:
PdmFieldHandle* m_owner;

View File

@ -56,6 +56,12 @@
#include <QPalette>
#include <QStatusBar>
#include <QString>
#include <QCompleter>
#include <QStringListModel>
#include <QAbstractProxyModel>
#include <QAbstractItemView>
#include <QDebug>
namespace caf
{
@ -111,8 +117,8 @@ void PdmUiLineEditor::configureAndUpdateUi(const QString& uiConfigName)
m_lineEdit->setToolTip(uiField()->uiToolTip(uiConfigName));
PdmUiLineEditorAttribute leab;
{
PdmUiLineEditorAttribute leab;
caf::PdmUiObjectHandle* uiObject = uiObj(uiField()->fieldHandle()->ownerObject());
if (uiObject)
{
@ -126,31 +132,58 @@ void PdmUiLineEditor::configureAndUpdateUi(const QString& uiConfigName)
m_lineEdit->setAvoidSendingEnterEventToParentWidget(leab.avoidSendingEnterEventToParentWidget);
}
bool fromMenuOnly = true;
QList<PdmOptionItemInfo> enumNames = uiField()->valueOptions(&fromMenuOnly);
m_optionCache = uiField()->valueOptions(&fromMenuOnly);
CAF_ASSERT(fromMenuOnly); // Not supported
if (!enumNames.isEmpty() && fromMenuOnly == true)
if (!m_optionCache.isEmpty() && fromMenuOnly == true)
{
if (!m_completer)
{
m_completer = new QCompleter(this);
m_completerTextList = new QStringListModel( this);
m_completer->setModel(m_completerTextList);
m_completer->setFilterMode( leab.completerFilterMode );
m_completer->setCaseSensitivity( leab.completerCaseSensitivity);
m_lineEdit->setCompleter(m_completer);
connect(m_completer, SIGNAL(activated(const QModelIndex&)), this, SLOT(slotCompleterActivated(const QModelIndex&)));
m_completer->popup()->installEventFilter(this);
}
QStringList optionNames;
for (const PdmOptionItemInfo& item: m_optionCache)
{
optionNames.push_back(item.optionUiText());
}
m_completerTextList->setStringList(optionNames);
int enumValue = uiField()->uiValue().toInt();
if (enumValue < enumNames.size() && enumValue > -1)
if (enumValue < m_optionCache.size() && enumValue > -1)
{
m_lineEdit->setText(enumNames[enumValue].optionUiText());
m_lineEdit->setText(m_optionCache[enumValue].optionUiText());
}
}
else
{
PdmUiLineEditorAttributeUiDisplayString leab;
m_lineEdit->setCompleter(nullptr);
delete m_completerTextList;
delete m_completer;
m_optionCache.clear();
PdmUiLineEditorAttributeUiDisplayString displayStringAttrib;
caf::PdmUiObjectHandle* uiObject = uiObj(uiField()->fieldHandle()->ownerObject());
if (uiObject)
{
uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, &leab);
uiObject->editorAttribute(uiField()->fieldHandle(), uiConfigName, &displayStringAttrib);
}
QString displayString;
if (leab.m_displayString.isEmpty())
if (displayStringAttrib.m_displayString.isEmpty())
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
bool valueOk = false;
@ -171,7 +204,7 @@ void PdmUiLineEditor::configureAndUpdateUi(const QString& uiConfigName)
}
else
{
displayString = leab.m_displayString;
displayString = displayStringAttrib.m_displayString;
}
m_lineEdit->setText(displayString);
@ -203,9 +236,50 @@ QMargins PdmUiLineEditor::calculateLabelContentMargins() const
void PdmUiLineEditor::slotEditingFinished()
{
QVariant v;
QString textValue = m_lineEdit->text();
v = textValue;
this->setValueToField(v);
if (m_optionCache.size())
{
int index = findIndexToOption(m_lineEdit->text());
if (index > -1)
{
v = QVariant(static_cast<unsigned int>(index));
this->setValueToField(v);
}
else
{
// Try to complete the text in the widget
QModelIndex sourceindex = static_cast<QAbstractProxyModel*>(m_completer->completionModel())->mapToSource(m_completer->currentIndex());
if ( sourceindex.isValid() )
{
int currentRow = sourceindex.row();
{
// If the existing value in the field is the same as the completer will hit, we need to echo the
// choice into the text field because the field values are equal, so the normal echoing is considered unneccessary by the caf system.
int currentFieldIndexValue = uiField()->uiValue().toInt();
if ( currentRow == currentFieldIndexValue )
{
m_lineEdit->setText(m_completer->completionModel()->data(m_completer->currentIndex()).toString());
}
}
v = QVariant(static_cast<unsigned int>(sourceindex.row()));
this->setValueToField(v);
}
else
{
// Revert to value stored in the PdmField, because we didn't find any matches
this->updateUi();
}
}
}
else
{
QString textValue = m_lineEdit->text();
v = textValue;
this->setValueToField(v);
}
}
//--------------------------------------------------------------------------------------------------
@ -240,7 +314,6 @@ bool PdmUiLineEditor::isMultipleFieldsWithSameKeywordSelected(PdmFieldHandle* ed
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -274,6 +347,57 @@ void PdmUiLineEdit::keyPressEvent(QKeyEvent * event)
}
}
//--------------------------------------------------------------------------------------------------
/// Event filter filtering events to the QCompleter
//--------------------------------------------------------------------------------------------------
bool PdmUiLineEditor::eventFilter(QObject *watched, QEvent *event)
{
if ( event->type() == QEvent::KeyPress )
{
QKeyEvent * ke = static_cast<QKeyEvent*>(event);
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)
{
m_ignoreCompleterActivated = true;
this->m_completer->popup()->close();
this->slotEditingFinished();
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiLineEditor::slotCompleterActivated(const QModelIndex& index)
{
if (m_completer && !m_ignoreCompleterActivated)
{
slotEditingFinished();
}
m_ignoreCompleterActivated = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int PdmUiLineEditor::findIndexToOption(const QString& uiText)
{
QString uiTextTrimmed = uiText.trimmed();
for (int idx = 0; idx < m_optionCache.size(); ++idx)
{
if (uiTextTrimmed == m_optionCache[idx].optionUiText())
{
return idx;
}
}
return -1;
}
// Define at this location to avoid duplicate symbol definitions in 'cafPdmUiDefaultObjectEditor.cpp' in a cotire build. The
// variables defined by the macro are prefixed by line numbers causing a crash if the macro is defined at the same line number.
CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiLineEditor);

View File

@ -47,6 +47,8 @@
#include <QWidget>
class QGridLayout;
class QCompleter;
class QStringListModel;
namespace caf
{
@ -60,11 +62,17 @@ public:
PdmUiLineEditorAttribute()
{
avoidSendingEnterEventToParentWidget = false;
completerCaseSensitivity = Qt::CaseSensitive;
completerFilterMode = Qt::MatchContains;
}
public:
bool avoidSendingEnterEventToParentWidget;
bool avoidSendingEnterEventToParentWidget;
QPointer<QValidator> validator;
// Completer setup
Qt::CaseSensitivity completerCaseSensitivity;
Qt::MatchFlags completerFilterMode;
};
//--------------------------------------------------------------------------------------------------
@ -80,6 +88,9 @@ public:
QString m_displayString;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class PdmUiLineEdit : public QLineEdit
{
Q_OBJECT
@ -101,7 +112,7 @@ class PdmUiLineEditor : public PdmUiFieldEditorHandle
CAF_PDM_UI_FIELD_EDITOR_HEADER_INIT;
public:
PdmUiLineEditor() {}
PdmUiLineEditor() : m_ignoreCompleterActivated(false) {}
~PdmUiLineEditor() override {}
protected:
@ -110,16 +121,25 @@ protected:
void configureAndUpdateUi(const QString& uiConfigName) override;
QMargins calculateLabelContentMargins() const override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
protected slots:
void slotEditingFinished();
void slotCompleterActivated(const QModelIndex& index);
private:
bool isMultipleFieldsWithSameKeywordSelected(PdmFieldHandle* editorField) const;
protected:
QPointer<PdmUiLineEdit> m_lineEdit;
QPointer<QShortenedLabel> m_label;
QPointer<PdmUiLineEdit> m_lineEdit;
QPointer<QShortenedLabel> m_label;
QPointer<QCompleter> m_completer;
QPointer<QStringListModel> m_completerTextList;
QList<PdmOptionItemInfo> m_optionCache;
bool m_ignoreCompleterActivated;
int findIndexToOption(const QString& uiText);
};