#13987 PDM: Migrate Surface and Polygon collections to PdmNestedCollection

Port RimSurfaceCollection, RimPolygonCollection and the polygon-in-view
side onto the new caf::PdmNestedCollection framework, replacing the
per-class folder plumbing (m_subCollections field, topmost-folder flag,
add/remove/find sub-collection, factory, "new folder" command) with the
shared base.

- RimSurfaceCollection and RimPolygonCollection now derive from
  caf::PdmNestedCollection. Each constructor uses the generic folder
  icon and exposes a static createTopmost() that marks the top instance
  and applies the branded domain icon; RimOilField calls the factory.
- RimPolygonInViewCollection uses the new RimNestedMirrorCollectionInView
  helper, and a new RimPolygonContainer carries the source-side polygon
  link.
- RicNewSurfaceCollectionFeature is removed; the generic
  RicNewNestedCollectionFeature drives the "Add Folder" action against
  both collections.
- Update callers (RimAnnotationCollection, RimEnsembleSurface, polygon
  command features) and the scripting wrapper (RimcSurfaceCollection),
  plus the Python add-folder binding and polygon test.
This commit is contained in:
Magne Sjaastad
2026-05-13 14:53:00 +02:00
parent 1e0ba3cdec
commit dc20a016f7
23 changed files with 356 additions and 526 deletions
@@ -28,6 +28,8 @@
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicCreatePolygonFeature, "RicCreatePolygonFeature" );
@@ -37,7 +39,13 @@ CAF_CMD_SOURCE_INIT( RicCreatePolygonFeature, "RicCreatePolygonFeature" );
//--------------------------------------------------------------------------------------------------
void RicCreatePolygonFeature::onActionTriggered( bool isChecked )
{
auto polygonCollection = RimTools::polygonCollection();
RimPolygonCollection* polygonCollection = nullptr;
auto selected = caf::selectedObjectsByTypeStrict<RimPolygonCollection*>();
if ( !selected.empty() ) polygonCollection = selected.front();
if ( !polygonCollection ) polygonCollection = RimTools::polygonCollection();
if ( !polygonCollection ) return;
auto newPolygon = polygonCollection->appendUserDefinedPolygon();
polygonCollection->uiCapability()->updateAllRequiredEditors();
@@ -29,6 +29,8 @@
#include "Riu3DMainWindowTools.h"
#include "RiuFileDialogTools.h"
#include "cafSelectionManagerTools.h"
#include <QAction>
#include <QFileInfo>
@@ -55,7 +57,13 @@ void RicImportPolygonFileFeature::onActionTriggered( bool isChecked )
// Remember the path to next time
app->setLastUsedDialogDirectory( RimPolygonTools::polygonCacheName(), QFileInfo( fileNames.last() ).absolutePath() );
auto polygonCollection = RimTools::polygonCollection();
RimPolygonCollection* polygonCollection = nullptr;
auto selected = caf::selectedObjectsByTypeStrict<RimPolygonCollection*>();
if ( !selected.empty() ) polygonCollection = selected.front();
if ( !polygonCollection ) polygonCollection = RimTools::polygonCollection();
if ( !polygonCollection ) return;
RimPolygon* objectToSelect = nullptr;
@@ -7,7 +7,6 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToTsurfFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToGriFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToGriUi.h
${CMAKE_CURRENT_LIST_DIR}/RicNewSurfaceCollectionFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewDepthSurfaceFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewRegularSurfaceFeature.h
)
@@ -21,7 +20,6 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToTsurfFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToGriFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportSurfaceToGriUi.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewSurfaceCollectionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewDepthSurfaceFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewRegularSurfaceFeature.cpp
)
@@ -1,33 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
//==================================================================================================
///
//==================================================================================================
class RicNewSurfaceCollectionFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};
@@ -108,7 +108,7 @@ void RimAnnotationCollection::initAfterRead()
if ( oldPoly == nullptr ) continue;
RimPolygonFile* newPoly = new RimPolygonFile();
newPoly->setName( oldPoly->uiName() );
newPoly->setCollectionName( oldPoly->uiName() );
newPoly->setFileName( oldPoly->fileName() );
@@ -1,5 +1,6 @@
set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimPolygon.h
${CMAKE_CURRENT_LIST_DIR}/RimPolygonContainer.h
${CMAKE_CURRENT_LIST_DIR}/RimPolygonFile.h
${CMAKE_CURRENT_LIST_DIR}/RimPolygonCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimPolygonInView.h
@@ -10,6 +11,7 @@ set(SOURCE_GROUP_HEADER_FILES
set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimPolygon.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPolygonContainer.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPolygonFile.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPolygonCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPolygonInView.cpp
@@ -37,10 +37,30 @@ CAF_PDM_SOURCE_INIT( RimPolygonCollection, "PolygonCollection", "RimPolygonColle
//--------------------------------------------------------------------------------------------------
RimPolygonCollection::RimPolygonCollection()
{
CAF_PDM_InitScriptableObject( "Polygons", ":/PolylinesFromFile16x16.png" );
CAF_PDM_InitScriptableObject( "Polygons", ":/Folder.png" );
CAF_PDM_InitScriptableFieldNoDefault( &m_polygons, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_polygonFiles, "PolygonFiles", "Polygon Files" );
CAF_PDM_InitScriptableFieldNoDefault( &m_collectionName, "PolygonCollectionName", "Name" );
m_collectionName = "Polygons";
CAF_PDM_InitScriptableFieldNoDefault( &m_subCollections, "SubCollections", "Subcollections" );
CAF_PDM_InitScriptableFieldNoDefault( &m_items, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_polygonFiles_OBSOLETE, "PolygonFiles", "Polygon Files" );
m_polygonFiles_OBSOLETE.uiCapability()->setUiHidden( true );
m_polygonFiles_OBSOLETE.xmlCapability()->setIOWritable( false );
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonCollection* RimPolygonCollection::createTopmost()
{
auto* coll = new RimPolygonCollection();
coll->setAsTopmostFolder();
coll->uiCapability()->setUiIconFromResourceString( ":/PolylinesFromFile16x16.png" );
return coll;
}
//--------------------------------------------------------------------------------------------------
@@ -48,9 +68,17 @@ RimPolygonCollection::RimPolygonCollection()
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::loadData()
{
for ( auto& p : m_polygonFiles() )
for ( auto* sub : subCollections() )
{
p->loadData();
if ( !sub ) continue;
if ( auto* file = dynamic_cast<RimPolygonFile*>( sub ) )
{
file->loadData();
}
else if ( auto* coll = dynamic_cast<RimPolygonCollection*>( sub ) )
{
coll->loadData();
}
}
}
@@ -60,10 +88,10 @@ void RimPolygonCollection::loadData()
RimPolygon* RimPolygonCollection::createUserDefinedPolygon()
{
auto newPolygon = new RimPolygon();
newPolygon->setName( "Polygon " + QString::number( userDefinedPolygons().size() + 1 ) );
newPolygon->setName( "Polygon " + QString::number( allPolygons().size() + 1 ) );
auto colorCandidates = RiaColorTables::summaryCurveDefaultPaletteColors();
newPolygon->setColor( colorCandidates.cycledColor3f( userDefinedPolygons().size() ) );
newPolygon->setColor( colorCandidates.cycledColor3f( allPolygons().size() ) );
return newPolygon;
}
@@ -84,7 +112,7 @@ RimPolygon* RimPolygonCollection::appendUserDefinedPolygon()
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::addUserDefinedPolygon( RimPolygon* polygon )
{
m_polygons().push_back( polygon );
m_items.push_back( polygon );
connectPolygonSignals( polygon );
@@ -97,7 +125,7 @@ void RimPolygonCollection::addUserDefinedPolygon( RimPolygon* polygon )
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::deleteUserDefinedPolygons()
{
m_polygons().deleteChildren();
m_items.deleteChildren();
updateViewTreeItems();
scheduleRedrawViews();
@@ -108,63 +136,33 @@ void RimPolygonCollection::deleteUserDefinedPolygons()
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::deleteAllPolygons()
{
m_polygons().deleteChildren();
m_polygonFiles().deleteChildren();
m_items.deleteChildren();
m_subCollections.deleteChildren();
updateViewTreeItems();
scheduleRedrawViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::addPolygonFile( RimPolygonFile* polygonFile )
{
m_polygonFiles().push_back( polygonFile );
connectPolygonFileSignals( polygonFile );
updateViewTreeItems();
scheduleRedrawViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygon*> RimPolygonCollection::userDefinedPolygons() const
{
return m_polygons.childrenByType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygonFile*> RimPolygonCollection::polygonFiles() const
{
return m_polygonFiles.childrenByType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygon*> RimPolygonCollection::allPolygons() const
{
std::vector<RimPolygon*> allPolygons;
return allItems();
}
for ( auto& p : m_polygonFiles() )
{
for ( auto& polygon : p->polygons() )
{
allPolygons.push_back( polygon );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::addPolygonFile( RimPolygonFile* polygonFile )
{
if ( !polygonFile ) return;
for ( auto& polygon : m_polygons.childrenByType() )
{
allPolygons.push_back( polygon );
}
addSubCollection( polygonFile );
connectPolygonFileSignals( polygonFile );
return allPolygons;
updateViewTreeItems();
scheduleRedrawViews();
}
//--------------------------------------------------------------------------------------------------
@@ -200,9 +198,21 @@ void RimPolygonCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuil
{
RimPolygonCollection::appendPolygonMenuItems( menuBuilder );
menuBuilder.addSeparator();
menuBuilder << "RicNewNestedCollectionFeature";
menuBuilder.addSeparator();
menuBuilder << "RicDeleteAllPolygonsFeature";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_collectionName );
uiOrdering.add( &m_subCollections );
uiOrdering.add( &m_items );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -268,15 +278,51 @@ void RimPolygonCollection::onPolygonFileChanged( const caf::SignalEmitter* emitt
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::initAfterRead()
void RimPolygonCollection::connectSignalsRecursively()
{
for ( auto& p : m_polygons() )
connectSignalsForContainer( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::connectSignalsForContainer( RimPolygonContainer* container )
{
if ( !container ) return;
for ( auto* polygon : container->items() )
{
connectPolygonSignals( p );
connectPolygonSignals( polygon );
}
for ( auto& pf : m_polygonFiles() )
for ( auto* sub : container->subCollections() )
{
connectPolygonFileSignals( pf );
if ( !sub ) continue;
if ( auto* file = dynamic_cast<RimPolygonFile*>( sub ) )
{
connectPolygonFileSignals( file );
}
connectSignalsForContainer( sub );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonCollection::initAfterRead()
{
// Migrate legacy m_polygonFiles into m_subCollections so files become polymorphic
// children alongside folders. Old projects had files in a separate field; new
// projects store everything in m_subCollections.
if ( !m_polygonFiles_OBSOLETE.empty() )
{
std::vector<RimPolygonFile*> legacy = m_polygonFiles_OBSOLETE.childrenByType();
m_polygonFiles_OBSOLETE.clearWithoutDelete();
for ( auto* file : legacy )
{
m_subCollections.push_back( file );
}
}
connectSignalsRecursively();
}
@@ -18,8 +18,7 @@
#pragma once
#include "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
#include "RimPolygonContainer.h"
class RimPolygon;
class RimPolygonFile;
@@ -28,13 +27,18 @@ class RimPolygonFile;
///
///
//==================================================================================================
class RimPolygonCollection : public caf::PdmObject
class RimPolygonCollection : public RimPolygonContainer
{
CAF_PDM_HEADER_INIT;
public:
RimPolygonCollection();
// Construct the single top-level polygon collection. Marks the instance as the topmost folder
// and applies the branded polygon icon. Sub-folders use the default folder icon from the
// constructor.
static RimPolygonCollection* createTopmost();
void loadData();
RimPolygon* createUserDefinedPolygon();
RimPolygon* appendUserDefinedPolygon();
@@ -42,11 +46,13 @@ public:
void deleteUserDefinedPolygons();
void deleteAllPolygons();
void addPolygonFile( RimPolygonFile* polygonFile );
std::vector<RimPolygon*> allPolygons() const;
std::vector<RimPolygon*> userDefinedPolygons() const;
std::vector<RimPolygonFile*> polygonFiles() const;
std::vector<RimPolygon*> allPolygons() const;
// Adds a polygon file as a sub-collection and wires the runtime side-effects
// (file-changed signal, view-tree refresh, redraw). Use this when introducing a
// file at runtime; addSubCollection() alone is fine when the side-effects will
// be triggered another way (e.g., during initAfterRead).
void addPolygonFile( RimPolygonFile* polygonFile );
static void appendPolygonMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder );
@@ -54,6 +60,7 @@ private:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void updateViewTreeItems();
void scheduleRedrawViews();
@@ -63,9 +70,14 @@ private:
void onPolygonChanged( const caf::SignalEmitter* emitter );
void onPolygonFileChanged( const caf::SignalEmitter* emitter );
void connectSignalsRecursively();
void connectSignalsForContainer( RimPolygonContainer* container );
private:
caf::PdmChildArrayField<RimPolygon*> m_polygons;
caf::PdmChildArrayField<RimPolygonFile*> m_polygonFiles;
// Legacy field. Polygon files are now stored polymorphically inside m_subCollections
// (inherited from RimPolygonContainer). Kept declared so old projects load; migrated
// into m_subCollections in initAfterRead.
caf::PdmChildArrayField<RimPolygonFile*> m_polygonFiles_OBSOLETE;
protected:
void initAfterRead() override;
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- Equinor ASA
// Copyright (C) 2026 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
@@ -16,45 +16,30 @@
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewSurfaceCollectionFeature.h"
#include "RimPolygonContainer.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
#include "RimPolygon.h"
#include "RimPolygonCollection.h"
#include "Riu3DMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cafUtils.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewSurfaceCollectionFeature, "RicNewSurfaceCollectionFeature" );
CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPolygonContainer, "RimPolygonContainer" ); // Abstract class
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSurfaceCollectionFeature::onActionTriggered( bool isChecked )
RimPolygonContainer::RimPolygonContainer()
{
std::vector<RimSurfaceCollection*> colls = caf::selectedObjectsByTypeStrict<RimSurfaceCollection*>();
if ( colls.empty() ) return;
RimSurfaceCollection* surfColl = colls[0];
CAF_PDM_InitObject( "Polygon Container" );
if ( surfColl )
{
// add a new surface collection and select it in the tree
RimSurfaceCollection* newcoll = new RimSurfaceCollection();
surfColl->addSubCollection( newcoll );
Riu3DMainWindowTools::selectAsCurrentItem( newcoll );
}
// m_collectionName, m_subCollections and m_items are initialized by derived classes
// with derived-specific XML keywords, matching the caf::PdmNestedCollection convention.
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSurfaceCollectionFeature::setupActionLook( QAction* actionToSetup )
RimPolygonContainer* RimPolygonContainer::addNewSubCollection()
{
actionToSetup->setIcon( QIcon( ":/ReservoirSurfaces16x16.png" ) );
actionToSetup->setText( "Add Folder" );
auto* sub = new RimPolygonCollection();
addSubCollection( sub );
return sub;
}
@@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2026 Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmNestedCollection.h"
class RimPolygon;
//==================================================================================================
///
/// Common base for polygon containers (folders and files).
///
/// Both RimPolygonCollection (a user-managed folder) and RimPolygonFile (a file-backed
/// folder of polygons) inherit from this. They live polymorphically in the inherited
/// m_subCollections, so the in-view mirror tree picks both up uniformly.
///
//==================================================================================================
class RimPolygonContainer : public caf::PdmNestedCollection<RimPolygonContainer, RimPolygon>
{
CAF_PDM_HEADER_INIT;
public:
RimPolygonContainer();
// "Add Folder" should produce a real folder (RimPolygonCollection), not another container
// shell. Override here so the default base impl (new SelfT) is bypassed for both this class
// and any derivative that does not override it. The runtime instance is a RimPolygonCollection;
// the return type stays at RimPolygonContainer* to avoid pulling RimPolygonCollection.h into
// this header (which would create an include cycle).
RimPolygonContainer* addNewSubCollection() override;
};
@@ -40,12 +40,20 @@ RimPolygonFile::RimPolygonFile()
{
CAF_PDM_InitObject( "PolygonFile", ":/Folder.png" );
// Inherited fields. The polygon items keep the original "Polygons" keyword so
// existing files load. The previous Name field was provided by RimNamedObject under
// keyword "Name"; reuse that keyword for m_collectionName for backward compatibility.
CAF_PDM_InitFieldNoDefault( &m_collectionName, "Name", "Name" );
CAF_PDM_InitFieldNoDefault( &m_subCollections, "SubCollections", "Subcollections" );
m_subCollections.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_items, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_fileName, "FileName", "File Name" );
m_fileName.registerKeywordAlias( "StimPlanFileName" );
m_fileName.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitFieldNoDefault( &m_polygons, "Polygons", "Polygons" );
setDeletable( true );
}
@@ -71,11 +79,12 @@ void RimPolygonFile::loadData()
polygonsFromFile[0]->setName( name() );
}
if ( m_polygons.size() == polygonsFromFile.size() )
auto existingPolygons = items();
if ( existingPolygons.size() == polygonsFromFile.size() )
{
for ( size_t i = 0; i < m_polygons.size(); i++ )
for ( size_t i = 0; i < existingPolygons.size(); i++ )
{
auto projectPoly = m_polygons()[i];
auto projectPoly = existingPolygons[i];
projectPoly->setDeletable( false );
auto filePoly = polygonsFromFile[i];
projectPoly->setPointsInDomainCoords( filePoly->pointsInDomainCoords() );
@@ -86,9 +95,9 @@ void RimPolygonFile::loadData()
}
else
{
m_polygons.deleteChildren();
m_items.deleteChildren();
m_polygons.setValue( polygonsFromFile );
m_items.setValue( polygonsFromFile );
}
if ( polygonsFromFile.empty() )
@@ -106,7 +115,7 @@ void RimPolygonFile::loadData()
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygon*> RimPolygonFile::polygons() const
{
return m_polygons.childrenByType();
return items();
}
//--------------------------------------------------------------------------------------------------
@@ -114,7 +123,7 @@ std::vector<RimPolygon*> RimPolygonFile::polygons() const
//--------------------------------------------------------------------------------------------------
QString RimPolygonFile::name() const
{
QString nameCandidate = RimNamedObject::name();
QString nameCandidate = m_collectionName.value();
if ( !nameCandidate.isEmpty() )
{
@@ -131,12 +140,20 @@ QString RimPolygonFile::name() const
return fileInfo.fileName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonContainer* RimPolygonFile::addNewSubCollection()
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( nameField() );
uiOrdering.add( &m_collectionName );
uiOrdering.add( &m_fileName );
uiOrdering.skipRemainingFields();
}
@@ -150,7 +167,7 @@ void RimPolygonFile::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
{
updateName();
m_polygons.deleteChildren();
m_items.deleteChildren();
loadData();
}
@@ -197,7 +214,7 @@ std::vector<RimPolygon*> RimPolygonFile::importDataFromFile( const QString& file
void RimPolygonFile::updateName()
{
QFileInfo fileInfo( m_fileName().path() );
setName( fileInfo.baseName() );
setCollectionName( fileInfo.baseName() );
}
//--------------------------------------------------------------------------------------------------
@@ -213,7 +230,7 @@ void RimPolygonFile::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder )
//--------------------------------------------------------------------------------------------------
void RimPolygonFile::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
if ( m_polygons.empty() )
if ( m_items.empty() )
{
caf::PdmUiTreeViewItemAttribute::appendTagToTreeViewItemAttribute( attribute, ":/warning.svg" );
}
@@ -17,14 +17,12 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimNamedObject.h"
#include "RimPolygonContainer.h"
#include "cafFilePath.h"
#include "cafPdmChildArrayField.h"
#include "cafSignal.h"
class RimPolygon;
class RimPolygonFile : public RimNamedObject
class RimPolygonFile : public RimPolygonContainer
{
CAF_PDM_HEADER_INIT;
@@ -40,7 +38,11 @@ public:
std::vector<RimPolygon*> polygons() const;
QString name() const override;
QString name() const;
// A file is a leaf folder. Refuse to grow sub-folders inside it.
bool canAddSubCollection() const override { return false; }
RimPolygonContainer* addNewSubCollection() override;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
@@ -54,6 +56,4 @@ private:
private:
caf::PdmField<caf::FilePath> m_fileName;
caf::PdmChildArrayField<RimPolygon*> m_polygons;
};
@@ -47,9 +47,12 @@ class RimPolygonInView : public RimCheckableNamedObject, public RimPolylinesData
CAF_PDM_HEADER_INIT;
public:
using SourceItemT = RimPolygon;
RimPolygonInView();
RimPolygon* polygon() const;
RimPolygon* sourceItem() const { return polygon(); }
void setPolygon( RimPolygon* polygon );
void updateTargetsFromPolygon();
@@ -22,7 +22,6 @@
#include "Rim3dView.h"
#include "RimPolygon.h"
#include "RimPolygonCollection.h"
#include "RimPolygonFile.h"
#include "RimPolygonInView.h"
#include "RimTools.h"
@@ -37,8 +36,10 @@ RimPolygonInViewCollection::RimPolygonInViewCollection()
{
CAF_PDM_InitObject( "Polygons", ":/Folder.png" );
CAF_PDM_InitFieldNoDefault( &m_polygonsInView, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_itemsInView, "Polygons", "Polygons" );
CAF_PDM_InitFieldNoDefault( &m_collectionsInView, "Collections", "Collections" );
CAF_PDM_InitFieldNoDefault( &m_sourceCollection, "SourceCollection", "Source Collection" );
m_sourceCollection.uiCapability()->setUiHidden( true );
nameField()->uiCapability()->setUiHidden( true );
}
@@ -48,7 +49,11 @@ RimPolygonInViewCollection::RimPolygonInViewCollection()
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::updateFromPolygonCollection()
{
updateAllViewItems();
if ( !sourceCollection() )
{
setSourceCollection( RimTools::polygonCollection() );
}
updateFromSource();
}
//--------------------------------------------------------------------------------------------------
@@ -58,7 +63,7 @@ std::vector<RimPolygonInView*> RimPolygonInViewCollection::visiblePolygonsInView
{
if ( !m_isChecked ) return {};
std::vector<RimPolygonInView*> polys = m_polygonsInView.childrenByType();
std::vector<RimPolygonInView*> polys = m_itemsInView.childrenByType();
for ( auto coll : m_collectionsInView )
{
@@ -76,7 +81,7 @@ std::vector<RimPolygonInView*> RimPolygonInViewCollection::visiblePolygonsInView
//--------------------------------------------------------------------------------------------------
std::vector<RimPolygonInView*> RimPolygonInViewCollection::allPolygonsInView() const
{
std::vector<RimPolygonInView*> polys = m_polygonsInView.childrenByType();
std::vector<RimPolygonInView*> polys = m_itemsInView.childrenByType();
for ( auto coll : m_collectionsInView )
{
@@ -87,24 +92,6 @@ std::vector<RimPolygonInView*> RimPolygonInViewCollection::allPolygonsInView() c
return polys;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::setPolygonFile( RimPolygonFile* polygonFile )
{
m_polygonFile = polygonFile;
updateName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonFile* RimPolygonInViewCollection::polygonFile() const
{
return m_polygonFile;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -141,156 +128,27 @@ void RimPolygonInViewCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& me
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::updateAllViewItems()
std::vector<RimPolygonContainer*> RimPolygonInViewCollection::sourceSubCollections() const
{
// Based on the same concept as RimSurfaceInViewCollection
syncCollectionsWithView();
syncPolygonsWithView();
updateConnectedEditors();
if ( auto* src = sourceCollection() ) return src->subCollections();
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::syncCollectionsWithView()
std::vector<RimPolygon*> RimPolygonInViewCollection::sourceItems() const
{
// Based on the same concept as RimSurfaceInViewCollection
auto colls = m_collectionsInView.childrenByType();
for ( auto coll : colls )
{
if ( !coll->polygonFile() )
{
m_collectionsInView.removeChild( coll );
delete coll;
}
}
if ( !m_polygonFile )
{
std::vector<RimPolygonInViewCollection*> orderedColls;
if ( auto polygonCollection = RimTools::polygonCollection() )
{
std::vector<RimPolygonInView*> newPolygonsInView;
for ( auto polygonFile : polygonCollection->polygonFiles() )
{
if ( polygonFile->polygons().empty() ) continue;
if ( polygonFile->polygons().size() == 1 ) continue;
auto viewPolygonFile = getCollectionInViewForPolygonFile( polygonFile );
if ( viewPolygonFile == nullptr )
{
auto newColl = new RimPolygonInViewCollection();
newColl->setPolygonFile( polygonFile );
orderedColls.push_back( newColl );
}
else
{
viewPolygonFile->updateName();
orderedColls.push_back( viewPolygonFile );
}
}
}
m_collectionsInView.clearWithoutDelete();
for ( auto viewColl : orderedColls )
{
m_collectionsInView.push_back( viewColl );
viewColl->updateAllViewItems();
}
}
updateName();
if ( auto* src = sourceCollection() ) return src->items();
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::syncPolygonsWithView()
RimPolygonInView* RimPolygonInViewCollection::createItemInView( RimPolygon* source )
{
std::vector<RimPolygonInView*> existingPolygonsInView = m_polygonsInView.childrenByType();
m_polygonsInView.clearWithoutDelete();
std::vector<RimPolygon*> polygons;
if ( m_polygonFile )
{
polygons = m_polygonFile->polygons();
}
else
{
auto polygonCollection = RimTools::polygonCollection();
polygons = polygonCollection->userDefinedPolygons();
for ( auto polyfile : polygonCollection->polygonFiles() )
{
if ( polyfile->polygons().size() == 1 )
{
polygons.push_back( polyfile->polygons()[0] );
}
}
}
std::vector<RimPolygonInView*> newPolygonsInView;
for ( auto polygon : polygons )
{
auto it = std::find_if( existingPolygonsInView.begin(),
existingPolygonsInView.end(),
[polygon]( auto* polygonInView ) { return polygonInView->polygon() == polygon; } );
if ( it != existingPolygonsInView.end() )
{
newPolygonsInView.push_back( *it );
( *it )->updateTargetsFromPolygon();
existingPolygonsInView.erase( it );
}
else
{
auto polygonInView = new RimPolygonInView();
polygonInView->setPolygon( polygon );
newPolygonsInView.push_back( polygonInView );
}
}
m_polygonsInView.setValue( newPolygonsInView );
for ( auto polyInView : existingPolygonsInView )
{
delete polyInView;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPolygonInViewCollection::updateName()
{
QString name = "Polygons";
if ( m_polygonFile )
{
name = m_polygonFile->name();
}
setName( name );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimPolygonInViewCollection* RimPolygonInViewCollection::getCollectionInViewForPolygonFile( const RimPolygonFile* polygonFile ) const
{
for ( auto collInView : m_collectionsInView )
{
if ( collInView->polygonFile() == polygonFile )
{
return collInView;
}
}
return nullptr;
auto* viewItem = new RimPolygonInView();
viewItem->setPolygon( source );
return viewItem;
}
@@ -18,20 +18,17 @@
#pragma once
#include "RimCheckableNamedObject.h"
#include "RimNestedMirrorCollectionInView.h"
#include "RimPolygonContainer.h"
#include "RimPolygonInView.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmPointer.h"
class RimPolygonInView;
class RimPolygonFile;
class RimPolygon;
//==================================================================================================
///
///
//==================================================================================================
class RimPolygonInViewCollection : public RimCheckableNamedObject
class RimPolygonInViewCollection : public RimNestedMirrorCollectionInView<RimPolygonInViewCollection, RimPolygonContainer, RimPolygonInView>
{
CAF_PDM_HEADER_INIT;
@@ -43,23 +40,12 @@ public:
std::vector<RimPolygonInView*> visiblePolygonsInView() const;
std::vector<RimPolygonInView*> allPolygonsInView() const;
protected:
std::vector<RimPolygonContainer*> sourceSubCollections() const override;
std::vector<RimPolygon*> sourceItems() const override;
RimPolygonInView* createItemInView( RimPolygon* source ) override;
private:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void setPolygonFile( RimPolygonFile* polygonFile );
RimPolygonFile* polygonFile() const;
void updateAllViewItems();
void syncCollectionsWithView();
void syncPolygonsWithView();
void updateName();
RimPolygonInViewCollection* getCollectionInViewForPolygonFile( const RimPolygonFile* polygonFile ) const;
private:
caf::PdmChildArrayField<RimPolygonInView*> m_polygonsInView;
caf::PdmChildArrayField<RimPolygonInViewCollection*> m_collectionsInView;
caf::PdmPointer<RimPolygonFile> m_polygonFile;
};
@@ -70,8 +70,7 @@ RimOilField::RimOilField()
measurement.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &surfaceCollection, "SurfaceCollection", "Surfaces" );
surfaceCollection = new RimSurfaceCollection();
surfaceCollection->setAsTopmostFolder();
surfaceCollection = RimSurfaceCollection::createTopmost();
CAF_PDM_InitFieldNoDefault( &seismicDataCollection, "SeismicCollection", "Seismic Data" );
seismicDataCollection = new RimSeismicDataCollection();
@@ -93,7 +92,7 @@ RimOilField::RimOilField()
formationNamesCollection = new RimFormationNamesCollection();
annotationCollection = new RimAnnotationCollection();
ensembleWellLogsCollection = new RimEnsembleWellLogsCollection();
polygonCollection = new RimPolygonCollection();
polygonCollection = RimPolygonCollection::createTopmost();
CAF_PDM_InitFieldNoDefault( &vfpDataCollection, "VfpDataCollection", "VFP Data" );
vfpDataCollection = new RimVfpDataCollection();
@@ -270,7 +270,7 @@ RimSurfaceCollection* RimEnsembleSurface::sourceFileSurfaceCollection() const
{
auto name = ensembleSourceFileCollectionName();
return getSubCollection( name );
return findSubCollectionByName( name );
}
//--------------------------------------------------------------------------------------------------
@@ -51,9 +51,8 @@ CAF_PDM_SOURCE_INIT( RimSurfaceCollection, "SurfaceCollection" );
///
//--------------------------------------------------------------------------------------------------
RimSurfaceCollection::RimSurfaceCollection()
: m_isTopLevelFolder( false )
{
CAF_PDM_InitScriptableObject( "Surfaces", ":/ReservoirSurfaces16x16.png" );
CAF_PDM_InitScriptableObject( "Surfaces", ":/Folder.png" );
CAF_PDM_InitScriptableFieldNoDefault( &m_collectionName, "SurfaceUserDescription", "Name" );
m_collectionName.registerKeywordAlias( "SurfaceUserDecription" );
@@ -64,7 +63,7 @@ RimSurfaceCollection::RimSurfaceCollection()
auto reorderability = caf::PdmFieldReorderCapability::addToField( &m_subCollections );
reorderability->orderChanged.connect( this, &RimSurfaceCollection::orderChanged );
CAF_PDM_InitScriptableFieldNoDefault( &m_surfaces, "SurfacesField", "Surfaces" );
CAF_PDM_InitScriptableFieldNoDefault( &m_items, "SurfacesField", "Surfaces" );
setDeletable( true );
}
@@ -79,44 +78,12 @@ RimSurfaceCollection::~RimSurfaceCollection()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::setAsTopmostFolder()
RimSurfaceCollection* RimSurfaceCollection::createTopmost()
{
m_collectionName.uiCapability()->setUiHidden( true );
m_collectionName.xmlCapability()->disableIO();
setDeletable( false );
m_isTopLevelFolder = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSurfaceCollection::collectionName() const
{
return m_collectionName.value();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::setCollectionName( const QString name )
{
if ( !m_isTopLevelFolder )
{
m_collectionName.setValue( name );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimSurfaceCollection::userDescriptionField()
{
if ( !m_isTopLevelFolder )
{
return &m_collectionName;
}
return nullptr;
auto* coll = new RimSurfaceCollection();
coll->setAsTopmostFolder();
coll->uiCapability()->setUiIconFromResourceString( ":/ReservoirSurfaces16x16.png" );
return coll;
}
//--------------------------------------------------------------------------------------------------
@@ -124,7 +91,7 @@ caf::PdmFieldHandle* RimSurfaceCollection::userDescriptionField()
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::addSurface( RimSurface* surface )
{
m_surfaces.push_back( surface );
m_items.push_back( surface );
}
//--------------------------------------------------------------------------------------------------
@@ -181,7 +148,7 @@ RimSurface* RimSurfaceCollection::createSurfaceFromFile( const QString& fileName
RimSurface* RimSurfaceCollection::importSurfacesFromFiles( const QStringList& fileNames, bool showLegend /* = true */ )
{
size_t newSurfCount = 0;
size_t existingSurfCount = m_surfaces().size();
size_t existingSurfCount = m_items().size();
QString errorMessages;
std::vector<RimSurface*> surfacesToLoad;
@@ -216,9 +183,9 @@ RimSurface* RimSurfaceCollection::importSurfacesFromFiles( const QStringList& fi
updateViews( surfacesToLoad, showLegend );
if ( newSurfCount > 0 && !m_surfaces.empty() )
if ( newSurfCount > 0 && !m_items.empty() )
{
return m_surfaces[m_surfaces.size() - 1];
return m_items[m_items.size() - 1];
}
else
{
@@ -266,7 +233,7 @@ RimSurface* RimSurfaceCollection::copySurfaces( std::vector<RimSurface*> surface
RimSurface* retsurf = nullptr;
for ( RimSurface* surface : newsurfaces )
{
m_surfaces.push_back( surface );
m_items.push_back( surface );
retsurf = surface;
}
@@ -291,7 +258,7 @@ RimSurface* RimSurfaceCollection::addGridCaseSurface( RimCase* sourceCase, int o
return nullptr;
}
m_surfaces.push_back( s );
m_items.push_back( s );
updateConnectedEditors();
@@ -307,15 +274,7 @@ RimSurface* RimSurfaceCollection::addGridCaseSurface( RimCase* sourceCase, int o
//--------------------------------------------------------------------------------------------------
std::vector<RimSurface*> RimSurfaceCollection::surfaces() const
{
return m_surfaces.childrenByType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSurfaceCollection*> RimSurfaceCollection::subCollections() const
{
return m_subCollections.childrenByType();
return m_items.childrenByType();
}
//--------------------------------------------------------------------------------------------------
@@ -330,7 +289,7 @@ void RimSurfaceCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuil
menuBuilder << "RicImportEnsembleSurfaceFeature";
menuBuilder << "RicCreateEnsembleSurfaceFeature";
menuBuilder.addSeparator();
menuBuilder << "RicNewSurfaceCollectionFeature";
menuBuilder << "RicNewNestedCollectionFeature";
}
//--------------------------------------------------------------------------------------------------
@@ -338,7 +297,7 @@ void RimSurfaceCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuil
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::loadData()
{
for ( auto surf : m_surfaces )
for ( auto surf : m_items )
{
surf->loadDataIfRequired();
}
@@ -441,7 +400,7 @@ void RimSurfaceCollection::orderChanged( const caf::SignalEmitter* emitter )
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::removeSurface( RimSurface* surface )
{
m_surfaces.removeChild( surface );
m_items.removeChild( surface );
}
//--------------------------------------------------------------------------------------------------
@@ -484,11 +443,11 @@ RimSurface* RimSurfaceCollection::addSurfacesAtIndex( int position, std::vector<
if ( !surfaces.empty() ) returnSurface = surfaces[0];
// insert position at end?
if ( ( position >= static_cast<int>( m_surfaces.size() ) ) || ( position < 0 ) )
if ( ( position >= static_cast<int>( m_items.size() ) ) || ( position < 0 ) )
{
for ( auto surf : surfaces )
{
m_surfaces.push_back( surf );
m_items.push_back( surf );
}
}
else
@@ -500,7 +459,7 @@ RimSurface* RimSurfaceCollection::addSurfacesAtIndex( int position, std::vector<
while ( i < position )
{
orderedSurfs.push_back( m_surfaces[i++] );
orderedSurfs.push_back( m_items[i++] );
}
for ( auto surf : surfaces )
@@ -508,17 +467,17 @@ RimSurface* RimSurfaceCollection::addSurfacesAtIndex( int position, std::vector<
orderedSurfs.push_back( surf );
}
int surfcount = static_cast<int>( m_surfaces.size() );
int surfcount = static_cast<int>( m_items.size() );
while ( i < surfcount )
{
orderedSurfs.push_back( m_surfaces[i++] );
orderedSurfs.push_back( m_items[i++] );
}
// reset the surface collection and use the new order
m_surfaces.clearWithoutDelete();
m_items.clearWithoutDelete();
for ( auto surf : orderedSurfs )
{
m_surfaces.push_back( surf );
m_items.push_back( surf );
}
}
@@ -528,45 +487,6 @@ RimSurface* RimSurfaceCollection::addSurfacesAtIndex( int position, std::vector<
return returnSurface;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::addSubCollection( RimSurfaceCollection* subcoll )
{
m_subCollections.push_back( subcoll );
updateConnectedEditors();
updateViews();
return;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSurfaceCollection* RimSurfaceCollection::getSubCollection( const QString& name ) const
{
for ( auto coll : m_subCollections )
{
if ( coll->collectionName() == name ) return coll;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSurfaceCollection::deleteSubCollection( const QString& name )
{
auto coll = getSubCollection( name );
if ( coll )
{
auto index = m_subCollections.indexOf( coll );
m_subCollections.erase( index );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -17,16 +17,13 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmField.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
#include "cafPdmNestedCollection.h"
class RimSurface;
class RimEnsembleSurface;
class RimCase;
class RimSurfaceCollection : public caf::PdmObject
class RimSurfaceCollection : public caf::PdmNestedCollection<RimSurfaceCollection, RimSurface>
{
CAF_PDM_HEADER_INIT;
@@ -34,8 +31,12 @@ public:
RimSurfaceCollection();
~RimSurfaceCollection() override;
// Construct the single top-level surface collection. Marks the instance as the topmost folder
// and applies the branded surface icon. Sub-folders use the default folder icon from the
// constructor.
static RimSurfaceCollection* createTopmost();
void addSurface( RimSurface* surface );
void setAsTopmostFolder();
void addEnsembleSurface( RimEnsembleSurface* ensembleSurface );
std::vector<RimEnsembleSurface*> ensembleSurfaces() const;
@@ -47,10 +48,6 @@ public:
static RimSurface* createSurfaceFromFile( const QString& fileName );
void addSubCollection( RimSurfaceCollection* collection );
RimSurfaceCollection* getSubCollection( const QString& name ) const;
void deleteSubCollection( const QString& name );
bool containsFileSurface( QString filename );
bool containsSurface();
@@ -65,22 +62,11 @@ public:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
QString collectionName() const;
void setCollectionName( const QString name );
std::vector<RimSurface*> surfaces() const;
std::vector<RimSurfaceCollection*> subCollections() const;
std::vector<RimSurface*> surfaces() const;
protected:
caf::PdmFieldHandle* userDescriptionField() override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
private:
void orderChanged( const caf::SignalEmitter* emitter );
caf::PdmField<QString> m_collectionName;
caf::PdmChildArrayField<RimSurface*> m_surfaces;
caf::PdmChildArrayField<RimSurfaceCollection*> m_subCollections;
bool m_isTopLevelFolder;
};
@@ -32,7 +32,6 @@
#include <QStringList>
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_importSurface, "ImportSurface" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_addFolder, "AddFolder" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_newSurface, "NewSurface" );
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurfaceCollection, RimcSurfaceCollection_newRegularSurface, "NewRegularSurface" );
@@ -71,42 +70,6 @@ QString RimcSurfaceCollection_importSurface::classKeywordReturnedType() const
return RimFileSurface::classKeywordStatic();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcSurfaceCollection_addFolder::RimcSurfaceCollection_addFolder( caf::PdmObjectHandle* self )
: PdmObjectCreationMethod( self )
{
CAF_PDM_InitObject( "Add Folder", "", "", "Add a new surface folder" );
CAF_PDM_InitScriptableField( &m_folderName, "FolderName", QString( "Surfaces" ), "", "", "", "New surface folder name" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcSurfaceCollection_addFolder::execute()
{
RimSurfaceCollection* coll = self<RimSurfaceCollection>();
if ( coll )
{
RimSurfaceCollection* newcoll = new RimSurfaceCollection();
newcoll->setCollectionName( m_folderName() );
coll->addSubCollection( newcoll );
return newcoll;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimcSurfaceCollection_addFolder::classKeywordReturnedType() const
{
return RimSurfaceCollection::classKeywordStatic();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -50,23 +50,6 @@ private:
caf::PdmField<QString> m_fileName;
};
//==================================================================================================
///
//==================================================================================================
class RimcSurfaceCollection_addFolder : public caf::PdmObjectCreationMethod
{
CAF_PDM_HEADER_INIT;
public:
RimcSurfaceCollection_addFolder( caf::PdmObjectHandle* self );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
QString classKeywordReturnedType() const override;
private:
caf::PdmField<QString> m_folderName;
};
//==================================================================================================
///
//==================================================================================================
+11 -2
View File
@@ -603,8 +603,17 @@ class PdmObjectBase:
try:
pb2_object = self._pdm_object_stub.CallPdmObjectMethod(request)
pdm_object = class_definition(pb2_object=pb2_object, channel=self.channel())
return pdm_object
# Prefer the actual class the server returned over the statically declared one
# so that generic methods (e.g. AddFolder registered on a shared base) yield
# the most-derived Python proxy and inherited accessors work as expected.
from .generated.generated_classes import class_from_keyword
actual_class = class_from_keyword(pb2_object.class_keyword)
if actual_class is not None and issubclass(actual_class, class_definition):
return actual_class(pb2_object=pb2_object, channel=self.channel())
return class_definition(pb2_object=pb2_object, channel=self.channel())
except grpc.RpcError as exc:
raise RipsError(
"%s" % exc.details(), code=exc.code(), details=exc.details()
@@ -32,3 +32,36 @@ def test_create_polygon(rips_instance, initialize_test):
assert len(expected) == len(actual)
for e, a in zip(expected, actual):
assert math.isclose(e, a, rel_tol=1e-9, abs_tol=0.0)
def test_add_folders_and_polygons(rips_instance, initialize_test):
rips_instance.project.open(
dataroot.PATH + "/TEST10K_FLT_LGR_NNC/10KWithWellLog.rsp"
)
root = rips_instance.project.descendants(rips.PolygonCollection)[0]
folder_a = root.add_folder(folder_name="Folder A")
folder_b = root.add_folder(folder_name="Folder B")
nested = folder_a.add_folder(folder_name="Nested")
sub_names = [s.polygon_collection_name for s in root.sub_collections()]
assert "Folder A" in sub_names
assert "Folder B" in sub_names
assert [s.polygon_collection_name for s in folder_a.sub_collections()] == ["Nested"]
coordinates = [
[0.0, 0.0, -1000.0],
[100.0, 0.0, -1000.0],
[100.0, 100.0, -1000.0],
[0.0, 100.0, -1000.0],
]
root.create_polygon(name="root poly", coordinates=coordinates)
folder_a.create_polygon(name="A poly", coordinates=coordinates)
nested.create_polygon(name="nested poly", coordinates=coordinates)
assert [p.name for p in root.polygons()] == ["root poly"]
assert [p.name for p in folder_a.polygons()] == ["A poly"]
assert [p.name for p in folder_b.polygons()] == []
assert [p.name for p in nested.polygons()] == ["nested poly"]