diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index 1ebf9cddf8..7e2f8974f8 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -134,6 +134,8 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseEnsemble.h ${CMAKE_CURRENT_LIST_DIR}/RimCameraPosition.h ${CMAKE_CURRENT_LIST_DIR}/RimWellTargetCandidatesGenerator.h + ${CMAKE_CURRENT_LIST_DIR}/RimFieldReference.h + ${CMAKE_CURRENT_LIST_DIR}/RimPinnedFieldCollection.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -268,6 +270,8 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseEnsemble.cpp ${CMAKE_CURRENT_LIST_DIR}/RimCameraPosition.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellTargetCandidatesGenerator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimFieldReference.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPinnedFieldCollection.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp index 079b5a33e6..1e4905cecf 100644 --- a/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/CellFilters/RimCellRangeFilter.cpp @@ -25,6 +25,7 @@ #include "RigReservoirGridTools.h" #include "Rim3dView.h" #include "RimCase.h" +#include "RimPinnedFieldCollection.h" #include "RimTools.h" #include "cafPdmUiLabelEditor.h" @@ -217,14 +218,23 @@ void RimCellRangeFilter::setDefaultValues( int sliceDirection, int defaultSlice case 0: cellCountI = 1; if ( defaultSlice > 0 ) startIndexI = defaultSlice; + + RimPinnedFieldCollection::instance()->addField( &startIndexI ); + break; case 1: cellCountJ = 1; if ( defaultSlice > 0 ) startIndexJ = defaultSlice; + + RimPinnedFieldCollection::instance()->addField( &startIndexJ ); + break; case 2: cellCountK = 1; if ( defaultSlice > 0 ) startIndexK = defaultSlice; + + RimPinnedFieldCollection::instance()->addField( &startIndexK ); + break; default: break; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index db56d9b746..a248b9aa62 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -74,6 +74,7 @@ #include "RimIntersectionResultsDefinitionCollection.h" #include "RimMultipleEclipseResults.h" #include "RimOilField.h" +#include "RimPinnedFieldCollection.h" #include "RimProject.h" #include "RimRegularLegendConfig.h" #include "RimReservoirCellResultsStorage.h" @@ -246,6 +247,8 @@ RimEclipseView::RimEclipseView() m_faultReactVizModel = new cvf::ModelBasicList; m_faultReactVizModel->setName( "FaultReactModel" ); + + RimPinnedFieldCollection::instance()->addField( &m_eclipseCase ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimFieldReference.cpp b/ApplicationLibCode/ProjectDataModel/RimFieldReference.cpp new file mode 100644 index 0000000000..e5ad1832ef --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimFieldReference.cpp @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 "RimFieldReference.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafPdmUiToolButtonEditor.h" + +CAF_PDM_SOURCE_INIT( RimFieldReference, "RimFieldReference" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFieldReference::RimFieldReference() +{ + CAF_PDM_InitFieldNoDefault( &m_object, "Object", "Object" ); + CAF_PDM_InitFieldNoDefault( &m_fieldName, "FieldName", "FieldName" ); + + CAF_PDM_InitField( &m_selectObjectButton, "SelectObject", false, "...", ":/Bullet.png", "Select Object in Property Editor" ); + m_selectObjectButton.uiCapability()->setUiEditorTypeName( caf::PdmUiToolButtonEditor::uiEditorTypeName() ); + m_selectObjectButton.xmlCapability()->disableIO(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFieldReference::setField( caf::PdmFieldHandle* field ) +{ + if ( !field ) return; + + auto ownerObject = field->ownerObject(); + if ( !ownerObject ) return; + + setField( field->ownerObject(), field->keyword() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFieldReference::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + if ( field() ) + { + uiOrdering.add( field() ); + } + + uiOrdering.add( &m_selectObjectButton ); + + uiOrdering.skipRemainingFields(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFieldReference::field() const +{ + if ( !m_object() ) return nullptr; + + return m_object->findField( m_fieldName() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFieldReference::selectObjectButton() +{ + return &m_selectObjectButton; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFieldReference::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_selectObjectButton ) + { + m_selectObjectButton = false; + + if ( auto pdmObj = dynamic_cast( m_object() ) ) + { + Riu3DMainWindowTools::selectAsCurrentItem( pdmObj ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFieldReference::setField( caf::PdmObjectHandle* object, const QString& fieldName ) +{ + m_object = object; + m_fieldName = fieldName; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimFieldReference.h b/ApplicationLibCode/ProjectDataModel/RimFieldReference.h new file mode 100644 index 0000000000..eb3e039142 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimFieldReference.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPtrField.h" + +//================================================================================================== +/// +/// This class is used to store a reference to a field in a PdmObject, and is similar to caf::PdmPtrField that is +/// used for a non-owning reference to an object. Consider creating a caf::PdmPtrField instead of this class. +/// +/// Investigate if PdmFieldCapability::attributes can be used to store the field name for a caf::PdmPtrField +/// +//================================================================================================== +class RimFieldReference : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimFieldReference(); + + void setField( caf::PdmFieldHandle* field ); + caf::PdmFieldHandle* field() const; + + caf::PdmFieldHandle* selectObjectButton(); + +private: + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + + void setField( caf::PdmObjectHandle* object, const QString& fieldName ); + +private: + caf::PdmPtrField m_object; + caf::PdmField m_fieldName; + caf::PdmField m_selectObjectButton; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimPinnedFieldCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimPinnedFieldCollection.cpp new file mode 100644 index 0000000000..5c5b5e7900 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimPinnedFieldCollection.cpp @@ -0,0 +1,141 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 "RimPinnedFieldCollection.h" + +#include "RimFieldReference.h" +#include "RimProject.h" + +#include "cafAssert.h" + +CAF_PDM_SOURCE_INIT( RimPinnedFieldCollection, "RimFieldReferenceCollection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPinnedFieldCollection::RimPinnedFieldCollection() +{ + CAF_PDM_InitObject( "Field Reference Collection" ); + + CAF_PDM_InitFieldNoDefault( &m_fieldReferences, "Objects", "Objects" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPinnedFieldCollection* RimPinnedFieldCollection::instance() +{ + auto proj = RimProject::current(); + CAF_ASSERT( proj && "RimProject is nullptr when trying to access RimFieldReferenceCollection::instance()" ); + + return proj->pinnedFieldCollection(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPinnedFieldCollection::addField( caf::PdmFieldHandle* field ) +{ + if ( !field ) return; + + for ( auto fieldRef : m_fieldReferences ) + { + if ( field == fieldRef->field() ) + { + return; + } + } + + auto fieldReference = new RimFieldReference(); + fieldReference->setField( field ); + + m_fieldReferences.push_back( fieldReference ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPinnedFieldCollection::removeField( caf::PdmFieldHandle* field ) +{ + if ( !field ) return; + + for ( auto fieldRef : m_fieldReferences ) + { + if ( field == fieldRef->field() ) + { + m_fieldReferences.removeChild( fieldRef ); + delete fieldRef; + return; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPinnedFieldCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + std::map> fieldMap; + + // Group fields by object + for ( auto fieldRef : m_fieldReferences ) + { + if ( !fieldRef ) continue; + + if ( auto field = fieldRef->field() ) + { + if ( auto ownerObject = field->ownerObject() ) + { + fieldMap[ownerObject].push_back( fieldRef ); + } + } + } + + int groupId = 1; + + // Create ui ordering with a group containing fields for each object + for ( auto& pair : fieldMap ) + { + auto object = pair.first; + auto fieldRefs = pair.second; + + QString groupName; + auto uiCapability = object->uiCapability(); + if ( uiCapability->userDescriptionField() && uiCapability->userDescriptionField()->uiCapability() ) + { + groupName = uiCapability->userDescriptionField()->uiCapability()->uiValue().toString(); + } + else + { + groupName = "Group " + QString::number( groupId ); + } + + auto group = uiOrdering.addNewGroup( groupName ); + groupId++; + + for ( auto fieldRef : fieldRefs ) + { + group->add( fieldRef->field() ); + } + + if ( !fieldRefs.empty() ) + { + group->add( fieldRefs.front()->selectObjectButton(), { .newRow = false } ); + } + } +} diff --git a/ApplicationLibCode/ProjectDataModel/RimPinnedFieldCollection.h b/ApplicationLibCode/ProjectDataModel/RimPinnedFieldCollection.h new file mode 100644 index 0000000000..01dd7ebc0b --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimPinnedFieldCollection.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 "cafPdmField.h" +#include "cafPdmObject.h" + +class RimFieldReference; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimPinnedFieldCollection : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimPinnedFieldCollection(); + + static RimPinnedFieldCollection* instance(); + + void addField( caf::PdmFieldHandle* field ); + void removeField( caf::PdmFieldHandle* field ); + +private: + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + +private: + caf::PdmChildArrayField m_fieldReferences; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimProject.cpp b/ApplicationLibCode/ProjectDataModel/RimProject.cpp index c2a6f89685..695aa1f320 100644 --- a/ApplicationLibCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimProject.cpp @@ -72,6 +72,7 @@ #include "RimObservedDataCollection.h" #include "RimObservedSummaryData.h" #include "RimOilField.h" +#include "RimPinnedFieldCollection.h" #include "RimPlotWindow.h" #include "RimPltPlotCollection.h" #include "RimPolylinesFromFileAnnotation.h" @@ -161,6 +162,7 @@ RimProject::RimProject() scriptCollection.xmlCapability()->disableIO(); CAF_PDM_InitFieldNoDefault( &m_mainPlotCollection, "MainPlotCollection", "Plots" ); + CAF_PDM_InitFieldNoDefault( &m_pinnedFieldCollection, "PinnedFieldCollection", "PinnedFieldCollection" ); CAF_PDM_InitFieldNoDefault( &viewLinkerCollection, "LinkedViews", "Linked Views", ":/LinkView.svg" ); viewLinkerCollection = new RimViewLinkerCollection; @@ -221,7 +223,8 @@ RimProject::RimProject() scriptCollection->uiCapability()->setUiName( "Scripts" ); scriptCollection->uiCapability()->setUiIconFromResourceString( ":/octave.png" ); - m_mainPlotCollection = new RimMainPlotCollection(); + m_mainPlotCollection = new RimMainPlotCollection(); + m_pinnedFieldCollection = new RimPinnedFieldCollection(); CAF_PDM_InitFieldNoDefault( &m_plotTemplateTopFolder, "PlotTemplateCollection", "Plot Templates" ); m_plotTemplateTopFolder = new RimPlotTemplateFolderItem(); @@ -352,6 +355,14 @@ void RimProject::updatesAfterProjectFileIsRead() if ( m_subWindowsTiledPlotWindow_OBSOLETE ) m_subWindowsTileModePlotWindow = RiaDefines::WindowTileMode::DEFAULT; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPinnedFieldCollection* RimProject::pinnedFieldCollection() const +{ + return m_pinnedFieldCollection(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimProject.h b/ApplicationLibCode/ProjectDataModel/RimProject.h index 92b414698f..3f3ff461c8 100644 --- a/ApplicationLibCode/ProjectDataModel/RimProject.h +++ b/ApplicationLibCode/ProjectDataModel/RimProject.h @@ -71,6 +71,7 @@ class RimValveTemplate; class RimCompletionTemplateCollection; class RimPlotTemplateFolderItem; class RimGridCalculationCollection; +class RimPinnedFieldCollection; namespace caf { @@ -190,6 +191,8 @@ public: void updatesAfterProjectFileIsRead(); + RimPinnedFieldCollection* pinnedFieldCollection() const; + protected: void initAfterRead() override; void setupBeforeSave() override; @@ -202,7 +205,8 @@ private: QString updatedFilePathFromPathId( QString filePath, RiaVariableMapper* pathListMapper = nullptr ) const; private: - caf::PdmChildField m_mainPlotCollection; + caf::PdmChildField m_mainPlotCollection; + caf::PdmChildField m_pinnedFieldCollection; caf::PdmField m_globalPathList; caf::PdmField m_projectFileVersionString; diff --git a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp index 59fcdc9b7e..1209845d3f 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp @@ -43,6 +43,7 @@ #include "RimFaultInViewCollection.h" #include "RimGeoMechCase.h" #include "RimGeoMechView.h" +#include "RimPinnedFieldCollection.h" #include "RimProject.h" #include "RimSimWellInViewCollection.h" #include "RimViewLinker.h" @@ -188,6 +189,11 @@ RiuMainWindow::~RiuMainWindow() { m_pdmUiPropertyView->showProperties( nullptr ); } + + if ( m_pinnedFieldView ) + { + m_pinnedFieldView->showProperties( nullptr ); + } } //-------------------------------------------------------------------------------------------------- @@ -239,6 +245,8 @@ void RiuMainWindow::initializeGuiNewProjectLoaded() m_pdmUiPropertyView->currentObject()->uiCapability()->updateConnectedEditors(); } + m_pinnedFieldView->showProperties( RimPinnedFieldCollection::instance() ); + if ( statusBar() && !RiaRegressionTestRunner::instance()->isRunningRegressionTests() ) { statusBar()->showMessage( "Ready ..." ); @@ -295,6 +303,11 @@ void RiuMainWindow::cleanupGuiCaseClose() m_pdmUiPropertyView->showProperties( nullptr ); } + if ( m_pinnedFieldView ) + { + m_pinnedFieldView->showProperties( nullptr ); + } + for ( auto& additionalProjectView : m_additionalProjectViews ) { RiuProjectAndPropertyView* projPropView = dynamic_cast( additionalProjectView->widget() ); @@ -808,6 +821,14 @@ void RiuMainWindow::createDockPanels() dockManager()->addDockWidget( ads::DockWidgetArea::BottomDockWidgetArea, dockWidget, leftArea ); } + { + auto dockWidget = RiuDockWidgetTools::createDockWidget( "Quick Access", "Quick Access", dockManager() ); + + m_pinnedFieldView = new caf::PdmUiPropertyView( dockWidget ); + dockWidget->setWidget( m_pinnedFieldView ); + dockManager()->addDockWidget( ads::DockWidgetArea::BottomDockWidgetArea, dockWidget, leftArea ); + } + #ifdef USE_ODB_API { auto dockWidget = @@ -1482,6 +1503,7 @@ void RiuMainWindow::selectedObjectsChanged() updateUiFieldsFromActiveResult( firstSelectedObject ); m_pdmUiPropertyView->showProperties( firstSelectedObject ); + m_pinnedFieldView->showProperties( RimPinnedFieldCollection::instance() ); m_seismicHistogramPanel->showHistogram( firstSelectedObject ); diff --git a/ApplicationLibCode/UserInterface/RiuMainWindow.h b/ApplicationLibCode/UserInterface/RiuMainWindow.h index ae7a6baad3..ff6145fda5 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindow.h +++ b/ApplicationLibCode/UserInterface/RiuMainWindow.h @@ -261,6 +261,7 @@ public: private: caf::PdmObject* m_pdmRoot; caf::PdmUiPropertyView* m_pdmUiPropertyView; + caf::PdmUiPropertyView* m_pinnedFieldView; QComboBox* m_scaleFactor;