diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp index f918369bf8..0793ec30a5 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicAppendSummaryPlotsForObjectsFeature.cpp @@ -93,10 +93,10 @@ void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* s adrMod.setAddress( modifiedAdr ); } summaryMultiPlot->addPlot( duplicatedPlot ); - duplicatedPlot->resolveReferencesRecursively(); - duplicatedPlot->loadDataAndUpdate(); } + + duplicatedPlot->loadDataAndUpdate(); } info.incrementProgress(); } diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFeature.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFeature.cpp index efcda8508f..4091957c40 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFeature.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicNewSummaryMultiPlotFeature.cpp @@ -20,6 +20,7 @@ #include "RicSummaryPlotBuilder.h" +#include "RimProject.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" #include "RimSummaryMultiPlot.h" @@ -60,22 +61,30 @@ void RicNewSummaryMultiPlotFeature::onActionTriggered( bool isChecked ) std::vector selectedUiItems; caf::SelectionManager::instance()->selectedItems( selectedUiItems ); - RimSummaryMultiPlotCollection* coll = selectedCollection( selectedUiItems ); - if ( coll ) - { - std::vector objects = {}; - RimSummaryMultiPlot* multiPlot = RicSummaryPlotBuilder::createAndAppendSummaryMultiPlot( objects ); - - return; - } - std::vector selectedIndividualSummaryCases; std::vector selectedEnsembles; - if ( selectedCases( &selectedIndividualSummaryCases, &selectedEnsembles ) ) + RimSummaryMultiPlotCollection* coll = selectedCollection( selectedUiItems ); + if ( coll ) { - RicSummaryPlotBuilder::createAndAppendDefaultSummaryMultiPlot( selectedIndividualSummaryCases, selectedEnsembles ); + auto ensembles = RimProject::current()->summaryGroups(); + if ( !ensembles.empty() ) + selectedEnsembles.push_back( ensembles.front() ); + else + { + auto summaryCases = RimProject::current()->allSummaryCases(); + if ( !summaryCases.empty() ) selectedIndividualSummaryCases.push_back( summaryCases.front() ); + } } + else + { + selectedCases( &selectedIndividualSummaryCases, &selectedEnsembles ); + } + + bool skipCreationOfPlotBasedOnPreferences = false; + RicSummaryPlotBuilder::createAndAppendDefaultSummaryMultiPlot( selectedIndividualSummaryCases, + selectedEnsembles, + skipCreationOfPlotBasedOnPreferences ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp index 25bceebd5b..9e3dfcd53d 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.cpp @@ -410,11 +410,14 @@ void RicSummaryPlotBuilder::appendPlotsToMultiPlot( RimMultiPlot* multiPlot, con //-------------------------------------------------------------------------------------------------- RimSummaryMultiPlot* RicSummaryPlotBuilder::createAndAppendDefaultSummaryMultiPlot( const std::vector& cases, - const std::vector& ensembles ) + const std::vector& ensembles, + bool skipCreationOfPlotBasedOnPreferences ) { RiaPreferencesSummary* prefs = RiaPreferencesSummary::current(); - if ( prefs->defaultSummaryPlotType() == RiaPreferencesSummary::DefaultSummaryPlotType::NONE ) return nullptr; + if ( skipCreationOfPlotBasedOnPreferences && + prefs->defaultSummaryPlotType() == RiaPreferencesSummary::DefaultSummaryPlotType::NONE ) + return nullptr; if ( prefs->defaultSummaryPlotType() == RiaPreferencesSummary::DefaultSummaryPlotType::PLOT_TEMPLATES ) { @@ -424,10 +427,17 @@ RimSummaryMultiPlot* { plotToSelect = RicSummaryPlotTemplateTools::create( filename, cases, ensembles ); } - return plotToSelect; + + if ( plotToSelect ) return plotToSelect; + + if ( skipCreationOfPlotBasedOnPreferences ) + { + return plotToSelect; + } } - if ( prefs->defaultSummaryCurvesTextFilter().trimmed().isEmpty() ) return nullptr; + if ( skipCreationOfPlotBasedOnPreferences && prefs->defaultSummaryCurvesTextFilter().trimmed().isEmpty() ) + return nullptr; RimProject* project = RimProject::current(); auto* plotCollection = project->mainPlotCollection()->summaryMultiPlotCollection(); diff --git a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h index b4c7d36ea6..dba405e40a 100644 --- a/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h +++ b/ApplicationLibCode/Commands/PlotBuilderCommands/RicSummaryPlotBuilder.h @@ -77,7 +77,8 @@ public: static RimSummaryMultiPlot* createAndAppendDefaultSummaryMultiPlot( const std::vector& cases, - const std::vector& ensembles ); + const std::vector& ensembles, + bool skipCreationOfPlotBasedOnPreferences = true ); static RimSummaryMultiPlot* createAndAppendSingleSummaryMultiPlotNoAutoSettings( RimSummaryPlot* plot ); static RimSummaryMultiPlot* createAndAppendSingleSummaryMultiPlot( RimSummaryPlot* plot ); diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake index 2daeb86cd4..fe183d08c8 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/CMakeLists_files.cmake @@ -1,4 +1,5 @@ set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicOpenSummaryPlotEditorFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewDefaultSummaryPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCurveFeature.h @@ -46,6 +47,7 @@ set(SOURCE_GROUP_HEADER_FILES ) set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicOpenSummaryPlotEditorFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewDefaultSummaryPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCurveFeature.cpp diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicOpenSummaryPlotEditorFeature.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicOpenSummaryPlotEditorFeature.cpp new file mode 100644 index 0000000000..a1c90e6c01 --- /dev/null +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicOpenSummaryPlotEditorFeature.cpp @@ -0,0 +1,139 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2022 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicOpenSummaryPlotEditorFeature.h" + +#include "RiaSummaryTools.h" + +#include "RicEditSummaryPlotFeature.h" +#include "RicNewSummaryEnsembleCurveSetFeature.h" +#include "RicSummaryPlotEditorDialog.h" +#include "RicSummaryPlotEditorUi.h" +#include "RicSummaryPlotFeatureImpl.h" + +#include "RimCustomObjectiveFunctionCollection.h" +#include "RimEnsembleCurveFilter.h" +#include "RimEnsembleCurveFilterCollection.h" +#include "RimProject.h" +#include "RimRegularLegendConfig.h" +#include "RimSummaryCase.h" +#include "RimSummaryCaseCollection.h" +#include "RimSummaryCaseMainCollection.h" +#include "RimSummaryPlot.h" + +#include "RiuPlotMainWindow.h" + +#include "cafSelectionManagerTools.h" +#include "cvfAssert.h" + +#include + +CAF_CMD_SOURCE_INIT( RicOpenSummaryPlotEditorFeature, "RicOpenSummaryPlotEditorFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicOpenSummaryPlotEditorFeature::isCommandEnabled() +{ + RimSummaryMultiPlot* multiPlot = nullptr; + RimCustomObjectiveFunctionCollection* customObjFuncCollection = nullptr; + + caf::PdmObject* selObj = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ); + if ( selObj ) + { + multiPlot = RiaSummaryTools::parentSummaryMultiPlot( selObj ); + selObj->firstAncestorOrThisOfType( customObjFuncCollection ); + } + + auto ensembleFilter = dynamic_cast( selObj ); + auto ensembleFilterColl = dynamic_cast( selObj ); + auto legendConfig = dynamic_cast( selObj ); + + if ( ensembleFilter || ensembleFilterColl || legendConfig || customObjFuncCollection ) return false; + if ( multiPlot ) return true; + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicOpenSummaryPlotEditorFeature::onActionTriggered( bool isChecked ) +{ + RimProject* project = RimProject::current(); + CVF_ASSERT( project ); + + std::vector selectedCases = caf::selectedObjectsByType(); + std::vector selectedGroups = caf::selectedObjectsByType(); + + std::vector sourcesToSelect( selectedCases.begin(), selectedCases.end() ); + + if ( sourcesToSelect.empty() && selectedGroups.empty() ) + { + const auto allSingleCases = project->firstSummaryCaseMainCollection()->topLevelSummaryCases(); + const auto allGroups = project->summaryGroups(); + std::vector allEnsembles; + for ( const auto group : allGroups ) + if ( group->isEnsemble() ) allEnsembles.push_back( group ); + + if ( !allSingleCases.empty() ) + { + sourcesToSelect.push_back( allSingleCases.front() ); + } + else if ( !allEnsembles.empty() ) + { + sourcesToSelect.push_back( allEnsembles.front() ); + } + } + + // Append grouped cases + for ( auto group : selectedGroups ) + { + if ( group->isEnsemble() ) + { + sourcesToSelect.push_back( group ); + } + else + { + auto groupCases = group->allSummaryCases(); + sourcesToSelect.insert( sourcesToSelect.end(), groupCases.begin(), groupCases.end() ); + } + } + + auto dialog = RicEditSummaryPlotFeature::curveCreatorDialog( true ); + + if ( !dialog->isVisible() ) + { + dialog->show(); + } + else + { + dialog->raise(); + } + + dialog->updateFromDefaultCases( sourcesToSelect ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicOpenSummaryPlotEditorFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Open Summary Plot Editor" ); + actionToSetup->setIcon( QIcon( ":/SummaryPlotLight16x16.png" ) ); +} diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicOpenSummaryPlotEditorFeature.h b/ApplicationLibCode/Commands/SummaryPlotCommands/RicOpenSummaryPlotEditorFeature.h new file mode 100644 index 0000000000..c36c873c34 --- /dev/null +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicOpenSummaryPlotEditorFeature.h @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RicfCommandObject.h" + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicOpenSummaryPlotEditorFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp index ab9f714668..77b6641c07 100644 --- a/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp +++ b/ApplicationLibCode/Commands/SummaryPlotCommands/RicSummaryPlotEditorUi.cpp @@ -50,6 +50,8 @@ #include "RiuSummaryVectorSelectionUi.h" #include "RiuTools.h" +#include "PlotBuilderCommands/RicSummaryPlotBuilder.h" + #include "cafPdmUiComboBoxEditor.h" #include "cafPdmUiPushButtonEditor.h" @@ -263,7 +265,7 @@ QList RicSummaryPlotEditorUi::calculateValueOptions( con { QList options; - if ( m_targetPlot && ( fieldNeedingOptions == &m_targetPlot ) ) + if ( fieldNeedingOptions == &m_targetPlot ) { // Create New Plot item QString displayName = "( New Plot )"; @@ -845,6 +847,12 @@ void RicSummaryPlotEditorUi::createNewPlot() RimSummaryPlot* newSummaryPlot = nullptr; + if ( !m_plotContainer ) + { + std::vector plots; + m_plotContainer = RicSummaryPlotBuilder::createAndAppendSummaryMultiPlot( plots ); + } + if ( m_plotContainer ) { newSummaryPlot = new RimSummaryPlot(); diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 2a162602f5..cf6bcf436c 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -561,6 +561,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() else if ( dynamic_cast( firstUiItem ) ) { menuBuilder << "RicNewSummaryMultiPlotFeature"; + menuBuilder << "RicOpenSummaryPlotEditorFeature"; menuBuilder << "Separator"; menuBuilder << "RicPasteSummaryPlotFeature"; menuBuilder << "RicPasteAsciiDataToSummaryPlotFeature"; @@ -774,6 +775,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.addSeparator(); menuBuilder << "RicNewSummaryMultiPlotFeature"; menuBuilder << "RicNewDerivedEnsembleFeature"; + menuBuilder << "RicOpenSummaryPlotEditorFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder.addSeparator(); menuBuilder << "RicConvertGroupToEnsembleFeature"; @@ -781,6 +783,9 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() } else if ( dynamic_cast( firstUiItem ) ) { + menuBuilder << "RicShowDataSourcesForRealization"; + menuBuilder.addSeparator(); + menuBuilder.subMenuStart( "Import" ); menuBuilder << "RicImportSummaryCaseFeature"; menuBuilder << "RicImportSummaryCasesFeature"; @@ -789,6 +794,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder.subMenuEnd(); menuBuilder.addSeparator(); menuBuilder << "RicNewSummaryMultiPlotFeature"; + menuBuilder << "RicOpenSummaryPlotEditorFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder << "RicAppendSummaryCurvesForSummaryCasesFeature"; menuBuilder << "RicAppendSummaryPlotsForSummaryCasesFeature"; @@ -1092,6 +1098,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicNewSummaryMultiPlotFeature"; menuBuilder << "RicNewDerivedEnsembleFeature"; + menuBuilder << "RicOpenSummaryPlotEditorFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder << "RicSummaryCurveSwitchAxisFeature"; menuBuilder << "RicNewDerivedSummaryFeature"; @@ -1110,7 +1117,6 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicReloadSummaryCaseFeature"; menuBuilder << "RicReplaceSummaryCaseFeature"; menuBuilder << "RicCreateSummaryCaseCollectionFeature"; - menuBuilder << "RicShowDataSourcesForRealization"; menuBuilder << "Separator"; menuBuilder << "RicCutReferencesToClipboardFeature"; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index e5949f3f22..c4327abba6 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -184,6 +184,8 @@ void RimSummaryCaseCollection::addCase( RimSummaryCase* summaryCase ) { summaryCase->nameChanged.connect( this, &RimSummaryCaseCollection::onCaseNameChanged ); + if ( m_cases.empty() ) summaryCase->setShowRealizationDataSource( true ); + m_cases.push_back( summaryCase ); m_cachedSortedEnsembleParameters.clear(); m_analyzer.reset(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp index 885dae6ee1..056c310ad1 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp @@ -1162,7 +1162,13 @@ void RimSummaryMultiPlot::summaryPlotItemInfos( QList* o { for ( RimSummaryPlot* plot : summaryPlots() ) { - QString displayName = plot->description(); + QString displayName; + + if ( plot && plot->userDescriptionField() && plot->userDescriptionField() ) + { + displayName = plot->userDescriptionField()->uiCapability()->uiValue().toString(); + } + optionInfos->push_back( caf::PdmOptionItemInfo( displayName, plot, false, plot->uiCapability()->uiIconProvider() ) ); } } @@ -1217,8 +1223,6 @@ void RimSummaryMultiPlot::analyzePlotsAndAdjustAppearanceSettings() // Disable sub plot linking to be able to configure individually setSubPlotAxesLinked( false ); - axisProp->setShowDescription( false ); - auto [row, col] = gridLayoutInfoForSubPlot( p ); if ( col == 0 ) axisProp->setShowUnitText( true ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index cdbaaed199..e8c9f5805d 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -564,7 +564,8 @@ void RimSummaryPlot::updatePlotTitle() RimMultiPlot* plotWindow = nullptr; firstAncestorOrThisOfType( plotWindow ); - auto index = plotWindow->plotIndex( this ); + size_t index = 0; + if ( plotWindow ) index = plotWindow->plotIndex( this ); QString title = QString( "Sub Plot %1" ).arg( index + 1 ); m_fallbackPlotName = title; @@ -2361,6 +2362,11 @@ RiuPlotWidget* RimSummaryPlot::doCreatePlotViewWidget( QWidget* mainWindowParent useQtCharts = true; } + // Disable all use of QtCharts for now. If a plot was created using QtCharts during the period this flag was + // active, the use of QtCharts was stored in the project file or template file. Set flag to false to force use + // of Qwt + useQtCharts = false; + if ( useQtCharts ) { m_summaryPlot = std::make_unique( this, mainWindowParent ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index 3c4cd5f780..0eb550b7a5 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -62,6 +62,8 @@ RimSummaryPlotSourceStepping::RimSummaryPlotSourceStepping() { CAF_PDM_InitObject( "Summary Curves Modifier" ); + setNotifyAllFieldsInMultiFieldChangedEvents( true ); + CAF_PDM_InitFieldNoDefault( &m_stepDimension, "StepDimension", "Step Dimension" ); CAF_PDM_InitFieldNoDefault( &m_summaryCase, "CurveCase", "Case" ); diff --git a/Fwk/AppFwk/cafCommand/cafCmdFieldChangeExec.cpp b/Fwk/AppFwk/cafCommand/cafCmdFieldChangeExec.cpp index a11c584b6a..4b27c7d692 100644 --- a/Fwk/AppFwk/cafCommand/cafCmdFieldChangeExec.cpp +++ b/Fwk/AppFwk/cafCommand/cafCmdFieldChangeExec.cpp @@ -89,11 +89,32 @@ void CmdFieldChangeExec::redo() PdmFieldHandle* field = PdmReferenceHelper::fieldFromReference( m_commandData->m_rootObject, fieldTextPath ); if ( !field ) continue; + bool objectFlag = false; + PdmObjectHandle* obj = field->ownerObject(); + auto uiObjectHandle = uiObj( obj ); + if ( uiObjectHandle ) + { + objectFlag = uiObjectHandle->notifyAllFieldsInMultiFieldChangedEvents(); + + // Make sure that uiOrdering has been called on all objects, as some object do some state initialization. + // This is relevant for data source stepping objects. This operation could be made into a virtual function. + caf::PdmUiOrdering ordering; + uiObjectHandle->uiOrdering( "", ordering ); + } + PdmUiFieldHandle* uiFieldHandle = field->uiCapability(); PdmXmlFieldHandle* xmlFieldHandle = field->xmlCapability(); if ( uiFieldHandle && xmlFieldHandle ) { - bool isLastField = ( i == m_commandData->m_pathToFields.size() - 1 ); + // In multi field update operations, a single fieldChanged() notification is sufficient for many use cases + // where properties like color/size are modified. For control operations like changing the data source + // for multiple sub objects, we need to issue fieldChanged() for all modified fields. This behaviour can be + // forced both on object level and field level + + bool isLastField = ( i == m_commandData->m_pathToFields.size() - 1 ); + bool sendFieldChangedNotification = isLastField; + if ( objectFlag ) sendFieldChangedNotification = true; + if ( uiFieldHandle->notifyAllFieldsInMultiFieldChangedEvents() ) sendFieldChangedNotification = true; if ( m_commandData->m_undoFieldValueSerialized[i].isEmpty() ) { @@ -107,7 +128,7 @@ void CmdFieldChangeExec::redo() // The ui value might be an index into the option entry cache, so we need to set the value // and be aware of the option entries, and then serialize the actual field value we ended up with. - uiFieldHandle->setValueFromUiEditor( m_commandData->m_newUiValue, isLastField ); + uiFieldHandle->setValueFromUiEditor( m_commandData->m_newUiValue, sendFieldChangedNotification ); if ( m_commandData->m_redoFieldValueSerialized.isEmpty() ) { @@ -126,7 +147,7 @@ void CmdFieldChangeExec::redo() QVariant newFieldData = uiFieldHandle->toUiBasedQVariant(); // New data is present in field, notify data changed - if ( isLastField ) + if ( sendFieldChangedNotification ) { uiFieldHandle->notifyFieldChanged( oldFieldData, newFieldData ); if ( m_notificationCenter ) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp index dfc2fd83a5..d6cfa56136 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.cpp @@ -488,6 +488,33 @@ void PdmUiItem::setUiReadOnly( bool isReadOnly, const QString& uiConfigName /*= m_configItemInfos[uiConfigName].m_isReadOnly = isReadOnly; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool PdmUiItem::notifyAllFieldsInMultiFieldChangedEvents( const QString& uiConfigName /*= "" */ ) const +{ + const PdmUiItemInfo* conInfo = configInfo( uiConfigName ); + const PdmUiItemInfo* defInfo = defaultInfo(); + const PdmUiItemInfo* sttInfo = m_staticItemInfo; + + if ( conInfo && !( conInfo->m_notifyAllFieldsInMultiFieldChangedEvents == -1 ) ) + return conInfo->m_notifyAllFieldsInMultiFieldChangedEvents; + if ( defInfo && !( defInfo->m_notifyAllFieldsInMultiFieldChangedEvents == -1 ) ) + return defInfo->m_notifyAllFieldsInMultiFieldChangedEvents; + if ( sttInfo && !( sttInfo->m_notifyAllFieldsInMultiFieldChangedEvents == -1 ) ) + return sttInfo->m_notifyAllFieldsInMultiFieldChangedEvents; + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiItem::setNotifyAllFieldsInMultiFieldChangedEvents( bool enable, const QString& uiConfigName /*= "" */ ) +{ + m_configItemInfos[uiConfigName].m_notifyAllFieldsInMultiFieldChangedEvents = enable; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h index 8032082a17..997ce49b42 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiItem.h @@ -71,6 +71,7 @@ public: , m_isReadOnly( -1 ) , m_labelAlignment( LEFT ) , m_isCustomContextMenuEnabled( -1 ) + , m_notifyAllFieldsInMultiFieldChangedEvents( -1 ) { } @@ -105,6 +106,7 @@ private: int m_isReadOnly; ///< UiItem should be insensitive, or read only. -1 means not set. LabelPosType m_labelAlignment; int m_isCustomContextMenuEnabled; + int m_notifyAllFieldsInMultiFieldChangedEvents; }; //================================================================================================== @@ -278,6 +280,9 @@ public: bool isUiReadOnly( const QString& uiConfigName = "" ) const; void setUiReadOnly( bool isReadOnly, const QString& uiConfigName = "" ); + bool notifyAllFieldsInMultiFieldChangedEvents( const QString& uiConfigName = "" ) const; + void setNotifyAllFieldsInMultiFieldChangedEvents( bool enable, const QString& uiConfigName = "" ); + PdmUiItemInfo::LabelPosType uiLabelPosition( const QString& uiConfigName = "" ) const; void setUiLabelPosition( PdmUiItemInfo::LabelPosType alignment, const QString& uiConfigName = "" ); diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index bbb7d78a5e..17950e9b16 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -5,7 +5,7 @@ set(RESINSIGHT_PATCH_VERSION 0) # Opional text with no restrictions #"set(RESINSIGHT_VERSION_TEXT "-dev") -set(RESINSIGHT_VERSION_TEXT "-RC_01") +set(RESINSIGHT_VERSION_TEXT "-RC_02") # Optional text # Must be unique and increasing within one combination of major/minor/patch version