diff --git a/ApplicationLibCode/Commands/CompletionCommands/RicDeleteValveTemplateFeature.cpp b/ApplicationLibCode/Commands/CompletionCommands/RicDeleteValveTemplateFeature.cpp index b48354b442a..ca05089ef7d 100644 --- a/ApplicationLibCode/Commands/CompletionCommands/RicDeleteValveTemplateFeature.cpp +++ b/ApplicationLibCode/Commands/CompletionCommands/RicDeleteValveTemplateFeature.cpp @@ -57,7 +57,7 @@ void RicDeleteValveTemplateFeature::onActionTriggered( bool isChecked ) } RimValveTemplateCollection* collection = valveTemplate->firstAncestorOrThisOfTypeAsserted(); - collection->removeAndDeleteValveTemplate( valveTemplate ); + collection->deleteItem( valveTemplate ); collection->updateAllRequiredEditors(); project->scheduleCreateDisplayModelAndRedrawAllViews(); diff --git a/ApplicationLibCode/Commands/CompletionCommands/RicImportValveTemplatesFeature.cpp b/ApplicationLibCode/Commands/CompletionCommands/RicImportValveTemplatesFeature.cpp index f36d22021f2..f5421050329 100644 --- a/ApplicationLibCode/Commands/CompletionCommands/RicImportValveTemplatesFeature.cpp +++ b/ApplicationLibCode/Commands/CompletionCommands/RicImportValveTemplatesFeature.cpp @@ -110,7 +110,7 @@ void RicImportValveTemplatesFeature::onActionTriggered( bool isChecked ) for ( const auto& aicdValue : aicdTemplates ) { auto newTemplate = RimValveTemplate::createAicdTemplate( aicdValue, number++ ); - templateColl->addValveTemplate( newTemplate ); + templateColl->addItem( newTemplate ); } } diff --git a/ApplicationLibCode/Commands/CompletionCommands/RicNewValveTemplateFeature.cpp b/ApplicationLibCode/Commands/CompletionCommands/RicNewValveTemplateFeature.cpp index 7a352b12aaf..3d446ccf494 100644 --- a/ApplicationLibCode/Commands/CompletionCommands/RicNewValveTemplateFeature.cpp +++ b/ApplicationLibCode/Commands/CompletionCommands/RicNewValveTemplateFeature.cpp @@ -87,9 +87,9 @@ RimValveTemplate* RicNewValveTemplateFeature::createNewValveTemplate() if ( valveTemplateColl ) { RimValveTemplate* valveTemplate = new RimValveTemplate(); - QString userLabel = QString( "Valve Template #%1" ).arg( valveTemplateColl->valveTemplates().size() + 1 ); + QString userLabel = QString( "Valve Template #%1" ).arg( valveTemplateColl->count() + 1 ); valveTemplate->setUserLabel( userLabel ); - valveTemplateColl->addValveTemplate( valveTemplate ); + valveTemplateColl->addItem( valveTemplate ); valveTemplate->setUnitSystem( valveTemplateColl->defaultUnitSystemType() ); valveTemplate->setDefaultValuesFromUnits(); return valveTemplate; diff --git a/ApplicationLibCode/Commands/FractureCommands/RicNewElasticPropertyScalingFeature.cpp b/ApplicationLibCode/Commands/FractureCommands/RicNewElasticPropertyScalingFeature.cpp index aea8a322ff6..2cd8081b8b4 100644 --- a/ApplicationLibCode/Commands/FractureCommands/RicNewElasticPropertyScalingFeature.cpp +++ b/ApplicationLibCode/Commands/FractureCommands/RicNewElasticPropertyScalingFeature.cpp @@ -46,7 +46,7 @@ void RicNewElasticPropertyScalingFeature::onActionTriggered( bool isChecked ) RimElasticPropertyScaling* elasticPropertyScaling = new RimElasticPropertyScaling; elasticPropertyScaling->ensureDefaultFormationAndFacies(); - scalingColl->addElasticPropertyScaling( elasticPropertyScaling ); + scalingColl->addItem( elasticPropertyScaling ); scalingColl->updateConnectedEditors(); Riu3DMainWindowTools::selectAsCurrentItem( elasticPropertyScaling ); diff --git a/ApplicationLibCode/Commands/RicWellMeasurementImportTools.cpp b/ApplicationLibCode/Commands/RicWellMeasurementImportTools.cpp index 5e11fc935d0..afa41058fe6 100644 --- a/ApplicationLibCode/Commands/RicWellMeasurementImportTools.cpp +++ b/ApplicationLibCode/Commands/RicWellMeasurementImportTools.cpp @@ -94,9 +94,11 @@ void RicWellMeasurementImportTools::importWellMeasurementsFromFiles( const QStri wellMeasurement->setValue( 0.0 ); } - wellPathCollection->measurementCollection()->appendMeasurement( wellMeasurement ); + wellPathCollection->measurementCollection()->addItem( wellMeasurement ); + wellPathCollection->measurementCollection()->addFilePath( wellMeasurement->filePath() ); lastWellMeasurement = wellMeasurement; } + wellPathCollection->measurementCollection()->updateAllCurves(); wellPathCollection->uiCapability()->updateConnectedEditors(); auto proj = RimProject::current(); diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index e9f42e01bcc..8a79144f190 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -1,4 +1,6 @@ set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimPdmObjectCollection.h + ${CMAKE_CURRENT_LIST_DIR}/RimPdmObjectCollection.inl ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimCaseCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimLegendConfigChangeType.h diff --git a/ApplicationLibCode/ProjectDataModel/Completions/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Completions/CMakeLists_files.cmake index ce8cc292d13..7fe976d6686 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/Completions/CMakeLists_files.cmake @@ -1,4 +1,6 @@ set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimIntervalCollection.h + ${CMAKE_CURRENT_LIST_DIR}/RimIntervalCollection.inl ${CMAKE_CURRENT_LIST_DIR}/RimCompletionCellIntersectionCalc.h ${CMAKE_CURRENT_LIST_DIR}/RimFishbonesCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimFishbones.h diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.cpp index f8d2f3aef6d..72bf460b8d7 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.cpp @@ -18,14 +18,7 @@ #include "RimCustomSegmentIntervalCollection.h" -#include "RiaLogging.h" -#include "RimCustomSegmentInterval.h" - #include "cafCmdFeatureMenuBuilder.h" -#include "cafPdmUiTableViewEditor.h" - -#include -#include CAF_PDM_SOURCE_INIT( RimCustomSegmentIntervalCollection, "CustomSegmentIntervalCollection" ); @@ -35,8 +28,7 @@ CAF_PDM_SOURCE_INIT( RimCustomSegmentIntervalCollection, "CustomSegmentIntervalC RimCustomSegmentIntervalCollection::RimCustomSegmentIntervalCollection() { CAF_PDM_InitObject( "Custom Segment Intervals", ":/WellPathComponent16x16.png" ); - - CAF_PDM_InitFieldNoDefault( &m_intervals, "Intervals", "Intervals" ); + CAF_PDM_InitFieldNoDefault( &m_items, "Intervals", "Intervals" ); } //-------------------------------------------------------------------------------------------------- @@ -46,124 +38,6 @@ RimCustomSegmentIntervalCollection::~RimCustomSegmentIntervalCollection() { } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimCustomSegmentIntervalCollection::intervals() const -{ - return m_intervals.childrenByType(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::addInterval( RimCustomSegmentInterval* interval ) -{ - if ( interval ) - { - m_intervals.push_back( interval ); - sortIntervalsByMD(); - updateConnectedEditors(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::removeInterval( RimCustomSegmentInterval* interval ) -{ - if ( interval ) - { - m_intervals.removeChild( interval ); - delete interval; - updateConnectedEditors(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::removeAllIntervals() -{ - m_intervals.deleteChildren(); - updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimCustomSegmentInterval* RimCustomSegmentIntervalCollection::createInterval( double startMD, double endMD ) -{ - auto* interval = new RimCustomSegmentInterval(); - interval->setStartMD( startMD ); - interval->setEndMD( endMD ); - - addInterval( interval ); - return interval; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimCustomSegmentInterval* RimCustomSegmentIntervalCollection::createDefaultInterval() -{ - auto* interval = new RimCustomSegmentInterval(); - addInterval( interval ); - return interval; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimCustomSegmentInterval* RimCustomSegmentIntervalCollection::findIntervalAtMD( double md ) const -{ - for ( auto* interval : intervals() ) - { - if ( interval && interval->containsMD( md ) ) - { - return interval; - } - } - return nullptr; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimCustomSegmentIntervalCollection::hasValidIntervals() const -{ - if ( isEmpty() ) return false; - - for ( auto* interval : intervals() ) - { - if ( !interval || !interval->isValidInterval() ) - { - return false; - } - } - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimCustomSegmentIntervalCollection::hasOverlappingIntervals() const -{ - auto intervalList = intervals(); - - for ( size_t i = 0; i < intervalList.size(); ++i ) - { - for ( size_t j = i + 1; j < intervalList.size(); ++j ) - { - if ( intervalList[i]->overlaps( intervalList[j] ) ) - { - return true; - } - } - } - return false; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -213,142 +87,6 @@ std::map RimCustomSegmentIntervalCollection::validate( const Q return errors; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::sortIntervalsByMD() -{ - auto intervalList = intervals(); - std::sort( intervalList.begin(), - intervalList.end(), - []( const RimCustomSegmentInterval* a, const RimCustomSegmentInterval* b ) { return *a < *b; } ); - - // Rebuild the collection in sorted order - m_intervals.clearWithoutDelete(); - for ( auto* interval : intervalList ) - { - m_intervals.push_back( interval ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimCustomSegmentIntervalCollection::isEmpty() const -{ - return m_intervals.empty(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RimCustomSegmentIntervalCollection::count() const -{ - return m_intervals.size(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::updateConnectedEditors() -{ - m_intervals.uiCapability()->updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmChildArrayField& RimCustomSegmentIntervalCollection::intervalsField() -{ - return m_intervals; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::updateOverlapVisualFeedback() -{ - auto intervalList = intervals(); - - // First, reset all intervals to no overlap - for ( auto* interval : intervalList ) - { - interval->updateOverlapVisualFeedback( false ); - } - - // Then check for overlaps and update visual feedback - for ( size_t i = 0; i < intervalList.size(); ++i ) - { - bool hasOverlap = false; - - for ( size_t j = 0; j < intervalList.size(); ++j ) - { - if ( i != j && intervalList[i]->overlaps( intervalList[j] ) ) - { - hasOverlap = true; - break; - } - } - - if ( hasOverlap ) - { - intervalList[i]->updateOverlapVisualFeedback( true ); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, - const QVariant& oldValue, - const QVariant& newValue ) -{ - if ( changedField == &m_intervals ) - { - sortIntervalsByMD(); - updateOverlapVisualFeedback(); - } - - updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) -{ - uiOrdering.add( &m_intervals ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::defineEditorAttribute( const caf::PdmFieldHandle* field, - QString uiConfigName, - caf::PdmUiEditorAttribute* attribute ) -{ - if ( field == &m_intervals ) - { - auto tvAttribute = dynamic_cast( attribute ); - if ( tvAttribute ) - { - tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER; - tvAttribute->alwaysEnforceResizePolicy = true; - tvAttribute->minimumHeight = 300; - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, - std::vector& referringObjects ) -{ - updateConnectedEditors(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -364,20 +102,3 @@ void RimCustomSegmentIntervalCollection::defineCustomContextMenu( const caf::Pdm menuBuilder.appendToMenu( menu ); } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimCustomSegmentIntervalCollection::insertInterval( RimCustomSegmentInterval* insertBefore, RimCustomSegmentInterval* interval ) -{ - if ( !interval ) return; - - size_t index = m_intervals.indexOf( insertBefore ); - if ( index < m_intervals.size() ) - m_intervals.insert( index, interval ); - else - m_intervals.push_back( interval ); - - sortIntervalsByMD(); - updateConnectedEditors(); -} diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.h b/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.h index bbbfe8727bc..8de7a976d2a 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimCustomSegmentIntervalCollection.h @@ -17,21 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once -#include "RiaDefines.h" - -#include "cafPdmChildArrayField.h" -#include "cafPdmObject.h" - -#include - -class RimCustomSegmentInterval; +#include "RimCustomSegmentInterval.h" +#include "RimIntervalCollection.h" //================================================================================================== /// /// Collection to manage custom segment intervals for measured depth ranges /// //================================================================================================== -class RimCustomSegmentIntervalCollection : public caf::PdmObject +class RimCustomSegmentIntervalCollection : public RimIntervalCollection { CAF_PDM_HEADER_INIT; @@ -39,47 +33,9 @@ class RimCustomSegmentIntervalCollection : public caf::PdmObject RimCustomSegmentIntervalCollection(); ~RimCustomSegmentIntervalCollection() override; - // Collection management - std::vector intervals() const; - void addInterval( RimCustomSegmentInterval* interval ); - void insertInterval( RimCustomSegmentInterval* insertBefore, RimCustomSegmentInterval* interval ); - void removeInterval( RimCustomSegmentInterval* interval ); - void removeAllIntervals(); - - // Interval creation - RimCustomSegmentInterval* createInterval( double startMD, double endMD ); - RimCustomSegmentInterval* createDefaultInterval(); - - // Lookup methods - RimCustomSegmentInterval* findIntervalAtMD( double md ) const; - // Validation std::map validate( const QString& configName = "" ) const override; - bool hasValidIntervals() const; - bool hasOverlappingIntervals() const; - - // Sorting and organization - void sortIntervalsByMD(); - - // Utility - bool isEmpty() const; - size_t count() const; - void updateConnectedEditors(); - - // Accessor for UI integration - caf::PdmChildArrayField& intervalsField(); - - // Visual feedback for overlapping intervals - void updateOverlapVisualFeedback(); protected: - void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; - void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override; - void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; - -private: - void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) override; - - caf::PdmChildArrayField m_intervals; }; diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.cpp index 08278c0da3b..b7ab7d72833 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.cpp @@ -18,12 +18,10 @@ #include "RimDiameterRoughnessIntervalCollection.h" -#include "RiaLogging.h" #include "RimDiameterRoughnessInterval.h" #include "RimMswCompletionParameters.h" #include "cafCmdFeatureMenuBuilder.h" -#include "cafPdmUiTableViewEditor.h" #include #include @@ -36,8 +34,7 @@ CAF_PDM_SOURCE_INIT( RimDiameterRoughnessIntervalCollection, "DiameterRoughnessI RimDiameterRoughnessIntervalCollection::RimDiameterRoughnessIntervalCollection() { CAF_PDM_InitObject( "Diameter Roughness Intervals", ":/WellPathComponent16x16.png" ); - - CAF_PDM_InitFieldNoDefault( &m_intervals, "Intervals", "Intervals" ); + CAF_PDM_InitFieldNoDefault( &m_items, "Intervals", "Intervals" ); } //-------------------------------------------------------------------------------------------------- @@ -47,49 +44,6 @@ RimDiameterRoughnessIntervalCollection::~RimDiameterRoughnessIntervalCollection( { } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimDiameterRoughnessIntervalCollection::intervals() const -{ - return m_intervals.childrenByType(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::addInterval( RimDiameterRoughnessInterval* interval ) -{ - if ( interval ) - { - m_intervals.push_back( interval ); - sortIntervalsByMD(); - updateConnectedEditors(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::removeInterval( RimDiameterRoughnessInterval* interval ) -{ - if ( interval ) - { - m_intervals.removeChild( interval ); - delete interval; - updateConnectedEditors(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::removeAllIntervals() -{ - m_intervals.deleteChildren(); - updateConnectedEditors(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -106,16 +60,6 @@ RimDiameterRoughnessInterval* return interval; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimDiameterRoughnessInterval* RimDiameterRoughnessIntervalCollection::createDefaultInterval() -{ - auto* interval = new RimDiameterRoughnessInterval(); - addInterval( interval ); - return interval; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -146,58 +90,6 @@ double RimDiameterRoughnessIntervalCollection::getRoughnessAtMD( double md, RiaD return RimMswCompletionParameters::defaultRoughnessFactor( unitSystem ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimDiameterRoughnessInterval* RimDiameterRoughnessIntervalCollection::findIntervalAtMD( double md ) const -{ - for ( auto* interval : intervals() ) - { - if ( interval && interval->containsMD( md ) ) - { - return interval; - } - } - return nullptr; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimDiameterRoughnessIntervalCollection::hasValidIntervals() const -{ - if ( isEmpty() ) return false; - - for ( auto* interval : intervals() ) - { - if ( !interval || !interval->isValidInterval() ) - { - return false; - } - } - return true; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimDiameterRoughnessIntervalCollection::hasOverlappingIntervals() const -{ - auto intervalList = intervals(); - - for ( size_t i = 0; i < intervalList.size(); ++i ) - { - for ( size_t j = i + 1; j < intervalList.size(); ++j ) - { - if ( intervalList[i]->overlaps( intervalList[j] ) ) - { - return true; - } - } - } - return false; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -223,67 +115,6 @@ bool RimDiameterRoughnessIntervalCollection::coversFullRange( double startMD, do return currentPos >= endMD - 1e-6; // Allow small tolerance } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimDiameterRoughnessIntervalCollection::validateIntervals() const -{ - std::vector issues; - - if ( isEmpty() ) - { - issues.push_back( "No intervals defined" ); - return issues; - } - - auto intervalList = intervals(); - - // Check for invalid intervals - for ( auto* interval : intervalList ) - { - if ( !interval->isValidInterval() ) - { - issues.push_back( QString( "Invalid interval: MD %.1f-%.1f" ).arg( interval->startMD() ).arg( interval->endMD() ) ); - } - } - - // Check for overlaps - for ( size_t i = 0; i < intervalList.size(); ++i ) - { - for ( size_t j = i + 1; j < intervalList.size(); ++j ) - { - if ( intervalList[i]->overlaps( intervalList[j] ) ) - { - issues.push_back( QString( "Overlapping intervals: MD %.1f-%.1f and MD %.1f-%.1f" ) - .arg( intervalList[i]->startMD() ) - .arg( intervalList[i]->endMD() ) - .arg( intervalList[j]->startMD() ) - .arg( intervalList[j]->endMD() ) ); - } - } - } - - return issues; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::sortIntervalsByMD() -{ - auto intervalList = intervals(); - std::sort( intervalList.begin(), - intervalList.end(), - []( const RimDiameterRoughnessInterval* a, const RimDiameterRoughnessInterval* b ) { return *a < *b; } ); - - // Rebuild the collection in sorted order - m_intervals.clearWithoutDelete(); - for ( auto* interval : intervalList ) - { - m_intervals.push_back( interval ); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -320,131 +151,13 @@ void RimDiameterRoughnessIntervalCollection::mergeAdjacentIntervals() } // Rebuild collection with merged intervals - m_intervals.clearWithoutDelete(); + this->m_items.clearWithoutDelete(); for ( auto* interval : mergedIntervals ) { - m_intervals.push_back( interval ); + this->m_items.push_back( interval ); } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimDiameterRoughnessIntervalCollection::isEmpty() const -{ - return m_intervals.empty(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RimDiameterRoughnessIntervalCollection::count() const -{ - return m_intervals.size(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::updateConnectedEditors() -{ - m_intervals.uiCapability()->updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmChildArrayField& RimDiameterRoughnessIntervalCollection::intervalsField() -{ - return m_intervals; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::updateOverlapVisualFeedback() -{ - auto intervalList = intervals(); - - // First, reset all intervals to no overlap - for ( auto* interval : intervalList ) - { - interval->updateOverlapVisualFeedback( false ); - } - - // Then check for overlaps and update visual feedback - for ( size_t i = 0; i < intervalList.size(); ++i ) - { - bool hasOverlap = false; - - for ( size_t j = 0; j < intervalList.size(); ++j ) - { - if ( i != j && intervalList[i]->overlaps( intervalList[j] ) ) - { - hasOverlap = true; - break; - } - } - - if ( hasOverlap ) - { - intervalList[i]->updateOverlapVisualFeedback( true ); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, - const QVariant& oldValue, - const QVariant& newValue ) -{ - if ( changedField == &m_intervals ) - { - sortIntervalsByMD(); - updateOverlapVisualFeedback(); - } - - updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) -{ - uiOrdering.add( &m_intervals ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::defineEditorAttribute( const caf::PdmFieldHandle* field, - QString uiConfigName, - caf::PdmUiEditorAttribute* attribute ) -{ - if ( field == &m_intervals ) - { - auto tvAttribute = dynamic_cast( attribute ); - if ( tvAttribute ) - { - tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER; - tvAttribute->alwaysEnforceResizePolicy = true; - tvAttribute->minimumHeight = 300; - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, - std::vector& referringObjects ) -{ - updateConnectedEditors(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -460,20 +173,3 @@ void RimDiameterRoughnessIntervalCollection::defineCustomContextMenu( const caf: menuBuilder.appendToMenu( menu ); } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimDiameterRoughnessIntervalCollection::insertInterval( RimDiameterRoughnessInterval* insertBefore, RimDiameterRoughnessInterval* interval ) -{ - if ( !interval ) return; - - size_t index = m_intervals.indexOf( insertBefore ); - if ( index < m_intervals.size() ) - m_intervals.insert( index, interval ); - else - m_intervals.push_back( interval ); - - sortIntervalsByMD(); - updateConnectedEditors(); -} diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.h b/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.h index 220a44ae439..2158476e146 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimDiameterRoughnessIntervalCollection.h @@ -18,20 +18,15 @@ #pragma once #include "RiaDefines.h" - -#include "cafPdmChildArrayField.h" -#include "cafPdmObject.h" - -#include - -class RimDiameterRoughnessInterval; +#include "RimDiameterRoughnessInterval.h" +#include "RimIntervalCollection.h" //================================================================================================== /// /// Collection to manage diameter and roughness intervals for measured depth ranges /// //================================================================================================== -class RimDiameterRoughnessIntervalCollection : public caf::PdmObject +class RimDiameterRoughnessIntervalCollection : public RimIntervalCollection { CAF_PDM_HEADER_INIT; @@ -39,51 +34,19 @@ class RimDiameterRoughnessIntervalCollection : public caf::PdmObject RimDiameterRoughnessIntervalCollection(); ~RimDiameterRoughnessIntervalCollection() override; - // Collection management - std::vector intervals() const; - void addInterval( RimDiameterRoughnessInterval* interval ); - void insertInterval( RimDiameterRoughnessInterval* insertBefore, RimDiameterRoughnessInterval* interval ); - void removeInterval( RimDiameterRoughnessInterval* interval ); - void removeAllIntervals(); - - // Interval creation + // Domain-specific interval creation RimDiameterRoughnessInterval* createInterval( double startMD, double endMD, double diameter, double roughness ); - RimDiameterRoughnessInterval* createDefaultInterval(); - // Lookup methods - double getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const; - double getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const; - RimDiameterRoughnessInterval* findIntervalAtMD( double md ) const; + // Domain-specific lookup methods + double getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const; + double getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const; - // Validation - bool hasValidIntervals() const; - bool hasOverlappingIntervals() const; - bool coversFullRange( double startMD, double endMD ) const; - std::vector validateIntervals() const; + // Domain-specific validation + bool coversFullRange( double startMD, double endMD ) const; - // Sorting and organization - void sortIntervalsByMD(); + // Domain-specific organization void mergeAdjacentIntervals(); - // Utility - bool isEmpty() const; - size_t count() const; - void updateConnectedEditors(); - - // Accessor for UI integration - caf::PdmChildArrayField& intervalsField(); - - // Visual feedback for overlapping intervals - void updateOverlapVisualFeedback(); - protected: - void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; - void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override; - void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; - -private: - void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) override; - - caf::PdmChildArrayField m_intervals; }; diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimIntervalCollection.h b/ApplicationLibCode/ProjectDataModel/Completions/RimIntervalCollection.h new file mode 100644 index 00000000000..855c58e9bd3 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimIntervalCollection.h @@ -0,0 +1,78 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmObjectCollection.h" + +#include +#include + +//================================================================================================== +/// +/// Interval-specific templated collection base class +/// +/// Extends RimPdmObjectCollection with interval-specific operations for objects that have +/// measured depth (MD) ranges. Provides sorting, overlap detection, and validation. +/// +/// Template parameter: +/// - IntervalType: Must inherit from caf::PdmObject and provide interval methods +/// +/// IntervalType must provide: startMD(), endMD(), containsMD(double), overlaps(const IntervalType*), +/// isValidInterval(), updateOverlapVisualFeedback(bool), operator< +/// +/// Derived classes must call the base constructor with field name and display name. +/// +//================================================================================================== +template +class RimIntervalCollection : public caf::PdmObjectCollection +{ +public: + // Interval-specific lookup + IntervalType* findIntervalAtMD( double md ) const; + + // Validation + bool hasValidIntervals() const; + bool hasOverlappingIntervals() const; + std::vector validateIntervals() const; + + // Organization + void sortIntervalsByMD(); + void updateOverlapVisualFeedback(); + + // Convenience accessors (delegate to base class) + std::vector intervals() const; + void addInterval( IntervalType* interval ); + void removeInterval( IntervalType* interval ); + void removeAllIntervals(); + IntervalType* createDefaultInterval(); + caf::PdmChildArrayField& intervalsField(); + const caf::PdmChildArrayField& intervalsField() const; + +protected: + // Constructor (protected - only derived classes can instantiate) + // Derived classes MUST initialize m_items field using CAF_PDM_InitFieldNoDefault + RimIntervalCollection(); + ~RimIntervalCollection() override; + + // Override to automatically sort and update visual feedback when items change + void onItemsChanged() override; +}; + +// Include template implementation +#include "RimIntervalCollection.inl" diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimIntervalCollection.inl b/ApplicationLibCode/ProjectDataModel/Completions/RimIntervalCollection.inl new file mode 100644 index 00000000000..4f1008586ea --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimIntervalCollection.inl @@ -0,0 +1,243 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 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 + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RimIntervalCollection::RimIntervalCollection() +{ + // m_items field must be initialized by derived class using CAF_PDM_InitFieldNoDefault +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +RimIntervalCollection::~RimIntervalCollection() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +IntervalType* RimIntervalCollection::findIntervalAtMD( double md ) const +{ + for ( auto* interval : intervals() ) + { + if ( interval && interval->containsMD( md ) ) + { + return interval; + } + } + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +bool RimIntervalCollection::hasValidIntervals() const +{ + if ( this->isEmpty() ) return false; + + for ( auto* interval : intervals() ) + { + if ( !interval || !interval->isValidInterval() ) + { + return false; + } + } + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +bool RimIntervalCollection::hasOverlappingIntervals() const +{ + auto intervalList = intervals(); + + for ( size_t i = 0; i < intervalList.size(); ++i ) + { + for ( size_t j = i + 1; j < intervalList.size(); ++j ) + { + if ( intervalList[i]->overlaps( intervalList[j] ) ) + { + return true; + } + } + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +std::vector RimIntervalCollection::validateIntervals() const +{ + std::vector issues; + + if ( this->isEmpty() ) + { + issues.push_back( "No intervals defined" ); + return issues; + } + + auto intervalList = intervals(); + + // Check for invalid intervals + for ( auto* interval : intervalList ) + { + if ( !interval->isValidInterval() ) + { + issues.push_back( + QString( "Invalid interval: MD %.1f-%.1f (Start MD must be less than End MD)" ).arg( interval->startMD() ).arg( interval->endMD() ) ); + } + } + + // Check for overlaps + for ( size_t i = 0; i < intervalList.size(); ++i ) + { + for ( size_t j = i + 1; j < intervalList.size(); ++j ) + { + if ( intervalList[i]->overlaps( intervalList[j] ) ) + { + issues.push_back( QString( "Overlapping intervals: MD %.1f-%.1f and MD %.1f-%.1f" ) + .arg( intervalList[i]->startMD() ) + .arg( intervalList[i]->endMD() ) + .arg( intervalList[j]->startMD() ) + .arg( intervalList[j]->endMD() ) ); + } + } + } + + return issues; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RimIntervalCollection::sortIntervalsByMD() +{ + auto intervalList = intervals(); + std::sort( intervalList.begin(), intervalList.end(), []( const IntervalType* a, const IntervalType* b ) { return *a < *b; } ); + + // Rebuild the collection in sorted order + this->m_items.clearWithoutDelete(); + for ( auto* interval : intervalList ) + { + this->m_items.push_back( interval ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RimIntervalCollection::updateOverlapVisualFeedback() +{ + auto intervalList = intervals(); + + // First, reset all intervals to no overlap + for ( auto* interval : intervalList ) + { + interval->updateOverlapVisualFeedback( false ); + } + + // Then check for overlaps and update visual feedback + for ( size_t i = 0; i < intervalList.size(); ++i ) + { + bool hasOverlap = false; + + for ( size_t j = 0; j < intervalList.size(); ++j ) + { + if ( i != j && intervalList[i]->overlaps( intervalList[j] ) ) + { + hasOverlap = true; + break; + } + } + + if ( hasOverlap ) + { + intervalList[i]->updateOverlapVisualFeedback( true ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void RimIntervalCollection::onItemsChanged() +{ + sortIntervalsByMD(); + updateOverlapVisualFeedback(); +} + +//-------------------------------------------------------------------------------------------------- +/// Convenience accessors (delegate to base class) +//-------------------------------------------------------------------------------------------------- +template +std::vector RimIntervalCollection::intervals() const +{ + return this->items(); +} + +template +void RimIntervalCollection::addInterval( IntervalType* interval ) +{ + this->addItem( interval ); +} + +template +void RimIntervalCollection::removeInterval( IntervalType* interval ) +{ + this->deleteItem( interval ); +} + +template +void RimIntervalCollection::removeAllIntervals() +{ + this->deleteAllItems(); +} + +template +IntervalType* RimIntervalCollection::createDefaultInterval() +{ + return this->createDefaultItem(); +} + +template +caf::PdmChildArrayField& RimIntervalCollection::intervalsField() +{ + return this->itemsField(); +} + +template +const caf::PdmChildArrayField& RimIntervalCollection::intervalsField() const +{ + return this->itemsField(); +} diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.cpp index df77919458a..eb65aefbca4 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.cpp @@ -32,7 +32,7 @@ CAF_PDM_SOURCE_INIT( RimValveTemplateCollection, "ValveTemplateCollection" ); RimValveTemplateCollection::RimValveTemplateCollection() { CAF_PDM_InitScriptableObject( "Valve Templates", ":/ICDValve16x16.png" ); - CAF_PDM_InitScriptableFieldNoDefault( &m_valveDefinitions, "ValveDefinitions", "" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_items, "ValveDefinitions", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_defaultUnitsForValveTemplates, "ValveUnits", "Default unit system for valve templates" ); m_defaultUnitsForValveTemplates = RiaDefines::EclipseUnitSystem::UNITS_METRIC; addDefaultValveTemplates(); @@ -45,36 +45,6 @@ RimValveTemplateCollection::~RimValveTemplateCollection() { } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimValveTemplateCollection::valveTemplates() const -{ - std::vector templates; - for ( auto& templ : m_valveDefinitions ) - { - templates.push_back( templ ); - } - return templates; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimValveTemplateCollection::addValveTemplate( RimValveTemplate* valveTemplate ) -{ - m_valveDefinitions.push_back( valveTemplate ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimValveTemplateCollection::removeAndDeleteValveTemplate( RimValveTemplate* valveTemplate ) -{ - m_valveDefinitions.removeChild( valveTemplate ); - delete valveTemplate; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -114,7 +84,7 @@ void RimValveTemplateCollection::addDefaultValveTemplates() icv->setType( RiaDefines::WellPathComponentType::ICV ); icv->setUserLabel( "Valve Template #3" ); - addValveTemplate( aicd ); - addValveTemplate( icd ); - addValveTemplate( icv ); + addItem( aicd ); + addItem( icd ); + addItem( icv ); } diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.h b/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.h index d6befa52474..c94144c23c1 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimValveTemplateCollection.h @@ -20,17 +20,16 @@ #include "RiaDefines.h" -#include "cafPdmChildArrayField.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" +#include "RimValveTemplate.h" -class RimValveTemplate; +#include "cafPdmField.h" +#include "cafPdmObjectCollection.h" //================================================================================================== /// /// //================================================================================================== -class RimValveTemplateCollection : public caf::PdmObject +class RimValveTemplateCollection : public caf::PdmObjectCollection { CAF_PDM_HEADER_INIT; @@ -38,15 +37,12 @@ class RimValveTemplateCollection : public caf::PdmObject RimValveTemplateCollection(); ~RimValveTemplateCollection() override; - std::vector valveTemplates() const; - void addValveTemplate( RimValveTemplate* valveTemplate ); - void removeAndDeleteValveTemplate( RimValveTemplate* valveTemplate ); - void addDefaultValveTemplates(); + // Domain-specific methods + void addDefaultValveTemplates(); caf::AppEnum defaultUnitSystemType() const; void setDefaultUnitSystemBasedOnLoadedCases(); private: - caf::PdmChildArrayField m_valveDefinitions; caf::PdmField> m_defaultUnitsForValveTemplates; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimProject.cpp b/ApplicationLibCode/ProjectDataModel/RimProject.cpp index 043bcfe6011..b1d14f032d3 100644 --- a/ApplicationLibCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimProject.cpp @@ -1301,7 +1301,7 @@ std::vector RimProject::allValveTemplates() const std::vector templates; for ( RimValveTemplateCollection* templColl : allValveTemplateCollections() ) { - for ( RimValveTemplate* templ : templColl->valveTemplates() ) + for ( RimValveTemplate* templ : templColl->items() ) { templates.push_back( templ ); } diff --git a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.cpp b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.cpp index 016bda07b71..283be4d4303 100644 --- a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.cpp @@ -34,29 +34,7 @@ RimElasticPropertyScalingCollection::RimElasticPropertyScalingCollection() { CAF_PDM_InitScriptableObject( "Elastic Property Scalings" ); - CAF_PDM_InitScriptableFieldNoDefault( &m_elasticPropertyScalings, "ElasticPropertyScalings", "Elastic Property Scalings" ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimElasticPropertyScalingCollection::elasticPropertyScalings() const -{ - std::vector templates; - for ( auto& templ : m_elasticPropertyScalings ) - { - templates.push_back( templ ); - } - return templates; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimElasticPropertyScalingCollection::addElasticPropertyScaling( RimElasticPropertyScaling* scaling ) -{ - scaling->changed.connect( this, &RimElasticPropertyScalingCollection::elasticPropertyScalingChanged ); - m_elasticPropertyScalings.push_back( scaling ); + CAF_PDM_InitScriptableFieldNoDefault( &m_items, "ElasticPropertyScalings", "Elastic Property Scalings" ); } //-------------------------------------------------------------------------------------------------- @@ -70,9 +48,9 @@ void RimElasticPropertyScalingCollection::elasticPropertyScalingChanged( const c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimElasticPropertyScalingCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, - std::vector& referringObjects ) +void RimElasticPropertyScalingCollection::onItemsChanged() { + connectSignals(); changed.send(); } @@ -83,7 +61,7 @@ double RimElasticPropertyScalingCollection::getScaling( const QString& const QString& faciesName, RiaDefines::CurveProperty property ) const { - for ( const RimElasticPropertyScaling* scaling : m_elasticPropertyScalings ) + for ( const RimElasticPropertyScaling* scaling : items() ) { if ( scaling->property() == property && ( scaling->formation().compare( formationName, Qt::CaseInsensitive ) == 0 ) && ( scaling->facies().compare( faciesName, Qt::CaseInsensitive ) == 0 ) && scaling->isChecked() ) @@ -101,7 +79,15 @@ double RimElasticPropertyScalingCollection::getScaling( const QString& //-------------------------------------------------------------------------------------------------- void RimElasticPropertyScalingCollection::initAfterRead() { - for ( auto& scaling : m_elasticPropertyScalings ) + connectSignals(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimElasticPropertyScalingCollection::connectSignals() +{ + for ( auto& scaling : items() ) { scaling->changed.connect( this, &RimElasticPropertyScalingCollection::elasticPropertyScalingChanged ); } diff --git a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.h b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.h index 87cbb1bcb82..97db77fa50b 100644 --- a/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.h +++ b/ApplicationLibCode/ProjectDataModel/StimPlanModel/RimElasticPropertyScalingCollection.h @@ -18,19 +18,17 @@ #pragma once -#include "cafPdmChildArrayField.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" - #include "RiaStimPlanModelDefines.h" -class RimElasticPropertyScaling; +#include "RimElasticPropertyScaling.h" + +#include "cafPdmObjectCollection.h" //================================================================================================== /// /// //================================================================================================== -class RimElasticPropertyScalingCollection : public caf::PdmObject +class RimElasticPropertyScalingCollection : public caf::PdmObjectCollection { CAF_PDM_HEADER_INIT; @@ -39,17 +37,14 @@ class RimElasticPropertyScalingCollection : public caf::PdmObject caf::Signal<> changed; - std::vector elasticPropertyScalings() const; - void addElasticPropertyScaling( RimElasticPropertyScaling* templ ); - - void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) override; - + // Domain-specific methods double getScaling( const QString& formationName, const QString& faciesName, RiaDefines::CurveProperty property ) const; protected: void initAfterRead() override; + void onItemsChanged() override; private: - void elasticPropertyScalingChanged( const caf::SignalEmitter* emitter ); - caf::PdmChildArrayField m_elasticPropertyScalings; + void connectSignals(); + void elasticPropertyScalingChanged( const caf::SignalEmitter* emitter ); }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.cpp index af063c553a2..3c5c725ce7e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.cpp @@ -33,8 +33,8 @@ RimSummaryTableCollection::RimSummaryTableCollection() { CAF_PDM_InitObject( "Summary Tables", ":/CorrelationMatrixPlot16x16.png" ); - CAF_PDM_InitFieldNoDefault( &m_summaryTables, "SummaryTables", "Summary Tables" ); - caf::PdmFieldReorderCapability::addToField( &m_summaryTables ); + CAF_PDM_InitFieldNoDefault( &m_items, "SummaryTables", "Summary Tables" ); + caf::PdmFieldReorderCapability::addToField( &m_items ); } //-------------------------------------------------------------------------------------------------- @@ -49,7 +49,7 @@ RimSummaryTableCollection::~RimSummaryTableCollection() //-------------------------------------------------------------------------------------------------- void RimSummaryTableCollection::deleteAllPlots() { - m_summaryTables.deleteChildren(); + deleteAllItems(); } //-------------------------------------------------------------------------------------------------- @@ -57,7 +57,7 @@ void RimSummaryTableCollection::deleteAllPlots() //-------------------------------------------------------------------------------------------------- void RimSummaryTableCollection::loadDataAndUpdateAllPlots() { - for ( RimSummaryTable* table : m_summaryTables ) + for ( RimSummaryTable* table : items() ) { if ( !table ) continue; @@ -70,7 +70,7 @@ void RimSummaryTableCollection::loadDataAndUpdateAllPlots() //-------------------------------------------------------------------------------------------------- size_t RimSummaryTableCollection::plotCount() const { - return tableCount(); + return count(); } //-------------------------------------------------------------------------------------------------- @@ -78,28 +78,15 @@ size_t RimSummaryTableCollection::plotCount() const //-------------------------------------------------------------------------------------------------- std::vector RimSummaryTableCollection::tables() const { - return m_summaryTables.childrenByType(); + return items(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RimSummaryTableCollection::tableCount() const -{ - return m_summaryTables.size(); -} - void RimSummaryTableCollection::addTable( RimSummaryTable* table ) { - insertTable( table, tableCount() ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryTableCollection::insertTable( RimSummaryTable* table, size_t index ) -{ - m_summaryTables.insert( index, table ); + addItem( table ); } //-------------------------------------------------------------------------------------------------- @@ -107,8 +94,7 @@ void RimSummaryTableCollection::insertTable( RimSummaryTable* table, size_t inde //-------------------------------------------------------------------------------------------------- void RimSummaryTableCollection::removeTable( RimSummaryTable* table ) { - m_summaryTables.removeChild( table ); - updateAllRequiredEditors(); + deleteItem( table ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.h index eaaca4f85d7..0f1c77837d2 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryTableCollection.h @@ -23,16 +23,16 @@ #include "RimAbstractPlotCollection.h" #include "RimSummaryTable.h" -#include "cafPdmChildArrayField.h" -#include "cafPdmObject.h" +#include "cafPdmObjectCollection.h" class RimSummaryCase; //================================================================================================== /// +/// Collection for managing summary tables /// //================================================================================================== -class RimSummaryTableCollection : public caf::PdmObject, public RimPlotCollection +class RimSummaryTableCollection : public caf::PdmObjectCollection, public RimPlotCollection { CAF_PDM_HEADER_INIT; @@ -40,21 +40,19 @@ class RimSummaryTableCollection : public caf::PdmObject, public RimPlotCollectio RimSummaryTableCollection(); ~RimSummaryTableCollection() override; + // RimPlotCollection interface void deleteAllPlots() override; void loadDataAndUpdateAllPlots() override; size_t plotCount() const override; + // Convenience accessors (delegate to base class) std::vector tables() const; - size_t tableCount() const; void addTable( RimSummaryTable* table ); - void insertTable( RimSummaryTable* table, size_t index ); void removeTable( RimSummaryTable* table ); + // Domain-specific creation methods RimSummaryTable* createDefaultSummaryTable(); RimSummaryTable* createSummaryTableFromCategoryAndVectorName( RimSummaryCase* summaryCase, RifEclipseSummaryAddressDefines::SummaryCategory category, const QString& vectorName ); - -private: - caf::PdmChildArrayField m_summaryTables; }; diff --git a/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.cpp b/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.cpp index 47f4f8a4f64..fb07d69c355 100644 --- a/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.cpp @@ -39,9 +39,9 @@ RimWellMeasurementCollection::RimWellMeasurementCollection() { CAF_PDM_InitObject( "Well Measurements", ":/WellMeasurement16x16.png" ); - CAF_PDM_InitFieldNoDefault( &m_measurements, "Measurements", "Well Measurements" ); - m_measurements.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); - m_measurements.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + CAF_PDM_InitFieldNoDefault( &m_items, "Measurements", "Measurements" ); + this->itemsField().uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); + this->itemsField().uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); CAF_PDM_InitFieldNoDefault( &m_importedFiles, "ImportedFiles", "Imported Files" ); } @@ -53,6 +53,14 @@ RimWellMeasurementCollection::~RimWellMeasurementCollection() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellMeasurementCollection::measurements() const +{ + return this->items(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -93,101 +101,6 @@ void RimWellMeasurementCollection::deleteAllEmptyCurves() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimWellMeasurementCollection::measurements() const -{ - std::vector attrs; - - for ( auto attr : m_measurements ) - { - attrs.push_back( attr.p() ); - } - return attrs; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellMeasurementCollection::isEmpty() const -{ - return m_measurements.empty(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::insertMeasurement( RimWellMeasurement* insertBefore, RimWellMeasurement* measurement ) -{ - size_t index = m_measurements.indexOf( insertBefore ); - if ( index < m_measurements.size() ) - m_measurements.insert( index, measurement ); - else - m_measurements.push_back( measurement ); - - addFilePath( measurement->filePath() ); - updateAllCurves(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::appendMeasurement( RimWellMeasurement* measurement ) -{ - m_measurements.push_back( measurement ); - addFilePath( measurement->filePath() ); - updateAllCurves(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::deleteMeasurement( RimWellMeasurement* measurementToDelete ) -{ - m_measurements.removeChild( measurementToDelete ); - delete measurementToDelete; - - updateAllCurves(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::deleteAllMeasurements() -{ - m_measurements.deleteChildren(); - updateAllCurves(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::defineEditorAttribute( const caf::PdmFieldHandle* field, - QString uiConfigName, - caf::PdmUiEditorAttribute* attribute ) -{ - if ( field == &m_measurements ) - { - auto tvAttribute = dynamic_cast( attribute ); - if ( tvAttribute ) - { - tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER; - tvAttribute->alwaysEnforceResizePolicy = true; - tvAttribute->minimumHeight = 300; - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellMeasurementCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) -{ - uiOrdering.add( &m_measurements ); - uiOrdering.skipRemainingFields( true ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -244,19 +157,18 @@ void RimWellMeasurementCollection::removeMeasurementsForFilePath( RimWellMeasure { // Find all measurements for this file path std::vector measurementsToRemove; - for ( auto attr : m_measurements ) + for ( auto* measurement : this->items() ) { - if ( attr->filePath() == measurementFilePath->filePath() ) + if ( measurement->filePath() == measurementFilePath->filePath() ) { - measurementsToRemove.push_back( attr ); + measurementsToRemove.push_back( measurement ); } } - // Remove then remove them without invalidating the iterator - for ( unsigned int i = 0; i < measurementsToRemove.size(); i++ ) + // Remove them without invalidating the iterator + for ( auto* measurement : measurementsToRemove ) { - m_measurements.removeChild( measurementsToRemove[i] ); - delete measurementsToRemove[i]; + this->deleteItem( measurement ); } RimProject::current()->scheduleCreateDisplayModelAndRedrawAllViews(); diff --git a/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.h b/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.h index 2d24314290f..64b467100f2 100644 --- a/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.h +++ b/ApplicationLibCode/ProjectDataModel/WellMeasurement/RimWellMeasurementCollection.h @@ -17,18 +17,19 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once +#include "RimWellMeasurement.h" + #include "cafPdmChildArrayField.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" -#include "cafPdmProxyValueField.h" +#include "cafPdmObjectCollection.h" + +#include -class RimWellMeasurement; class RimWellMeasurementFilePath; //================================================================================================== /// //================================================================================================== -class RimWellMeasurementCollection : public caf::PdmObject +class RimWellMeasurementCollection : public caf::PdmObjectCollection { CAF_PDM_HEADER_INIT; @@ -36,15 +37,12 @@ class RimWellMeasurementCollection : public caf::PdmObject RimWellMeasurementCollection(); ~RimWellMeasurementCollection() override; + // Convenience accessor (delegates to base class items()) std::vector measurements() const; + // Domain-specific methods void updateAllCurves(); void deleteAllEmptyCurves(); - void insertMeasurement( RimWellMeasurement* insertBefore, RimWellMeasurement* measurement ); - void appendMeasurement( RimWellMeasurement* measurement ); - void deleteMeasurement( RimWellMeasurement* measurementToDelete ); - void deleteAllMeasurements(); - bool isEmpty() const; std::set importedFiles() const; @@ -53,11 +51,8 @@ class RimWellMeasurementCollection : public caf::PdmObject void removeMeasurementsForFilePath( RimWellMeasurementFilePath* measurementFilePath ); protected: - void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; - void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; private: - caf::PdmChildArrayField m_measurements; caf::PdmChildArrayField m_importedFiles; }; diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcElasticProperties.cpp b/ApplicationLibCode/ProjectDataModelCommands/RimcElasticProperties.cpp index 81837c5b4a3..0b9d4032485 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/RimcElasticProperties.cpp +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcElasticProperties.cpp @@ -59,7 +59,7 @@ std::expected RimcElasticProperties_addPropertyS property.setFromText( m_property() ); propertyScaling->setProperty( property ); - scalingColl->addElasticPropertyScaling( propertyScaling ); + scalingColl->addItem( propertyScaling ); scalingColl->updateConnectedEditors(); return propertyScaling; diff --git a/ApplicationLibCode/ProjectDataModelCommands/RimcValveTemplateCollection.cpp b/ApplicationLibCode/ProjectDataModelCommands/RimcValveTemplateCollection.cpp index f985ac86f08..95578606c1b 100644 --- a/ApplicationLibCode/ProjectDataModelCommands/RimcValveTemplateCollection.cpp +++ b/ApplicationLibCode/ProjectDataModelCommands/RimcValveTemplateCollection.cpp @@ -95,9 +95,8 @@ std::expected RimcValveTemplateCollection_add_te if ( userLabel.isEmpty() ) { // Generate default label based on type and count - auto templates = valveTemplateCollection->valveTemplates(); - int count = static_cast( templates.size() ) + 1; - userLabel = QString( "Template %1" ).arg( count ); + int count = static_cast( valveTemplateCollection->count() ) + 1; + userLabel = QString( "Template %1" ).arg( count ); } newTemplate->setUserLabel( userLabel ); @@ -110,7 +109,7 @@ std::expected RimcValveTemplateCollection_add_te newTemplate->setFlowCoefficient( m_flowCoefficient() ); // Add to collection - valveTemplateCollection->addValveTemplate( newTemplate ); + valveTemplateCollection->addItem( newTemplate ); valveTemplateCollection->updateAllRequiredEditors(); return newTemplate; diff --git a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt index 9586cb6cc08..49197adbe30 100644 --- a/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/CMakeLists.txt @@ -23,6 +23,8 @@ set(PROJECT_FILES cafPdmObjectGroup.h cafPdmObject.cpp cafPdmObject.h + cafPdmObjectCollection.h + cafPdmObjectCollection.inl ) add_library(${PROJECT_NAME} ${PROJECT_FILES}) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObjectCollection.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObjectCollection.h new file mode 100644 index 00000000000..b3c05956abe --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObjectCollection.h @@ -0,0 +1,92 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmChildArrayField.h" +#include "cafPdmObject.h" + +#include + +namespace caf +{ + +//================================================================================================== +/// +/// Generic templated collection base class for managing collections of PDM objects +/// +/// This template provides common collection operations (add, remove, insert, etc.) and UI +/// integration for any type of PDM object. Derived classes can add domain-specific functionality. +/// +/// Template parameter: +/// T - Item type, must inherit from caf::PdmObject +/// +/// Derived classes must call the base constructor with field name and display name. +/// +//================================================================================================== +template +class PdmObjectCollection : public PdmObject +{ + static_assert( std::is_base_of::value, "T must inherit from caf::PdmObject" ); + +public: + // Collection access + std::vector items() const; + size_t count() const; + bool isEmpty() const; + PdmChildArrayField& itemsField(); + const PdmChildArrayField& itemsField() const; + + // CRUD operations + void addItem( T* item ); + void insertItem( T* insertBefore, T* item ); + void deleteItem( T* item ); + void deleteAllItems(); + + // Creation helper + T* createDefaultItem(); + + // UI integration + void updateConnectedEditors(); + +protected: + // Constructor (protected - only derived classes can instantiate) + // Derived classes MUST initialize m_items field using CAF_PDM_InitFieldNoDefault + PdmObjectCollection(); + ~PdmObjectCollection() override; + + // Virtual hook for derived class customization + // Called when items are added, removed, or the collection is modified + virtual void onItemsChanged(); + + // PdmObject overrides + void fieldChangedByUi( const PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineUiOrdering( QString uiConfigName, PdmUiOrdering& uiOrdering ) override; + void defineEditorAttribute( const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute* attribute ) override; + + // Protected member - derived classes can access for advanced operations + PdmChildArrayField m_items; + +private: + void onChildDeleted( PdmChildArrayFieldHandle* childArray, std::vector& referringObjects ) override; +}; + +} // namespace caf + +// Include template implementation +#include "cafPdmObjectCollection.inl" diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObjectCollection.inl b/Fwk/AppFwk/cafProjectDataModel/cafPdmObjectCollection.inl new file mode 100644 index 00000000000..0a7c779b788 --- /dev/null +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObjectCollection.inl @@ -0,0 +1,230 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025 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 "cafPdmUiTableViewEditor.h" + +#include + +namespace caf +{ + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +PdmObjectCollection::PdmObjectCollection() +{ + // m_items field must be initialized by derived class using CAF_PDM_InitFieldNoDefault +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +PdmObjectCollection::~PdmObjectCollection() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +std::vector PdmObjectCollection::items() const +{ + return m_items.childrenByType(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +size_t PdmObjectCollection::count() const +{ + return m_items.size(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +bool PdmObjectCollection::isEmpty() const +{ + return m_items.empty(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +PdmChildArrayField& PdmObjectCollection::itemsField() +{ + return m_items; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +const PdmChildArrayField& PdmObjectCollection::itemsField() const +{ + return m_items; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::addItem( T* item ) +{ + if ( item ) + { + m_items.push_back( item ); + onItemsChanged(); + updateConnectedEditors(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::insertItem( T* insertBefore, T* item ) +{ + if ( !item ) return; + + size_t index = m_items.indexOf( insertBefore ); + if ( index < m_items.size() ) + m_items.insert( index, item ); + else + m_items.push_back( item ); + + onItemsChanged(); + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::deleteItem( T* item ) +{ + if ( item ) + { + m_items.removeChild( item ); + delete item; + updateConnectedEditors(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::deleteAllItems() +{ + m_items.deleteChildren(); + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +T* PdmObjectCollection::createDefaultItem() +{ + auto* item = new T(); + addItem( item ); + return item; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::updateConnectedEditors() +{ + uiCapability()->updateConnectedEditors(); + m_items.uiCapability()->updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::onItemsChanged() +{ + // Default implementation does nothing + // Derived classes can override to add custom behavior +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::fieldChangedByUi( const PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + if ( changedField == &m_items ) + { + onItemsChanged(); + } + + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::defineUiOrdering( QString uiConfigName, PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_items ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::defineEditorAttribute( const PdmFieldHandle* field, + QString uiConfigName, + PdmUiEditorAttribute* attribute ) +{ + if ( field == &m_items ) + { + auto tvAttribute = dynamic_cast( attribute ); + if ( tvAttribute ) + { + tvAttribute->resizePolicy = PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER; + tvAttribute->alwaysEnforceResizePolicy = true; + tvAttribute->minimumHeight = 300; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void PdmObjectCollection::onChildDeleted( PdmChildArrayFieldHandle* childArray, + std::vector& referringObjects ) +{ + updateConnectedEditors(); +} + +} // namespace caf