From c578a43b53bb18af5bf4edbceced1af38f53c2f6 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Fri, 11 Oct 2019 15:54:19 +0200 Subject: [PATCH] Introduce RimGridPlotWindow and RiuQwtPlotWidget --- .../RicExportToLasFileFeature.cpp | 16 +- .../RicExportToLasFileFeature.h | 2 +- .../Commands/RicDeleteItemExec.cpp | 5 +- .../RicSummaryCurveCreator.cpp | 4 +- .../WellLogCommands/CMakeLists_files.cmake | 4 +- .../RicAddWellLogToPlotFeature.cpp | 10 +- ...eature.cpp => RicDeleteSubPlotFeature.cpp} | 53 +- ...ackFeature.h => RicDeleteSubPlotFeature.h} | 2 +- .../WellLogCommands/RicNewPltPlotFeature.cpp | 4 +- .../WellLogCommands/RicNewRftPlotFeature.cpp | 4 +- .../RicNewWellBoreStabilityPlotFeature.cpp | 22 +- .../RicNewWellLogPlotFeatureImpl.cpp | 8 +- .../RicNewWellLogPlotTrackFeature.cpp | 6 +- .../RicPasteWellLogTrackFeature.cpp | 4 +- .../RicWellLogPlotTrackFeatureImpl.cpp | 49 +- .../RicWellLogPlotTrackFeatureImpl.h | 8 +- .../ProjectDataModel/CMakeLists_files.cmake | 8 +- .../Flow/RimWellAllocationPlot.cpp | 20 +- .../Flow/RimWellFlowRateCurve.cpp | 4 +- .../ProjectDataModel/Flow/RimWellPltPlot.cpp | 101 +- .../ProjectDataModel/Flow/RimWellRftPlot.cpp | 153 ++- .../ProjectDataModel/Flow/RimWellRftPlot.h | 2 - .../GridCrossPlots/RimGridCrossPlot.cpp | 321 +++-- .../GridCrossPlots/RimGridCrossPlot.h | 64 +- .../RimGridCrossPlotDataSet.cpp | 14 +- .../Rim2dIntersectionView.cpp | 2 +- .../ProjectDataModel/Rim2dIntersectionView.h | 2 +- .../ProjectDataModel/RimFormationNames.cpp | 6 +- .../ProjectDataModel/RimGridPlotWindow.cpp | 628 ++++++++++ .../ProjectDataModel/RimGridPlotWindow.h | 132 ++ .../RimGridTimeHistoryCurve.cpp | 4 +- .../ProjectDataModel/RimPlotInterface.cpp | 30 + .../ProjectDataModel/RimPlotInterface.h | 83 ++ .../ProjectDataModel/RimPlotWindow.cpp | 173 +++ .../ProjectDataModel/RimPlotWindow.h | 69 ++ .../ProjectDataModel/RimViewWindow.cpp | 8 + .../ProjectDataModel/RimViewWindow.h | 5 +- .../RimWellBoreStabilityPlot.cpp | 4 +- .../ProjectDataModel/RimWellLogCurve.cpp | 69 +- .../ProjectDataModel/RimWellLogCurve.h | 5 +- .../RimWellLogCurveCommonDataSource.cpp | 10 +- .../RimWellLogCurveCommonDataSource.h | 2 + .../RimWellLogExtractionCurve.cpp | 6 +- .../ProjectDataModel/RimWellLogFileCurve.cpp | 2 +- .../ProjectDataModel/RimWellLogPlot.cpp | 785 ++---------- .../ProjectDataModel/RimWellLogPlot.h | 113 +- .../RimWellLogPlotCollection.h | 1 - .../ProjectDataModel/RimWellLogRftCurve.cpp | 12 +- .../ProjectDataModel/RimWellLogTrack.cpp | 1064 ++++++++++------- .../ProjectDataModel/RimWellLogTrack.h | 126 +- .../Summary/RimEnsembleCurveSet.cpp | 34 +- .../Summary/RimSummaryCurve.cpp | 14 +- .../Summary/RimSummaryCurveCollection.cpp | 2 +- .../Summary/RimSummaryPlot.cpp | 559 +++++---- .../ProjectDataModel/Summary/RimSummaryPlot.h | 49 +- .../RigWellLogCurveData.cpp | 36 + .../ReservoirDataModel/RigWellLogCurveData.h | 1 + .../UserInterface/CMakeLists_files.cmake | 14 +- ApplicationCode/UserInterface/RiuDragDrop.cpp | 50 +- ApplicationCode/UserInterface/RiuDragDrop.h | 9 +- .../UserInterface/RiuGridCrossQwtPlot.cpp | 82 +- .../UserInterface/RiuGridCrossQwtPlot.h | 20 +- .../UserInterface/RiuGridPlotWindow.cpp | 687 +++++++++++ .../UserInterface/RiuGridPlotWindow.h | 124 ++ .../UserInterface/RiuMainWindowBase.cpp | 29 + .../UserInterface/RiuMainWindowBase.h | 1 + .../UserInterface/RiuMdiSubWindow.cpp | 1 - .../UserInterface/RiuPlotMainWindow.cpp | 4 +- .../UserInterface/RiuPlotMainWindowTools.cpp | 13 + .../UserInterface/RiuPlotMainWindowTools.h | 1 + ApplicationCode/UserInterface/RiuQwtPlot.cpp | 350 ------ ApplicationCode/UserInterface/RiuQwtPlot.h | 92 -- .../RiuQwtPlotLegend.cpp} | 31 +- .../RiuQwtPlotLegend.h} | 15 +- .../UserInterface/RiuQwtPlotTools.cpp | 53 +- .../UserInterface/RiuQwtPlotWidget.cpp | 830 +++++++++++++ .../UserInterface/RiuQwtPlotWidget.h | 146 +++ .../UserInterface/RiuQwtScalePicker.cpp | 8 +- .../UserInterface/RiuQwtScalePicker.h | 7 +- .../UserInterface/RiuSummaryQwtPlot.cpp | 60 +- .../UserInterface/RiuSummaryQwtPlot.h | 18 +- .../UserInterface/RiuWellLogPlot.cpp | 631 +--------- .../UserInterface/RiuWellLogPlot.h | 90 +- .../UserInterface/RiuWellLogTrack.cpp | 604 ++-------- .../UserInterface/RiuWellLogTrack.h | 126 +- .../cafUserInterface/cafPdmUiTreeView.cpp | 8 + .../cafUserInterface/cafPdmUiTreeView.h | 1 + .../cafPdmUiTreeViewEditor.cpp | 28 +- .../cafUserInterface/cafPdmUiTreeViewEditor.h | 1 + 89 files changed, 5249 insertions(+), 3809 deletions(-) rename ApplicationCode/Commands/WellLogCommands/{RicDeleteWellLogPlotTrackFeature.cpp => RicDeleteSubPlotFeature.cpp} (63%) rename ApplicationCode/Commands/WellLogCommands/{RicDeleteWellLogPlotTrackFeature.h => RicDeleteSubPlotFeature.h} (95%) create mode 100644 ApplicationCode/ProjectDataModel/RimGridPlotWindow.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimGridPlotWindow.h create mode 100644 ApplicationCode/ProjectDataModel/RimPlotInterface.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimPlotInterface.h create mode 100644 ApplicationCode/ProjectDataModel/RimPlotWindow.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimPlotWindow.h create mode 100644 ApplicationCode/UserInterface/RiuGridPlotWindow.cpp create mode 100644 ApplicationCode/UserInterface/RiuGridPlotWindow.h delete mode 100644 ApplicationCode/UserInterface/RiuQwtPlot.cpp delete mode 100644 ApplicationCode/UserInterface/RiuQwtPlot.h rename ApplicationCode/{ProjectDataModel/RimPlot.cpp => UserInterface/RiuQwtPlotLegend.cpp} (57%) rename ApplicationCode/{ProjectDataModel/RimPlot.h => UserInterface/RiuQwtPlotLegend.h} (76%) create mode 100644 ApplicationCode/UserInterface/RiuQwtPlotWidget.cpp create mode 100644 ApplicationCode/UserInterface/RiuQwtPlotWidget.h diff --git a/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.cpp index e569b3b060..8e4cc1e6ba 100644 --- a/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.cpp +++ b/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.cpp @@ -45,18 +45,22 @@ CAF_CMD_SOURCE_INIT( RicExportToLasFileFeature, "RicExportToLasFileFeature" ); //-------------------------------------------------------------------------------------------------- std::vector RicExportToLasFileFeature::exportToLasFiles( const QString& exportFolder, const QString& exportPrefix, - const RimWellLogPlot* plot, + const RimWellLogPlot* plotWindow, bool exportTvdRkb, bool capitalizeFileNames, double resampleInterval ) { - std::vector allCurves; - std::vector tracks = plot->visibleTracks(); + std::vector allCurves; + std::vector plots = plotWindow->visiblePlots(); - for ( RimWellLogTrack* track : tracks ) + for ( RimPlotInterface* plot : plots ) { - std::vector curves = track->visibleCurvesVector(); - allCurves.insert( allCurves.end(), curves.begin(), curves.end() ); + RimWellLogTrack* track = dynamic_cast( plot ); + if ( track ) + { + std::vector curves = track->visibleCurves(); + allCurves.insert( allCurves.end(), curves.begin(), curves.end() ); + } } std::vector wellNames; diff --git a/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.h b/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.h index 6b350ae44d..b1a41c1add 100644 --- a/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.h +++ b/ApplicationCode/Commands/ExportCommands/RicExportToLasFileFeature.h @@ -38,7 +38,7 @@ class RicExportToLasFileFeature : public caf::CmdFeature public: static std::vector exportToLasFiles( const QString& exportFolder, const QString& filePrefix, - const RimWellLogPlot* plot, + const RimWellLogPlot* plotWindow, bool exportTvdRkb = false, bool capitalizeFileNames = false, double resampleInterval = 0.0 ); diff --git a/ApplicationCode/Commands/RicDeleteItemExec.cpp b/ApplicationCode/Commands/RicDeleteItemExec.cpp index 679fc519ba..65a226dd4b 100644 --- a/ApplicationCode/Commands/RicDeleteItemExec.cpp +++ b/ApplicationCode/Commands/RicDeleteItemExec.cpp @@ -200,7 +200,7 @@ void RicDeleteItemExec::redo() if ( wellLogPlot ) { wellLogPlot->calculateAvailableDepthRange(); - wellLogPlot->updateDepthZoom(); + wellLogPlot->updateZoom(); RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateWellLogPlotToolBar(); } @@ -209,7 +209,8 @@ void RicDeleteItemExec::redo() parentObj->firstAncestorOrThisOfType( wellLogPlotTrack ); if ( wellLogPlotTrack ) { - wellLogPlotTrack->calculateXZoomRangeAndUpdateQwt(); + wellLogPlotTrack->setAutoScaleXEnabled( true ); + wellLogPlotTrack->updateZoomInQwt(); RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow(); mainPlotWindow->updateWellLogPlotToolBar(); } diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp index 031d7dc223..f3cc12e2a3 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCreator.cpp @@ -658,7 +658,7 @@ void RicSummaryCurveCreator::updateTargetPlot() copyEnsembleCurveAndAddToCurveSet( editedCurve, editedCurveSet ); } - newCurveSet->setParentQwtPlotNoReplot( m_targetPlot->qwtPlot() ); + newCurveSet->setParentQwtPlotNoReplot( m_targetPlot->viewer() ); } m_targetPlot->enableAutoPlotTitle( m_useAutoPlotTitleProxy() ); @@ -874,7 +874,7 @@ void RicSummaryCurveCreator::updateCurveNames() curve->updateCurveNameNoLegendUpdate(); } - if ( m_previewPlot && m_previewPlot->qwtPlot() ) m_previewPlot->qwtPlot()->updateLegend(); + if ( m_previewPlot && m_previewPlot->viewer() ) m_previewPlot->viewer()->updateLegend(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake index 888789b513..7f543db9eb 100644 --- a/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake @@ -13,7 +13,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogPlotFeatureImpl.h ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogPlotTrackFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicWellLogPlotCurveFeatureImpl.h ${CMAKE_CURRENT_LIST_DIR}/RicWellLogsImportFileFeature.h -${CMAKE_CURRENT_LIST_DIR}/RicDeleteWellLogPlotTrackFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicDeleteSubPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicWellLogPlotTrackFeatureImpl.h ${CMAKE_CURRENT_LIST_DIR}/RicPasteWellLogCurveFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicPasteWellLogTrackFeature.h @@ -44,7 +44,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogPlotFeatureImpl.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogPlotTrackFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicWellLogPlotCurveFeatureImpl.cpp ${CMAKE_CURRENT_LIST_DIR}/RicWellLogsImportFileFeature.cpp -${CMAKE_CURRENT_LIST_DIR}/RicDeleteWellLogPlotTrackFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicDeleteSubPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicWellLogPlotTrackFeatureImpl.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPasteWellLogCurveFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPasteWellLogTrackFeature.cpp diff --git a/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp index c950af9d96..a9e0dfcee7 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicAddWellLogToPlotFeature.cpp @@ -37,7 +37,7 @@ #include "RigWellLogFile.h" #include "RiaApplication.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" #include "cafSelectionManager.h" @@ -65,8 +65,8 @@ void RicAddWellLogToPlotFeature::onActionTriggered( bool isChecked ) RimWellLogPlot* plot = RicNewWellLogPlotFeatureImpl::createWellLogPlot(); RimWellLogTrack* plotTrack = new RimWellLogTrack(); - plot->addTrack( plotTrack ); - plotTrack->setDescription( QString( "Track %1" ).arg( plot->trackCount() ) ); + plot->addPlot( plotTrack ); + plotTrack->setDescription( QString( "Track %1" ).arg( plot->plotCount() ) ); plot->loadDataAndUpdate(); @@ -103,9 +103,7 @@ void RicAddWellLogToPlotFeature::onActionTriggered( bool isChecked ) curve->loadDataAndUpdate( true ); } } - plot->calculateAvailableDepthRange(); - plot->updateDepthZoom(); - plotTrack->viewer()->replot(); + plot->updateLayout(); RiaApplication::instance()->project()->updateConnectedEditors(); diff --git a/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp similarity index 63% rename from ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp rename to ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp index 9d2f054fe4..9f7cb2f830 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.cpp @@ -17,38 +17,38 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RicDeleteWellLogPlotTrackFeature.h" +#include "RicDeleteSubPlotFeature.h" #include "RicWellLogPlotCurveFeatureImpl.h" #include "RiaGuiApplication.h" +#include "RiuGridPlotWindow.h" #include "RiuPlotMainWindow.h" -#include "RiuWellLogPlot.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" -#include "RimWellLogPlot.h" -#include "RimWellLogTrack.h" +#include "RimGridPlotWindow.h" +#include "RimPlotInterface.h" #include "cafSelectionManager.h" #include -CAF_CMD_SOURCE_INIT( RicDeleteWellLogPlotTrackFeature, "RicDeleteWellLogPlotTrackFeature" ); +CAF_CMD_SOURCE_INIT( RicDeleteSubPlotFeature, "RicDeleteWellLogPlotTrackFeature" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RicDeleteWellLogPlotTrackFeature::isCommandEnabled() +bool RicDeleteSubPlotFeature::isCommandEnabled() { if ( RicWellLogPlotCurveFeatureImpl::parentWellAllocationPlot() ) return false; - std::vector selection; + std::vector selection; caf::SelectionManager::instance()->objectsByType( &selection ); if ( selection.size() > 0 ) { - RimWellLogPlot* wellLogPlot = nullptr; + RimGridPlotWindow* wellLogPlot = nullptr; selection[0]->firstAncestorOrThisOfType( wellLogPlot ); - if ( wellLogPlot && wellLogPlot->trackCount() > 1 ) + if ( dynamic_cast( selection[0] ) && wellLogPlot && wellLogPlot->plotCount() > 1 ) { return true; } @@ -60,38 +60,39 @@ bool RicDeleteWellLogPlotTrackFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicDeleteWellLogPlotTrackFeature::onActionTriggered( bool isChecked ) +void RicDeleteSubPlotFeature::onActionTriggered( bool isChecked ) { if ( RicWellLogPlotCurveFeatureImpl::parentWellAllocationPlot() ) return; - std::vector selection; + std::vector selection; caf::SelectionManager::instance()->objectsByType( &selection ); - RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); - std::set alteredWellLogPlots; + RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); + std::set alteredWellLogPlots; for ( size_t i = 0; i < selection.size(); i++ ) { - RimWellLogTrack* track = selection[i]; + RimPlotInterface* plot = dynamic_cast( selection[i] ); - RimWellLogPlot* wellLogPlot = nullptr; - track->firstAncestorOrThisOfType( wellLogPlot ); - if ( wellLogPlot && wellLogPlot->trackCount() > 1 ) + RimGridPlotWindow* wellLogPlot = nullptr; + selection[i]->firstAncestorOrThisOfType( wellLogPlot ); + if ( plot && wellLogPlot && wellLogPlot->plotCount() > 1 ) { alteredWellLogPlots.insert( wellLogPlot ); - wellLogPlot->removeTrack( track ); - caf::SelectionManager::instance()->removeObjectFromAllSelections( track ); + wellLogPlot->removePlot( plot ); + caf::SelectionManager::instance()->removeObjectFromAllSelections( selection[i] ); wellLogPlot->updateConnectedEditors(); - delete track; + delete plot; } } - for ( RimWellLogPlot* wellLogPlot : alteredWellLogPlots ) + for ( RimGridPlotWindow* wellLogPlot : alteredWellLogPlots ) { - RiuWellLogPlot* viewWidget = dynamic_cast( wellLogPlot->viewWidget() ); + RiuGridPlotWindow* viewWidget = dynamic_cast( wellLogPlot->viewWidget() ); plotWindow->setWidthOfMdiWindow( viewWidget, viewWidget->preferredWidth() ); - wellLogPlot->calculateAvailableDepthRange(); - wellLogPlot->updateDepthZoom(); + // TODO: add back with virtual methods + // wellLogPlot->calculateAvailableDepthRange(); + // wellLogPlot->updateDepthZoom(); wellLogPlot->uiCapability()->updateConnectedEditors(); } } @@ -99,7 +100,7 @@ void RicDeleteWellLogPlotTrackFeature::onActionTriggered( bool isChecked ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicDeleteWellLogPlotTrackFeature::setupActionLook( QAction* actionToSetup ) +void RicDeleteSubPlotFeature::setupActionLook( QAction* actionToSetup ) { actionToSetup->setText( "Delete Track" ); actionToSetup->setIcon( QIcon( ":/Erase.png" ) ); diff --git a/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.h b/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.h similarity index 95% rename from ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.h rename to ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.h index a72c16a9d4..f6b1daacf7 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicDeleteWellLogPlotTrackFeature.h +++ b/ApplicationCode/Commands/WellLogCommands/RicDeleteSubPlotFeature.h @@ -24,7 +24,7 @@ //================================================================================================== /// //================================================================================================== -class RicDeleteWellLogPlotTrackFeature : public caf::CmdFeature +class RicDeleteSubPlotFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp index 86c3104ea2..42d0810c6d 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp @@ -112,8 +112,8 @@ void RicNewPltPlotFeature::onActionTriggered( bool isChecked ) pltPlot->setCurrentWellName( wellPathName ); RimWellLogTrack* plotTrack = new RimWellLogTrack(); - pltPlot->addTrack( plotTrack ); - plotTrack->setDescription( QString( "Track %1" ).arg( pltPlot->trackCount() ) ); + pltPlot->addPlot( plotTrack ); + plotTrack->setDescription( QString( "Track %1" ).arg( pltPlot->plotCount() ) ); pltPlotColl->addPlot( pltPlot ); pltPlot->setDescription( plotName ); diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp index a14fe5c050..f544245fd6 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewRftPlotFeature.cpp @@ -73,8 +73,8 @@ void RicNewRftPlotFeature::onActionTriggered( bool isChecked ) rftPlot->setSimWellOrWellPathName( wellName ); RimWellLogTrack* plotTrack = new RimWellLogTrack(); - rftPlot->addTrack( plotTrack ); - plotTrack->setDescription( QString( "Track %1" ).arg( rftPlot->trackCount() ) ); + rftPlot->addPlot( plotTrack ); + plotTrack->setDescription( QString( "Track %1" ).arg( rftPlot->plotCount() ) ); rftPlotColl->addPlot( rftPlot ); rftPlot->applyInitialSelections(); diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp index 8ae7fded85..915ddbe8cd 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellBoreStabilityPlotFeature.cpp @@ -99,10 +99,10 @@ RimWellBoreStabilityPlot* plot->enableAllAutoNameTags( true ); plot->setPlotTitleVisible( true ); - plot->setTrackLegendsVisible( true ); - plot->setTrackLegendsHorizontal( true ); + plot->setLegendsVisible( true ); + plot->setLegendsHorizontal( true ); plot->setDepthType( RimWellLogPlot::TRUE_VERTICAL_DEPTH ); - plot->setDepthAutoZoom( true ); + plot->setAutoScaleYEnabled( true ); RicNewWellLogPlotFeatureImpl::updateAfterCreation( plot ); } @@ -191,7 +191,7 @@ void RicNewWellBoreStabilityPlotFeature::createFormationTrack( RimWellBoreStabil formationTrack->setFormationCase( geoMechCase ); formationTrack->setAnnotationType( RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ); formationTrack->setVisibleXRange( 0.0, 0.0 ); - formationTrack->setWidthScaleFactor( RimWellLogTrack::NARROW_TRACK ); + formationTrack->setWidthScaleFactor( RimWellLogTrack::NARROW ); } //-------------------------------------------------------------------------------------------------- @@ -202,7 +202,7 @@ void RicNewWellBoreStabilityPlotFeature::createCasingShoeTrack( RimWellBoreStabi RimGeoMechCase* geoMechCase ) { RimWellLogTrack* casingShoeTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Well Design", plot ); - casingShoeTrack->setWidthScaleFactor( RimWellLogTrack::NARROW_TRACK ); + casingShoeTrack->setWidthScaleFactor( RimWellLogTrack::NARROW ); casingShoeTrack->setFormationWellPath( wellPath ); casingShoeTrack->setFormationCase( geoMechCase ); casingShoeTrack->setAnnotationType( RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ); @@ -226,7 +226,7 @@ void RicNewWellBoreStabilityPlotFeature::createParametersTrack( RimWellBoreStabi RimWellLogTrack* paramCurvesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "WBS Parameters", plot ); - paramCurvesTrack->setWidthScaleFactor( RimWellLogTrack::WIDE_TRACK ); + paramCurvesTrack->setWidthScaleFactor( RimWellLogTrack::WIDE ); paramCurvesTrack->setAutoScaleXEnabled( true ); paramCurvesTrack->setTickIntervals( 0.5, 0.05 ); paramCurvesTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR ); @@ -234,7 +234,7 @@ void RicNewWellBoreStabilityPlotFeature::createParametersTrack( RimWellBoreStabi paramCurvesTrack->setFormationCase( geoMechCase ); paramCurvesTrack->setAnnotationType( RiuPlotAnnotationTool::CURVE_ANNOTATIONS ); paramCurvesTrack->setShowRegionLabels( true ); - paramCurvesTrack->setVisible( false ); + paramCurvesTrack->setChecked( false ); std::vector resultNames = RiaDefines::wellPathStabilityParameterNames(); std::vector colors = {cvf::Color3f::CRIMSON, cvf::Color3f::DARK_YELLOW}; @@ -258,7 +258,7 @@ void RicNewWellBoreStabilityPlotFeature::createParametersTrack( RimWellBoreStabi curve->loadDataAndUpdate( false ); curve->setAutoNameComponents( false, true, false, false, false ); } - paramCurvesTrack->calculateXZoomRangeAndUpdateQwt(); + paramCurvesTrack->setAutoScaleXEnabled( true ); } //-------------------------------------------------------------------------------------------------- @@ -272,7 +272,7 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBore RimWellLogTrack* stabilityCurvesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Stability Curves", plot ); - stabilityCurvesTrack->setWidthScaleFactor( RimWellLogTrack::EXTRA_WIDE_TRACK ); + stabilityCurvesTrack->setWidthScaleFactor( RimWellLogTrack::EXTRA_WIDE ); stabilityCurvesTrack->setAutoScaleXEnabled( true ); stabilityCurvesTrack->setTickIntervals( 0.5, 0.05 ); stabilityCurvesTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR ); @@ -309,7 +309,7 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBore curve->setSmoothCurve( true ); curve->setSmoothingThreshold( 0.002 ); } - stabilityCurvesTrack->calculateXZoomRangeAndUpdateQwt(); + stabilityCurvesTrack->setAutoScaleXEnabled( true ); } //-------------------------------------------------------------------------------------------------- @@ -366,7 +366,7 @@ void RicNewWellBoreStabilityPlotFeature::createAnglesTrack( RimWellBoreStability maxValue = cvf::Math::clamp( maxValue, angleIncrement, 360.0 ); minValue = cvf::Math::clamp( minValue, 0.0, maxValue - 90.0 ); } - wellPathAnglesTrack->setWidthScaleFactor( RimWellLogTrack::NORMAL_TRACK ); + wellPathAnglesTrack->setWidthScaleFactor( RimWellLogTrack::NORMAL ); wellPathAnglesTrack->setVisibleXRange( minValue, maxValue ); wellPathAnglesTrack->setTickIntervals( 90.0, 30.0 ); wellPathAnglesTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR ); diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp index aadf238cf0..0e084e653f 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotFeatureImpl.cpp @@ -165,14 +165,14 @@ RimWellLogTrack* RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( bool } RimWellLogTrack* plotTrack = new RimWellLogTrack(); - plot->addTrack( plotTrack ); + plot->addPlot( plotTrack ); if ( !trackDescription.isEmpty() ) { plotTrack->setDescription( trackDescription ); } else { - plotTrack->setDescription( QString( "Track %1" ).arg( plot->trackCount() ) ); + plotTrack->setDescription( QString( "Track %1" ).arg( plot->plotCount() ) ); } if ( caseToApply ) @@ -224,10 +224,6 @@ void RicNewWellLogPlotFeatureImpl::updateAfterCreation( RimWellLogPlot* plot ) { CVF_ASSERT( plot ); plot->loadDataAndUpdate(); - plot->updateDepthZoom(); - plot->updateConnectedEditors(); - plot->updateTracks(); - RiaApplication::instance()->project()->updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp index 425595d3e9..1111365902 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicNewWellLogPlotTrackFeature.cpp @@ -21,8 +21,8 @@ #include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" +#include "RiuQwtPlotWidget.h" #include "RiuWellLogPlot.h" -#include "RiuWellLogTrack.h" #include "RicNewWellLogCurveExtractionFeature.h" #include "RicWellLogPlotCurveFeatureImpl.h" @@ -62,8 +62,8 @@ void RicNewWellLogPlotTrackFeature::onActionTriggered( bool isChecked ) if ( wellLogPlot ) { RimWellLogTrack* plotTrack = new RimWellLogTrack; - wellLogPlot->addTrack( plotTrack ); - plotTrack->setDescription( QString( "Track %1" ).arg( wellLogPlot->trackCount() ) ); + wellLogPlot->addPlot( plotTrack ); + plotTrack->setDescription( QString( "Track %1" ).arg( wellLogPlot->plotCount() ) ); RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); RiuWellLogPlot* viewWidget = dynamic_cast( wellLogPlot->viewWidget() ); RicWellLogTools::addWellLogExtractionCurve( plotTrack, nullptr, nullptr, nullptr, nullptr, -1, true ); diff --git a/ApplicationCode/Commands/WellLogCommands/RicPasteWellLogTrackFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicPasteWellLogTrackFeature.cpp index 785c89bb32..9c50e0e78f 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicPasteWellLogTrackFeature.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicPasteWellLogTrackFeature.cpp @@ -81,9 +81,9 @@ void RicPasteWellLogTrackFeature::onActionTriggered( bool isChecked ) fileCurve->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) ); CVF_ASSERT( newObject ); - wellLogPlot->addTrack( newObject ); + wellLogPlot->addPlot( newObject ); - newObject->setDescription( QString( "Track %1" ).arg( wellLogPlot->trackCount() ) ); + newObject->setDescription( QString( "Track %1" ).arg( wellLogPlot->plotCount() ) ); // Resolve references after object has been inserted into the project data model newObject->resolveReferencesRecursively(); diff --git a/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp b/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp index 15986fee09..a73ee87de5 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp +++ b/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.cpp @@ -21,8 +21,8 @@ #include "RiaGuiApplication.h" #include "RiuPlotMainWindow.h" +#include "RiuQwtPlotWidget.h" #include "RiuWellLogPlot.h" -#include "RiuWellLogTrack.h" #include "RimWellLogCurve.h" #include "RimWellLogPlot.h" @@ -74,59 +74,42 @@ void RicWellLogPlotTrackFeatureImpl::moveCurvesToWellLogPlotTrack( RimWellLogTra for ( std::set::iterator tIt = srcTracks.begin(); tIt != srcTracks.end(); ++tIt ) { + ( *tIt )->setAutoScaleXEnabled( true ); ( *tIt )->updateParentPlotZoom(); - ( *tIt )->calculateXZoomRangeAndUpdateQwt(); } destTrack->loadDataAndUpdate(); + destTrack->setAutoScaleXEnabled( true ); destTrack->updateParentPlotZoom(); - destTrack->calculateXZoomRangeAndUpdateQwt(); destTrack->updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicWellLogPlotTrackFeatureImpl::moveTracksToWellLogPlot( RimWellLogPlot* dstWellLogPlot, - const std::vector& tracksToMove, - RimWellLogTrack* trackToInsertAfter ) +void RicWellLogPlotTrackFeatureImpl::movePlotsToGridPlotWindow( RimGridPlotWindow* gridPlotWindow, + const std::vector& plotsToMove, + RimPlotInterface* plotToInsertAfter ) { - CVF_ASSERT( dstWellLogPlot ); + CVF_ASSERT( gridPlotWindow ); - std::set srcPlots; - - for ( size_t tIdx = 0; tIdx < tracksToMove.size(); tIdx++ ) + for ( size_t tIdx = 0; tIdx < plotsToMove.size(); tIdx++ ) { - RimWellLogTrack* track = tracksToMove[tIdx]; - - RimWellLogPlot* srcPlot; - track->firstAncestorOrThisOfType( srcPlot ); + RimPlotInterface* plot = plotsToMove[tIdx]; + caf::PdmObject* pdmObject = dynamic_cast( plot ); + RimGridPlotWindow* srcPlot; + pdmObject->firstAncestorOrThisOfType( srcPlot ); if ( srcPlot ) { - srcPlot->removeTrack( track ); - - srcPlots.insert( srcPlot ); + srcPlot->removePlot( plot ); } } - for ( std::set::iterator pIt = srcPlots.begin(); pIt != srcPlots.end(); ++pIt ) - { - ( *pIt )->calculateAvailableDepthRange(); - ( *pIt )->updateDepthZoom(); - ( *pIt )->updateTrackNames(); - ( *pIt )->updateConnectedEditors(); - } - size_t insertionStartIndex = 0; - if ( trackToInsertAfter ) insertionStartIndex = dstWellLogPlot->trackIndex( trackToInsertAfter ) + 1; + if ( plotToInsertAfter ) insertionStartIndex = gridPlotWindow->plotIndex( plotToInsertAfter ) + 1; - for ( size_t tIdx = 0; tIdx < tracksToMove.size(); tIdx++ ) + for ( size_t tIdx = 0; tIdx < plotsToMove.size(); tIdx++ ) { - dstWellLogPlot->insertTrack( tracksToMove[tIdx], insertionStartIndex + tIdx ); + gridPlotWindow->insertPlot( plotsToMove[tIdx], insertionStartIndex + tIdx ); } - dstWellLogPlot->calculateAvailableDepthRange(); - dstWellLogPlot->updateDepthZoom(); - dstWellLogPlot->updateTrackNames(); - dstWellLogPlot->updateTracks(); - dstWellLogPlot->updateConnectedEditors(); } diff --git a/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.h b/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.h index ce811cdb55..597d6a3496 100644 --- a/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.h +++ b/ApplicationCode/Commands/WellLogCommands/RicWellLogPlotTrackFeatureImpl.h @@ -21,6 +21,8 @@ #include +class RimGridPlotWindow; +class RimPlotInterface; class RimWellLogPlot; class RimWellLogTrack; class RimWellLogCurve; @@ -34,7 +36,7 @@ public: static void moveCurvesToWellLogPlotTrack( RimWellLogTrack* dstTrack, const std::vector& curves, RimWellLogCurve* insertAfterCurve ); - static void moveTracksToWellLogPlot( RimWellLogPlot* wellLogPlot, - const std::vector& tracks, - RimWellLogTrack* trackToInsertAfter ); + static void movePlotsToGridPlotWindow( RimGridPlotWindow* gridPlotWindow, + const std::vector& plots, + RimPlotInterface* plotToInsertAfter ); }; diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index b11efd1821..055f2670e1 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -72,7 +72,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RimMainPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimRftPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimPltPlotCollection.h -${CMAKE_CURRENT_LIST_DIR}/RimPlot.h +${CMAKE_CURRENT_LIST_DIR}/RimPlotInterface.h +${CMAKE_CURRENT_LIST_DIR}/RimPlotWindow.h +${CMAKE_CURRENT_LIST_DIR}/RimGridPlotWindow.h ${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlot.h ${CMAKE_CURRENT_LIST_DIR}/RimWellLogTrack.h ${CMAKE_CURRENT_LIST_DIR}/RimWellLogCurve.h @@ -212,7 +214,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RimMainPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimRftPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimPltPlotCollection.cpp -${CMAKE_CURRENT_LIST_DIR}/RimPlot.cpp +${CMAKE_CURRENT_LIST_DIR}/RimPlotInterface.cpp +${CMAKE_CURRENT_LIST_DIR}/RimPlotWindow.cpp +${CMAKE_CURRENT_LIST_DIR}/RimGridPlotWindow.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlot.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellBoreStabilityPlot.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellLogTrack.cpp diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 7d41e07e0f..8466068737 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -46,8 +46,8 @@ #include "RimWellLogFile.h" #include "RimWellPlotTools.h" #include "RiuPlotMainWindow.h" +#include "RiuQwtPlotWidget.h" #include "RiuWellAllocationPlot.h" -#include "RiuWellLogTrack.h" CAF_PDM_SOURCE_INIT( RimWellAllocationPlot, "WellAllocationPlot" ); @@ -100,7 +100,7 @@ RimWellAllocationPlot::RimWellAllocationPlot() m_accumulatedWellFlowPlot = new RimWellLogPlot; m_accumulatedWellFlowPlot->setDepthUnit( RiaDefines::UNIT_NONE ); m_accumulatedWellFlowPlot->setDepthType( RimWellLogPlot::CONNECTION_NUMBER ); - m_accumulatedWellFlowPlot->setTrackLegendsVisible( false ); + m_accumulatedWellFlowPlot->setLegendsVisible( false ); m_accumulatedWellFlowPlot->uiCapability()->setUiIconFromResourceString( ":/WellFlowPlot16x16.png" ); CAF_PDM_InitFieldNoDefault( &m_totalWellAllocationPlot, "TotalWellFlowPlot", "Total Well Flow", "", "", "" ); @@ -189,12 +189,12 @@ void RimWellAllocationPlot::updateFromWell() for ( RimWellLogTrack* t : tracks ) { - accumulatedWellFlowPlot()->removeTrack( t ); + accumulatedWellFlowPlot()->removePlot( t ); delete t; } } - CVF_ASSERT( accumulatedWellFlowPlot()->trackCount() == 0 ); + CVF_ASSERT( accumulatedWellFlowPlot()->plotCount() == 0 ); QString description; if ( m_flowType() == ACCUMULATED ) description = "Accumulated Flow"; @@ -270,7 +270,7 @@ void RimWellAllocationPlot::updateFromWell() plotTrack->setFormationsForCaseWithSimWellOnly( true ); plotTrack->setFormationBranchIndex( (int)brIdx ); - accumulatedWellFlowPlot()->addTrack( plotTrack ); + accumulatedWellFlowPlot()->addPlot( plotTrack ); const std::vector& depthValues = depthType == RimWellLogPlot::CONNECTION_NUMBER ? wfCalculator->connectionNumbersFromTop( brIdx ) @@ -865,9 +865,13 @@ cvf::Color3f RimWellAllocationPlot::getTracerColor( const QString& tracerName ) //-------------------------------------------------------------------------------------------------- void RimWellAllocationPlot::updateFormationNamesData() const { - for ( size_t i = 0; i < m_accumulatedWellFlowPlot->trackCount(); ++i ) + for ( size_t i = 0; i < m_accumulatedWellFlowPlot->plotCount(); ++i ) { - RimWellLogTrack* track = m_accumulatedWellFlowPlot->trackByIndex( i ); - track->setAndUpdateSimWellFormationNamesData( m_case, m_wellName ); + RimWellLogTrack* track = dynamic_cast( m_accumulatedWellFlowPlot->plotByIndex( i ) ); + CAF_ASSERT( track ); + if ( track ) + { + track->setAndUpdateSimWellFormationNamesData( m_case, m_wellName ); + } } } diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellFlowRateCurve.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellFlowRateCurve.cpp index f68f086e4e..cff8accfe2 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellFlowRateCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellFlowRateCurve.cpp @@ -216,7 +216,7 @@ void RimWellFlowRateCurve::updateStackedPlotData() RimWellLogTrack* wellLogTrack; firstAncestorOrThisOfTypeAsserted( wellLogTrack ); - bool isFirstTrack = ( wellLogTrack == wellLogPlot->trackByIndex( 0 ) ); + bool isFirstTrack = ( wellLogTrack == wellLogPlot->plotByIndex( 0 ) ); RiaDefines::DepthUnitType displayUnit = RiaDefines::UNIT_NONE; @@ -271,7 +271,7 @@ void RimWellFlowRateCurve::updateStackedPlotData() stackedValues.insert( stackedValues.begin(), 0.0 ); polyLineStartStopIndices.front().second += 1; - if ( wellLogPlot->trackCount() > 1 && isFirstTrack ) + if ( wellLogPlot->plotCount() > 1 && isFirstTrack ) { // Add a dummy negative depth value to make the contribution // from other branches connected to well head visible diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp index 1a664a884e..a2970717cf 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp @@ -229,26 +229,31 @@ void RimWellPltPlot::setPlotXAxisTitles( RimWellLogTrack* plotTrack ) //-------------------------------------------------------------------------------------------------- void RimWellPltPlot::updateFormationsOnPlot() const { - if ( trackCount() > 0 ) + if ( plotCount() > 0 ) { RimProject* proj = RiaApplication::instance()->project(); RimWellPath* wellPath = proj->wellPathByName( m_wellPathName ); - RimCase* formationNamesCase = trackByIndex( 0 )->formationNamesCase(); - - if ( !formationNamesCase ) + RimWellLogTrack* track = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( track ); + if ( track ) { - /// Set default case. Todo : Use the first of the selected cases in the plot - std::vector cases; - proj->allCases( cases ); + RimCase* formationNamesCase = track->formationNamesCase(); - if ( !cases.empty() ) + if ( !formationNamesCase ) { - formationNamesCase = cases[0]; - } - } + /// Set default case. Todo : Use the first of the selected cases in the plot + std::vector cases; + proj->allCases( cases ); - trackByIndex( 0 )->setAndUpdateWellPathFormationNamesData( formationNamesCase, wellPath ); + if ( !cases.empty() ) + { + formationNamesCase = cases[0]; + } + } + + track->setAndUpdateWellPathFormationNamesData( formationNamesCase, wellPath ); + } } } @@ -486,7 +491,11 @@ public: //-------------------------------------------------------------------------------------------------- void RimWellPltPlot::syncCurvesFromUiSelection() { - RimWellLogTrack* plotTrack = trackByIndex( 0 ); + RimWellLogTrack* plotTrack = dynamic_cast( plotByIndex( 0 ) ); + + CAF_ASSERT( plotTrack ); + if ( !plotTrack ) return; + const std::set& curveDefs = selectedCurveDefs(); setPlotXAxisTitles( plotTrack ); @@ -700,8 +709,8 @@ void RimWellPltPlot::syncCurvesFromUiSelection() curveGroupId++; } + plotTrack->setAutoScaleXEnabled( true ); RimWellLogPlot::onLoadDataAndUpdate(); - plotTrack->calculateXZoomRange(); } //-------------------------------------------------------------------------------------------------- @@ -886,11 +895,15 @@ void RimWellPltPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, if ( changedField == &m_wellPathName ) { - RimWellLogTrack* const plotTrack = trackByIndex( 0 ); - plotTrack->deleteAllCurves(); - m_selectedSources.v().clear(); - m_selectedTimeSteps.v().clear(); - updateFormationsOnPlot(); + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) + { + plotTrack->deleteAllCurves(); + m_selectedSources.v().clear(); + m_selectedTimeSteps.v().clear(); + updateFormationsOnPlot(); + } } else if ( changedField == &m_selectedSources ) { @@ -924,20 +937,28 @@ void RimWellPltPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, updateFormationsOnPlot(); syncSourcesIoFieldFromGuiField(); syncCurvesFromUiSelection(); - updateDepthZoom(); - RimWellLogTrack* const plotTrack = trackByIndex( 0 ); - plotTrack->calculateXZoomRangeAndUpdateQwt(); + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) + { + plotTrack->setAutoScaleXEnabled( true ); + } + updateZoom(); } if ( changedField == &m_useStandardConditionCurves || changedField == &m_useReservoirConditionCurves || changedField == &m_phases ) { syncCurvesFromUiSelection(); - updateDepthZoom(); - RimWellLogTrack* const plotTrack = trackByIndex( 0 ); - plotTrack->calculateXZoomRangeAndUpdateQwt(); + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) + { + plotTrack->setAutoScaleXEnabled( true ); + } + updateZoom(); } } @@ -970,20 +991,23 @@ void RimWellPltPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& flowGroup->add( &m_phases ); - if ( trackCount() > 0 ) + if ( plotCount() > 0 ) { - RimWellLogTrack* track = trackByIndex( 0 ); + RimWellLogTrack* const track = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( track ); + if ( track ) + { + track->uiOrderingForRftPltFormations( uiOrdering ); - track->uiOrderingForRftPltFormations( uiOrdering ); + caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup( "Legend and Axis" ); + legendAndAxisGroup->setCollapsedByDefault( true ); - caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup( "Legend and Axis" ); - legendAndAxisGroup->setCollapsedByDefault( true ); + createPlotSettingsUiGroup( *legendAndAxisGroup ); - uiOrderingForPlotSettings( *legendAndAxisGroup ); + track->uiOrderingForXAxisSettings( *legendAndAxisGroup ); - track->uiOrderingForXAxisSettings( *legendAndAxisGroup ); - - uiOrderingForDepthAxis( *legendAndAxisGroup ); + uiOrderingForDepthAxis( *legendAndAxisGroup ); + } } uiOrdering.skipRemainingFields( true ); @@ -1098,9 +1122,14 @@ void RimWellPltPlot::onLoadDataAndUpdate() if ( m_isOnLoad ) { - if ( trackCount() > 0 ) + if ( plotCount() > 0 ) { - trackByIndex( 0 )->setAnnotationType( RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ); + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) + { + plotTrack->setAnnotationType( RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ); + } } m_isOnLoad = false; } diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellRftPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellRftPlot.cpp index 18212697d1..d3fd6789a0 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellRftPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellRftPlot.cpp @@ -53,7 +53,7 @@ #include "RimWellPlotTools.h" #include "RimWellPltPlot.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" #include "cafPdmUiTreeOrdering.h" #include "cafPdmUiTreeSelectionEditor.h" @@ -118,7 +118,7 @@ RimWellRftPlot::RimWellRftPlot() m_wellPathCollection = RiaApplication::instance()->project()->activeOilField()->wellPathCollection(); m_nameConfig->setCustomName( "RFT Plot" ); - m_trackLegendsHorizontal = true; + m_plotLegendsHorizontal = true; this->setAsPlotMdiWindow(); m_isOnLoad = true; @@ -150,10 +150,10 @@ void RimWellRftPlot::applyCurveAppearance( RimWellLogCurve* newCurve ) currentColor = m_dataSourceColors[sourceAddress]; if ( m_showStatisticsCurves ) { - if ( trackByIndex( 0 ) && trackByIndex( 0 )->viewer() ) + if ( plotByIndex( 0 ) && plotByIndex( 0 )->viewer() ) { cvf::Color3f backgroundColor = RiaColorTools::fromQColorTo3f( - trackByIndex( 0 )->viewer()->canvasBackground().color() ); + plotByIndex( 0 )->viewer()->canvasBackground().color() ); currentColor = RiaColorTools::blendCvfColors( backgroundColor, currentColor, 2, 1 ); } } @@ -185,35 +185,41 @@ void RimWellRftPlot::applyCurveAppearance( RimWellLogCurve* newCurve ) //-------------------------------------------------------------------------------------------------- void RimWellRftPlot::updateFormationsOnPlot() const { - if ( trackCount() > 0 ) + if ( plotCount() > 0 ) { RimProject* proj = RiaApplication::instance()->project(); RimWellPath* wellPath = proj->wellPathByName( m_wellPathNameOrSimWellName ); - RimCase* formationNamesCase = trackByIndex( 0 )->formationNamesCase(); - - if ( !formationNamesCase ) + RimCase* formationNamesCase = nullptr; + RimWellLogTrack* track = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( track ); + if ( track ) { - /// Set default case. Todo : Use the first of the selected cases in the plot - std::vector cases; - proj->allCases( cases ); + formationNamesCase = track->formationNamesCase(); - if ( !cases.empty() ) + if ( !formationNamesCase ) { - formationNamesCase = cases[0]; - } - } + /// Set default case. Todo : Use the first of the selected cases in the plot + std::vector cases; + proj->allCases( cases ); - if ( wellPath ) - { - trackByIndex( 0 )->setAndUpdateWellPathFormationNamesData( formationNamesCase, wellPath ); - } - else - { - trackByIndex( 0 )->setAndUpdateSimWellFormationNamesAndBranchData( formationNamesCase, - associatedSimWellName(), - m_branchIndex, - m_branchDetection ); + if ( !cases.empty() ) + { + formationNamesCase = cases[0]; + } + } + + if ( wellPath ) + { + track->setAndUpdateWellPathFormationNamesData( formationNamesCase, wellPath ); + } + else + { + track->setAndUpdateSimWellFormationNamesAndBranchData( formationNamesCase, + associatedSimWellName(), + m_branchIndex, + m_branchDetection ); + } } } } @@ -360,7 +366,10 @@ void RimWellRftPlot::updateEditorsFromCurves() //-------------------------------------------------------------------------------------------------- void RimWellRftPlot::syncCurvesFromUiSelection() { - RimWellLogTrack* plotTrack = trackByIndex( 0 ); + RimWellLogTrack* plotTrack = dynamic_cast( plotByIndex( 0 ) ); + + CAF_ASSERT( plotTrack ); + if ( !plotTrack ) return; const std::set& allCurveDefs = selectedCurveDefs(); const std::set& curveDefsInPlot = curveDefsFromCurves(); @@ -379,7 +388,7 @@ void RimWellRftPlot::syncCurvesFromUiSelection() allCurveDefs.end(), std::inserter( deleteCurveDefs, deleteCurveDefs.end() ) ); - for ( RimWellLogCurve* const curve : plotTrack->curvesVector() ) + for ( RimWellLogCurve* const curve : plotTrack->curves() ) { RiaRftPltCurveDefinition curveDef = RimWellPlotTools::curveDefFromCurve( curve ); if ( deleteCurveDefs.count( curveDef ) > 0 ) @@ -422,10 +431,14 @@ std::set RimWellRftPlot::curveDefsFromCurves() const { std::set curveDefs; - RimWellLogTrack* const plotTrack = trackByIndex( 0 ); - for ( RimWellLogCurve* const curve : plotTrack->curvesVector() ) + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) { - curveDefs.insert( RimWellPlotTools::curveDefFromCurve( curve ) ); + for ( RimWellLogCurve* const curve : plotTrack->curves() ) + { + curveDefs.insert( RimWellPlotTools::curveDefFromCurve( curve ) ); + } } return curveDefs; } @@ -437,8 +450,11 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set& curveDefsToAdd, const std::set& curvesToDelete ) { - const QString simWellName = associatedSimWellName(); - RimWellLogTrack* const plotTrack = trackByIndex( 0 ); + const QString simWellName = associatedSimWellName(); + + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( !plotTrack ) return; // Delete curves plotTrack->deleteAllCurves(); @@ -666,16 +682,20 @@ const char* RimWellRftPlot::plotNameFormatString() //-------------------------------------------------------------------------------------------------- void RimWellRftPlot::deleteCurvesAssosicatedWithObservedData( const RimObservedFmuRftData* observedFmuRftData ) { - for ( auto track : tracks() ) + for ( auto plot : plots() ) { - auto curves = track->curvesVector(); - for ( auto curve : curves ) + RimWellLogTrack* const track = dynamic_cast( plot ); + if ( track ) { - RimWellLogRftCurve* rftCurve = dynamic_cast( curve ); - if ( rftCurve && rftCurve->observedFmuRftData() == observedFmuRftData ) + auto curves = track->curves(); + for ( auto curve : curves ) { - track->takeOutCurve( rftCurve ); - delete rftCurve; + RimWellLogRftCurve* rftCurve = dynamic_cast( curve ); + if ( rftCurve && rftCurve->observedFmuRftData() == observedFmuRftData ) + { + track->takeOutCurve( rftCurve ); + delete rftCurve; + } } } } @@ -821,7 +841,7 @@ void RimWellRftPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, m_branchIndex = 0; - RimWellLogTrack* const plotTrack = trackByIndex( 0 ); + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); if ( plotTrack ) { plotTrack->deleteAllCurves(); @@ -899,18 +919,21 @@ void RimWellRftPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* timeStepsGroup = uiOrdering.addNewGroupWithKeyword( "Time Steps", "TimeSteps" ); timeStepsGroup->add( &m_selectedTimeSteps ); - if ( trackCount() > 0 ) + if ( plotCount() > 0 ) { - RimWellLogTrack* track = trackByIndex( 0 ); + RimWellLogTrack* const track = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( track ); + if ( track ) + { + track->uiOrderingForRftPltFormations( uiOrdering ); - track->uiOrderingForRftPltFormations( uiOrdering ); + caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup( "Legend and Axis" ); + legendAndAxisGroup->setCollapsedByDefault( true ); - caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup( "Legend and Axis" ); - legendAndAxisGroup->setCollapsedByDefault( true ); - - uiOrderingForPlotSettings( *legendAndAxisGroup ); - track->uiOrderingForXAxisSettings( *legendAndAxisGroup ); - uiOrderingForDepthAxis( *legendAndAxisGroup ); + createPlotSettingsUiGroup( *legendAndAxisGroup ); + track->uiOrderingForXAxisSettings( *legendAndAxisGroup ); + uiOrderingForDepthAxis( *legendAndAxisGroup ); + } } uiOrdering.skipRemainingFields( true ); @@ -985,9 +1008,14 @@ void RimWellRftPlot::onLoadDataAndUpdate() { if ( m_isOnLoad ) { - if ( trackCount() > 0 ) + if ( plotCount() > 0 ) { - trackByIndex( 0 )->setAnnotationType( RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ); + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) + { + plotTrack->setAnnotationType( RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ); + } } m_isOnLoad = false; @@ -1042,13 +1070,18 @@ void RimWellRftPlot::assignWellPathToExtractionCurves() if ( wellPath ) { - for ( RimWellLogCurve* curve : trackByIndex( 0 )->curvesVector() ) + RimWellLogTrack* const plotTrack = dynamic_cast( plotByIndex( 0 ) ); + CAF_ASSERT( plotTrack ); + if ( plotTrack ) { - auto extractionCurve = dynamic_cast( curve ); - if ( extractionCurve ) + for ( RimWellLogCurve* curve : plotTrack->curves() ) { - extractionCurve->setTrajectoryType( RimWellLogExtractionCurve::WELL_PATH ); - extractionCurve->setWellPath( wellPath ); + auto extractionCurve = dynamic_cast( curve ); + if ( extractionCurve ) + { + extractionCurve->setTrajectoryType( RimWellLogExtractionCurve::WELL_PATH ); + extractionCurve->setWellPath( wellPath ); + } } } } @@ -1138,14 +1171,6 @@ void RimWellRftPlot::defineCurveColorsAndSymbols( const std::set& allCurveDefs ); - void onDepthTypeChanged() override; - private: caf::PdmField m_wellPathNameOrSimWellName; caf::PdmField m_branchIndex; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp index d7681912b9..e1cb786bd4 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp @@ -88,6 +88,14 @@ RimGridCrossPlot::~RimGridCrossPlot() deleteViewWidget(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridCrossPlot::isChecked() const +{ + return isWindowVisible(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -139,7 +147,15 @@ std::vector RimGridCrossPlot::dataSets() const //-------------------------------------------------------------------------------------------------- QWidget* RimGridCrossPlot::viewWidget() { - return m_qwtPlot; + return m_plotWidget; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuQwtPlotWidget* RimGridCrossPlot::viewer() +{ + return m_plotWidget; } //-------------------------------------------------------------------------------------------------- @@ -149,9 +165,9 @@ QImage RimGridCrossPlot::snapshotWindowContent() { QImage image; - if ( m_qwtPlot ) + if ( m_plotWidget ) { - QPixmap pix = m_qwtPlot->grab(); + QPixmap pix = m_plotWidget->grab(); image = pix.toImage(); } @@ -163,16 +179,10 @@ QImage RimGridCrossPlot::snapshotWindowContent() //-------------------------------------------------------------------------------------------------- void RimGridCrossPlot::zoomAll() { - if ( !m_qwtPlot ) return; + setAutoScaleXEnabled( true ); + setAutoScaleYEnabled( true ); - setAutoZoomForAllAxes( true ); - updateAxisInQwt( RiaDefines::PLOT_AXIS_LEFT ); - updateAxisInQwt( RiaDefines::PLOT_AXIS_BOTTOM ); - - m_qwtPlot->replot(); - - updateAxisFromQwt( RiaDefines::PLOT_AXIS_LEFT ); - updateAxisFromQwt( RiaDefines::PLOT_AXIS_BOTTOM ); + updateZoomInQwt(); } //-------------------------------------------------------------------------------------------------- @@ -180,9 +190,9 @@ void RimGridCrossPlot::zoomAll() //-------------------------------------------------------------------------------------------------- void RimGridCrossPlot::calculateZoomRangeAndUpdateQwt() { - if ( m_qwtPlot ) + if ( m_plotWidget ) { - m_qwtPlot->replot(); + m_plotWidget->scheduleReplot(); } } @@ -191,17 +201,17 @@ void RimGridCrossPlot::calculateZoomRangeAndUpdateQwt() //-------------------------------------------------------------------------------------------------- void RimGridCrossPlot::reattachCurvesToQwtAndReplot() { - if ( m_qwtPlot ) + if ( m_plotWidget ) { for ( auto dataSet : m_crossPlotDataSets ) { dataSet->detachAllCurves(); if ( dataSet->isChecked() ) { - dataSet->setParentQwtPlotNoReplot( m_qwtPlot ); + dataSet->setParentQwtPlotNoReplot( m_plotWidget ); } } - updateAxisDisplay(); + updateZoomInQwt(); } } @@ -289,68 +299,39 @@ void RimGridCrossPlot::detachAllCurves() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridCrossPlot::updateAxisScaling() +void RimGridCrossPlot::loadDataAndUpdate() { - loadDataAndUpdate(); + onLoadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridCrossPlot::updateAxisDisplay() +void RimGridCrossPlot::setAutoScaleXEnabled( bool enabled ) { - if ( !m_qwtPlot ) return; - - updateAxisInQwt( RiaDefines::PLOT_AXIS_BOTTOM ); - updateAxisInQwt( RiaDefines::PLOT_AXIS_LEFT ); - - m_qwtPlot->updateAnnotationObjects( m_xAxisProperties ); - m_qwtPlot->updateAnnotationObjects( m_yAxisProperties ); - - m_qwtPlot->replot(); + m_xAxisProperties->setAutoZoom( enabled ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridCrossPlot::updateZoomWindowFromQwt() +void RimGridCrossPlot::setAutoScaleYEnabled( bool enabled ) { - if ( !m_qwtPlot ) return; - - updateAxisFromQwt( RiaDefines::PLOT_AXIS_LEFT ); - updateAxisFromQwt( RiaDefines::PLOT_AXIS_BOTTOM ); - setAutoZoomForAllAxes( false ); + m_yAxisProperties->setAutoZoom( enabled ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridCrossPlot::selectAxisInPropertyEditor( int axis ) +void RimGridCrossPlot::createPlotWidget() { - RiuPlotMainWindowTools::showPlotMainWindow(); - if ( axis == QwtPlot::yLeft ) - { - RiuPlotMainWindowTools::selectAsCurrentItem( m_yAxisProperties ); - } - else if ( axis == QwtPlot::xBottom ) - { - RiuPlotMainWindowTools::selectAsCurrentItem( m_xAxisProperties ); - } + createViewWidget( nullptr ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridCrossPlot::setAutoZoomForAllAxes( bool enableAutoZoom ) -{ - m_xAxisProperties->setAutoZoom( enableAutoZoom ); - m_yAxisProperties->setAutoZoom( enableAutoZoom ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmObject* RimGridCrossPlot::findRimPlotObjectFromQwtCurve( const QwtPlotCurve* qwtCurve ) const +caf::PdmObject* RimGridCrossPlot::findPdmObjectFromQwtCurve( const QwtPlotCurve* qwtCurve ) const { for ( auto dataSet : m_crossPlotDataSets ) { @@ -365,23 +346,49 @@ caf::PdmObject* RimGridCrossPlot::findRimPlotObjectFromQwtCurve( const QwtPlotCu return nullptr; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::onAxisSelected( int axis, bool toggle ) +{ + RiuPlotMainWindowTools::showPlotMainWindow(); + RimPlotAxisProperties* properties = nullptr; + if ( axis == QwtPlot::yLeft ) + { + properties = m_yAxisProperties; + } + else if ( axis == QwtPlot::xBottom ) + { + properties = m_xAxisProperties; + } + + if ( toggle ) + { + RiuPlotMainWindowTools::toggleItemInSelection( properties ); + } + else + { + RiuPlotMainWindowTools::selectAsCurrentItem( properties ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QWidget* RimGridCrossPlot::createViewWidget( QWidget* mainWindowParent ) { - if ( !m_qwtPlot ) + if ( !m_plotWidget ) { - m_qwtPlot = new RiuGridCrossQwtPlot( this, mainWindowParent ); + m_plotWidget = new RiuGridCrossQwtPlot( this, mainWindowParent ); for ( auto dataSet : m_crossPlotDataSets ) { - dataSet->setParentQwtPlotNoReplot( m_qwtPlot ); + dataSet->setParentQwtPlotNoReplot( m_plotWidget ); } - m_qwtPlot->replot(); + m_plotWidget->scheduleReplot(); } - return m_qwtPlot; + return m_plotWidget; } //-------------------------------------------------------------------------------------------------- @@ -390,10 +397,10 @@ QWidget* RimGridCrossPlot::createViewWidget( QWidget* mainWindowParent ) void RimGridCrossPlot::deleteViewWidget() { detachAllCurves(); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - m_qwtPlot->deleteLater(); - m_qwtPlot = nullptr; + m_plotWidget->deleteLater(); + m_plotWidget = nullptr; } } @@ -501,39 +508,55 @@ void RimGridCrossPlot::performAutoNameUpdate() updateCurveNamesAndPlotTitle(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::updateAxisDisplay() +{ + if ( !m_plotWidget ) return; + + updateAxisInQwt( RiaDefines::PLOT_AXIS_BOTTOM ); + updateAxisInQwt( RiaDefines::PLOT_AXIS_LEFT ); + + m_plotWidget->updateAnnotationObjects( m_xAxisProperties ); + m_plotWidget->updateAnnotationObjects( m_yAxisProperties ); + + m_plotWidget->scheduleReplot(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGridCrossPlot::updatePlot() { - if ( m_qwtPlot ) + if ( m_plotWidget ) { - RiuQwtPlotTools::setCommonPlotBehaviour( m_qwtPlot ); - RiuQwtPlotTools::setDefaultAxes( m_qwtPlot ); + RiuQwtPlotTools::setCommonPlotBehaviour( m_plotWidget ); + RiuQwtPlotTools::setDefaultAxes( m_plotWidget ); updateAxisDisplay(); for ( auto dataSet : m_crossPlotDataSets ) { - dataSet->setParentQwtPlotNoReplot( m_qwtPlot ); + dataSet->setParentQwtPlotNoReplot( m_plotWidget ); } if ( m_showLegend() ) { // Will be released in plot destructor or when a new legend is set - QwtLegend* legend = new QwtLegend( m_qwtPlot ); + QwtLegend* legend = new QwtLegend( m_plotWidget ); auto font = legend->font(); font.setPointSize( m_legendFontSize() ); legend->setFont( font ); - m_qwtPlot->insertLegend( legend, QwtPlot::BottomLegend ); + m_plotWidget->insertLegend( legend, QwtPlot::BottomLegend ); } else { - m_qwtPlot->insertLegend( nullptr ); + m_plotWidget->insertLegend( nullptr ); } - m_qwtPlot->updateLegendSizesToMatchPlot(); - m_qwtPlot->replot(); + m_plotWidget->updateLegendSizesToMatchPlot(); + m_plotWidget->scheduleReplot(); } } @@ -547,9 +570,9 @@ void RimGridCrossPlot::updateCurveNamesAndPlotTitle() m_crossPlotDataSets[i]->updateCurveNames( i, m_crossPlotDataSets.size() ); } - if ( m_qwtPlot ) + if ( m_plotWidget ) { - m_qwtPlot->setTitle( this->createAutoName() ); + m_plotWidget->setTitle( this->createAutoName() ); } updateMdiWindowTitle(); } @@ -621,14 +644,6 @@ QString RimGridCrossPlot::asciiDataForPlotExport( int dataSetIndex ) const } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuGridCrossQwtPlot* RimGridCrossPlot::qwtPlot() const -{ - return m_qwtPlot; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -691,34 +706,66 @@ bool RimGridCrossPlot::applyFontSize( RiaDefines::FontSettingType fontSettingTyp int fontSize, bool forceChange /*= false*/ ) { - if ( fontSettingType != RiaDefines::PLOT_FONT ) return false; - bool anyChange = false; - for ( auto plotAxis : allPlotAxes() ) + if ( fontSettingType == RiaDefines::PLOT_FONT && m_plotWidget ) { - if ( forceChange || plotAxis->titleFontSize() == oldFontSize ) + for ( auto plotAxis : allPlotAxes() ) { - plotAxis->setTitleFontSize( fontSize ); - anyChange = true; + if ( forceChange || plotAxis->titleFontSize() == oldFontSize ) + { + plotAxis->setTitleFontSize( fontSize ); + anyChange = true; + } + if ( forceChange || plotAxis->valuesFontSize() == oldFontSize ) + { + plotAxis->setValuesFontSize( fontSize ); + anyChange = true; + } } - if ( forceChange || plotAxis->valuesFontSize() == oldFontSize ) + + if ( forceChange || legendFontSize() == oldFontSize ) { - plotAxis->setValuesFontSize( fontSize ); - anyChange = true; + m_legendFontSize = fontSize; + anyChange = true; } + + if ( anyChange ) loadDataAndUpdate(); } - - if ( forceChange || legendFontSize() == oldFontSize ) - { - m_legendFontSize = fontSize; - anyChange = true; - } - - if ( anyChange ) loadDataAndUpdate(); - return anyChange; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::updateLayout() +{ + updatePlot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::updateZoomInQwt() +{ + if ( m_plotWidget ) + { + updateAxisInQwt( RiaDefines::PLOT_AXIS_LEFT ); + updateAxisInQwt( RiaDefines::PLOT_AXIS_BOTTOM ); + m_plotWidget->updateAxes(); + updateZoomFromQwt(); + m_plotWidget->scheduleReplot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::updateZoomFromQwt() +{ + updateAxisFromQwt( RiaDefines::PLOT_AXIS_LEFT ); + updateAxisFromQwt( RiaDefines::PLOT_AXIS_BOTTOM ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -772,7 +819,7 @@ QString RimGridCrossPlot::yAxisParameterString() const //-------------------------------------------------------------------------------------------------- void RimGridCrossPlot::updateAxisInQwt( RiaDefines::PlotAxis axisType ) { - if ( !m_qwtPlot ) return; + if ( !m_plotWidget ) return; RimPlotAxisProperties* axisProperties = m_xAxisProperties(); QString axisParameterString = xAxisParameterString(); @@ -787,17 +834,17 @@ void RimGridCrossPlot::updateAxisInQwt( RiaDefines::PlotAxis axisType ) if ( axisProperties->isActive() ) { - m_qwtPlot->enableAxis( qwtAxisId, true ); + m_plotWidget->enableAxis( qwtAxisId, true ); QwtText axisTitle( axisParameterString ); - QFont titleFont = m_qwtPlot->axisTitle( qwtAxisId ).font(); + QFont titleFont = m_plotWidget->axisTitle( qwtAxisId ).font(); titleFont.setBold( true ); titleFont.setPointSize( axisProperties->titleFontSize() ); axisTitle.setFont( titleFont ); - QFont valuesFont = m_qwtPlot->axisFont( qwtAxisId ); + QFont valuesFont = m_plotWidget->axisFont( qwtAxisId ); valuesFont.setPointSize( axisProperties->valuesFontSize() ); - m_qwtPlot->setAxisFont( qwtAxisId, valuesFont ); + m_plotWidget->setAxisFont( qwtAxisId, valuesFont ); switch ( axisProperties->titlePosition() ) { @@ -809,16 +856,16 @@ void RimGridCrossPlot::updateAxisInQwt( RiaDefines::PlotAxis axisType ) break; } - m_qwtPlot->setAxisTitle( qwtAxisId, axisTitle ); + m_plotWidget->setAxisTitle( qwtAxisId, axisTitle ); if ( axisProperties->isLogarithmicScaleEnabled ) { QwtLogScaleEngine* currentScaleEngine = dynamic_cast( - m_qwtPlot->axisScaleEngine( axisProperties->qwtPlotAxisType() ) ); + m_plotWidget->axisScaleEngine( axisProperties->qwtPlotAxisType() ) ); if ( !currentScaleEngine ) { - m_qwtPlot->setAxisScaleEngine( axisProperties->qwtPlotAxisType(), new QwtLogScaleEngine ); - m_qwtPlot->setAxisMaxMinor( axisProperties->qwtPlotAxisType(), 5 ); + m_plotWidget->setAxisScaleEngine( axisProperties->qwtPlotAxisType(), new QwtLogScaleEngine ); + m_plotWidget->setAxisMaxMinor( axisProperties->qwtPlotAxisType(), 5 ); } if ( axisProperties->isAutoZoom() ) @@ -833,38 +880,38 @@ void RimGridCrossPlot::updateAxisInQwt( RiaDefines::PlotAxis axisType ) std::swap( min, max ); } - m_qwtPlot->setAxisScale( qwtAxisId, min, max ); + m_plotWidget->setAxisScale( qwtAxisId, min, max ); } else { - m_qwtPlot->setAxisScale( qwtAxisId, axisProperties->visibleRangeMin, axisProperties->visibleRangeMax ); + m_plotWidget->setAxisScale( qwtAxisId, axisProperties->visibleRangeMin, axisProperties->visibleRangeMax ); } } else { QwtLinearScaleEngine* currentScaleEngine = dynamic_cast( - m_qwtPlot->axisScaleEngine( axisProperties->qwtPlotAxisType() ) ); + m_plotWidget->axisScaleEngine( axisProperties->qwtPlotAxisType() ) ); if ( !currentScaleEngine ) { - m_qwtPlot->setAxisScaleEngine( axisProperties->qwtPlotAxisType(), new QwtLinearScaleEngine ); - m_qwtPlot->setAxisMaxMinor( axisProperties->qwtPlotAxisType(), 3 ); + m_plotWidget->setAxisScaleEngine( axisProperties->qwtPlotAxisType(), new QwtLinearScaleEngine ); + m_plotWidget->setAxisMaxMinor( axisProperties->qwtPlotAxisType(), 3 ); } if ( axisProperties->isAutoZoom() ) { - m_qwtPlot->setAxisAutoScale( qwtAxisId ); + m_plotWidget->setAxisAutoScale( qwtAxisId ); } else { - m_qwtPlot->setAxisScale( qwtAxisId, axisProperties->visibleRangeMin, axisProperties->visibleRangeMax ); + m_plotWidget->setAxisScale( qwtAxisId, axisProperties->visibleRangeMin, axisProperties->visibleRangeMax ); } } - m_qwtPlot->axisScaleEngine( axisProperties->qwtPlotAxisType() ) + m_plotWidget->axisScaleEngine( axisProperties->qwtPlotAxisType() ) ->setAttribute( QwtScaleEngine::Inverted, axisProperties->isAxisInverted() ); } else { - m_qwtPlot->enableAxis( qwtAxisId, false ); + m_plotWidget->enableAxis( qwtAxisId, false ); } } @@ -873,10 +920,10 @@ void RimGridCrossPlot::updateAxisInQwt( RiaDefines::PlotAxis axisType ) //-------------------------------------------------------------------------------------------------- void RimGridCrossPlot::updateAxisFromQwt( RiaDefines::PlotAxis axisType ) { - CVF_ASSERT( m_qwtPlot ); + if ( !m_plotWidget ) return; - QwtInterval xAxisRange = m_qwtPlot->currentAxisRange( QwtPlot::xBottom ); - QwtInterval yAxisRange = m_qwtPlot->currentAxisRange( QwtPlot::yLeft ); + QwtInterval xAxisRange = m_plotWidget->axisRange( QwtPlot::xBottom ); + QwtInterval yAxisRange = m_plotWidget->axisRange( QwtPlot::yLeft ); RimPlotAxisProperties* axisProperties = m_xAxisProperties(); QwtInterval axisRange = xAxisRange; @@ -952,7 +999,37 @@ void RimGridCrossPlot::setShowInfoBox( bool enable ) //-------------------------------------------------------------------------------------------------- std::set RimGridCrossPlot::allPlotAxes() const { - return {m_xAxisProperties, m_yAxisProperties}; + return { m_xAxisProperties, m_yAxisProperties }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::updatePlotTitle() +{ + updateCurveNamesAndPlotTitle(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSet ) +{ + if ( m_plotWidget ) + { + m_plotWidget->addOrUpdateDataSetLegend( dataSet ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlot::removeDataSetLegend( RimGridCrossPlotDataSet* dataSet ) +{ + if ( m_plotWidget ) + { + m_plotWidget->removeDataSetLegend( dataSet ); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.h b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.h index 637fc44d0c..fe9a69ed44 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.h +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.h @@ -23,7 +23,8 @@ #include "RiaDefines.h" #include "RimNameConfig.h" -#include "RimPlot.h" +#include "RimPlotInterface.h" +#include "RimPlotWindow.h" #include "RimRiuQwtPlotOwnerInterface.h" #include @@ -49,7 +50,7 @@ protected: virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; }; -class RimGridCrossPlot : public RimPlot, public RimRiuQwtPlotOwnerInterface, public RimNameConfigHolderInterface +class RimGridCrossPlot : public RimPlotWindow, public RimPlotInterface, public RimNameConfigHolderInterface { CAF_PDM_HEADER_INIT; @@ -57,32 +58,36 @@ public: RimGridCrossPlot(); ~RimGridCrossPlot(); + bool isChecked() const override; + RimGridCrossPlotDataSet* createDataSet(); int indexOfDataSet( const RimGridCrossPlotDataSet* dataSet ) const; void addDataSet( RimGridCrossPlotDataSet* dataSet ); std::vector dataSets() const; - QWidget* viewWidget() override; - QImage snapshotWindowContent() override; - void zoomAll() override; - void calculateZoomRangeAndUpdateQwt(); - void reattachCurvesToQwtAndReplot(); - QString createAutoName() const override; + QWidget* viewWidget() override; + RiuQwtPlotWidget* viewer() override; + + QImage snapshotWindowContent() override; + void zoomAll() override; + void calculateZoomRangeAndUpdateQwt(); + void reattachCurvesToQwtAndReplot(); + QString createAutoName() const override; bool showInfoBox() const; caf::PdmFieldHandle* userDescriptionField() override; - void detachAllCurves(); + void detachAllCurves() override; void performAutoNameUpdate() override; void updateCurveNamesAndPlotTitle(); void swapAxes(); QString asciiTitleForPlotExport( int dataSetIndex ) const; QString asciiDataForPlotExport( int dataSetIndex ) const; - RiuGridCrossQwtPlot* qwtPlot() const; - bool isXAxisLogarithmic() const; - bool isYAxisLogarithmic() const; - void setYAxisInverted( bool inverted ); - int legendFontSize() const; + + bool isXAxisLogarithmic() const; + bool isYAxisLogarithmic() const; + void setYAxisInverted( bool inverted ); + int legendFontSize() const; bool hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const override; bool applyFontSize( RiaDefines::FontSettingType fontSettingType, @@ -90,14 +95,21 @@ public: int fontSize, bool forceChange = false ) override; -public: - // Rim2dPlotInterface overrides - void updateAxisScaling() override; - void updateAxisDisplay() override; - void updateZoomWindowFromQwt() override; - void selectAxisInPropertyEditor( int axis ) override; - void setAutoZoomForAllAxes( bool enableAutoZoom ) override; - caf::PdmObject* findRimPlotObjectFromQwtCurve( const QwtPlotCurve* curve ) const override; + void updateLayout() override; + + void updateZoomInQwt() override; + void updateZoomFromQwt() override; + + void loadDataAndUpdate(); + + void setAutoScaleXEnabled( bool enabled ) override; + void setAutoScaleYEnabled( bool enabled ) override; + void createPlotWidget() override; + caf::PdmObject* findPdmObjectFromQwtCurve( const QwtPlotCurve* curve ) const override; + void onAxisSelected( int axis, bool toggle ) override; + + void addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSet ); + void removeDataSetLegend( RimGridCrossPlotDataSet* dataSet ); protected: QWidget* createViewWidget( QWidget* mainWindowParent ) override; @@ -111,8 +123,8 @@ protected: const QVariant& newValue ) override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) override; - - void updatePlot(); + void updateAxisDisplay(); + void updatePlot(); virtual QString xAxisParameterString() const; QString yAxisParameterString() const; @@ -129,6 +141,8 @@ protected: std::set allPlotAxes() const; + void updatePlotTitle() override; + private: caf::PdmField m_showInfoBox; caf::PdmField m_showLegend; @@ -140,5 +154,5 @@ private: caf::PdmChildArrayField m_crossPlotDataSets; - QPointer m_qwtPlot; + QPointer m_plotWidget; }; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp index b868c2fec2..b6311196ed 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotDataSet.cpp @@ -943,10 +943,10 @@ QList } else if ( fieldNeedingOptions == &m_grouping ) { - std::set validOptions = {NO_GROUPING, - GROUP_BY_TIME, - GROUP_BY_FORMATION, - GROUP_BY_RESULT}; + std::set validOptions = { NO_GROUPING, + GROUP_BY_TIME, + GROUP_BY_FORMATION, + GROUP_BY_RESULT }; if ( !hasMultipleTimeSteps() ) { validOptions.erase( GROUP_BY_TIME ); @@ -977,7 +977,7 @@ void RimGridCrossPlotDataSet::updateLegendRange() RimGridCrossPlot* parent; this->firstAncestorOrThisOfTypeAsserted( parent ); - if ( parent->qwtPlot() ) + if ( parent->viewer() ) { if ( groupingEnabled() && m_case() && isChecked() && legendConfig()->showLegend() ) { @@ -1020,11 +1020,11 @@ void RimGridCrossPlotDataSet::updateLegendRange() m_groupingProperty->updateLegendData( eclipseCase, m_timeStep() ); } } - parent->qwtPlot()->addOrUpdateDataSetLegend( this ); + parent->addOrUpdateDataSetLegend( this ); } else { - parent->qwtPlot()->removeDataSetLegend( this ); + parent->removeDataSetLegend( this ); } } } diff --git a/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.cpp b/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.cpp index 55b82910a0..a4df6e4e21 100644 --- a/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.cpp +++ b/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.cpp @@ -460,7 +460,7 @@ void Rim2dIntersectionView::setName( const QString& name ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool Rim2dIntersectionView::isWindowVisible() +bool Rim2dIntersectionView::isWindowVisible() const { return m_showWindow(); } diff --git a/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.h b/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.h index 0e98d54911..7abe593082 100644 --- a/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.h +++ b/ApplicationCode/ProjectDataModel/Rim2dIntersectionView.h @@ -96,7 +96,7 @@ protected: cvf::Transform* scaleTransform() override; void resetLegendsInViewer() override; void onLoadDataAndUpdate() override; - bool isWindowVisible() override; + bool isWindowVisible() const override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, diff --git a/ApplicationCode/ProjectDataModel/RimFormationNames.cpp b/ApplicationCode/ProjectDataModel/RimFormationNames.cpp index 6491f3188d..5b2889005a 100644 --- a/ApplicationCode/ProjectDataModel/RimFormationNames.cpp +++ b/ApplicationCode/ProjectDataModel/RimFormationNames.cpp @@ -24,6 +24,7 @@ #include "RimCase.h" #include "RimTools.h" #include "RimWellLogTrack.h" +#include "RiuPlotMainWindowTools.h" #include "cafAssert.h" #include "cafPdmUiFilePathEditor.h" @@ -113,6 +114,7 @@ void RimFormationNames::updateConnectedViews() std::vector objects; this->objectsWithReferringPtrFieldsOfType( objects ); + bool updatedTracks = false; for ( RimCase* caseObj : objects ) { if ( caseObj ) @@ -126,11 +128,13 @@ void RimFormationNames::updateConnectedViews() // The track may be referring to the case for other reasons than formations. if ( track->formationNamesCase() == caseObj ) { - track->loadDataAndUpdate( true ); + track->loadDataAndUpdate(); + updatedTracks = true; } } } } + RiuPlotMainWindowTools::refreshToolbars(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimGridPlotWindow.cpp b/ApplicationCode/ProjectDataModel/RimGridPlotWindow.cpp new file mode 100644 index 0000000000..7565d310fa --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimGridPlotWindow.cpp @@ -0,0 +1,628 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimGridPlotWindow.h" + +#include "RimPlotInterface.h" +#include "RiuPlotMainWindow.h" +#include "RiuPlotMainWindowTools.h" + +#include + +#include + +namespace caf +{ +template <> +void RimGridPlotWindow::ColumnCountEnum::setUp() +{ + addItem( RimGridPlotWindow::COLUMNS_1, "1", "1 Column" ); + addItem( RimGridPlotWindow::COLUMNS_2, "2", "2 Columns" ); + addItem( RimGridPlotWindow::COLUMNS_3, "3", "3 Columns" ); + addItem( RimGridPlotWindow::COLUMNS_4, "4", "4 Columns" ); + addItem( RimGridPlotWindow::COLUMNS_UNLIMITED, "UNLIMITED", "Unlimited" ); + setDefault( RimGridPlotWindow::COLUMNS_UNLIMITED ); +} +} // namespace caf + +CAF_PDM_SOURCE_INIT( RimGridPlotWindow, "GridPlotWindow" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGridPlotWindow::RimGridPlotWindow() +{ + CAF_PDM_InitObject( "Grid Plot Window", ":/WellLogPlot16x16.png", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_plots, "Tracks", "", "", "", "" ); + m_plots.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_columnCountEnum, "NumberOfColumns", "Number of Columns", "", "", "" ); + + m_viewer = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGridPlotWindow::~RimGridPlotWindow() +{ + removeMdiWindowFromMdiArea(); + m_plots.deleteAllChildObjects(); + + deleteViewWidget(); +} + +//-------------------------------------------------------------------------------------------------- +/// Move-assignment operator. Argument has to be passed with std::move() +//-------------------------------------------------------------------------------------------------- +RimGridPlotWindow& RimGridPlotWindow::operator=( RimGridPlotWindow&& rhs ) +{ + RimPlotWindow::operator=( std::move( rhs ) ); + + // Move all tracks + std::vector plots = rhs.m_plots.childObjects(); + rhs.m_plots.clear(); + for ( caf::PdmObject* plot : plots ) + { + CAF_ASSERT( dynamic_cast( plot ) ); + m_plots.push_back( plot ); + } + + m_columnCountEnum = rhs.m_columnCountEnum; + + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* RimGridPlotWindow::viewWidget() +{ + return m_viewer; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::addPlot( RimPlotInterface* plot ) +{ + insertPlot( plot, m_plots.size() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::insertPlot( RimPlotInterface* plot, size_t index ) +{ + if ( plot ) + { + m_plots.insert( index, toPdmObjectAsserted( plot ) ); + + if ( m_viewer ) + { + plot->createPlotWidget(); + m_viewer->insertPlot( plot->viewer(), index ); + } + + onPlotAdditionOrRemoval(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::removePlot( RimPlotInterface* plot ) +{ + if ( plot ) + { + if ( m_viewer ) + { + m_viewer->removePlot( plot->viewer() ); + } + m_plots.removeChildObject( toPdmObjectAsserted( plot ) ); + + onPlotAdditionOrRemoval(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimGridPlotWindow::plotCount() const +{ + return m_plots.size(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimGridPlotWindow::plotIndex( const RimPlotInterface* plot ) const +{ + return m_plots.index( toPdmObjectAsserted( plot ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotInterface* RimGridPlotWindow::plotByIndex( size_t index ) const +{ + return toPlotInterfaceAsserted( m_plots[index] ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimGridPlotWindow::plots() const +{ + std::vector allPlots; + allPlots.reserve( m_plots.size() ); + + for ( caf::PdmObject* pdmObject : m_plots ) + { + allPlots.push_back( toPlotInterfaceAsserted( pdmObject ) ); + } + return allPlots; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimGridPlotWindow::visiblePlots() const +{ + std::vector allPlots; + for ( caf::PdmObject* pdmObject : m_plots() ) + { + RimPlotInterface* plot = toPlotInterfaceAsserted( pdmObject ); + if ( plot->isChecked() ) + { + allPlots.push_back( plot ); + } + } + return allPlots; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updateLayout() +{ + if ( m_showWindow ) + { + m_viewer->scheduleUpdate(); + } +} + +#if 0 +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updatePlotNames() +{ + auto plotVector = plots(); + for ( size_t tIdx = 0; tIdx < plotVector.size(); ++tIdx ) + { + QString description = plotVector[tIdx]->description(); + QRegularExpression regexp( "Track \\d+" ); + description.replace( regexp, QString( "Track %1" ).arg( tIdx + 1 ) ); + plotVector[tIdx]->setDescription( description ); + } +} +#endif + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updatePlotOrderFromGridWidget() +{ + std::sort( m_plots.begin(), m_plots.end(), [this]( caf::PdmObject* lhs, caf::PdmObject* rhs ) { + auto indexLhs = m_viewer->indexOfPlotWidget( toPlotInterfaceAsserted( lhs )->viewer() ); + auto indexRhs = m_viewer->indexOfPlotWidget( toPlotInterfaceAsserted( rhs )->viewer() ); + return indexLhs < indexRhs; + } ); + // updatePlotNames(); + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::setAutoScaleXEnabled( bool enabled ) +{ + for ( RimPlotInterface* plot : plots() ) + { + plot->setAutoScaleXEnabled( enabled ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::setAutoScaleYEnabled( bool enabled ) +{ + for ( RimPlotInterface* plot : plots() ) + { + plot->setAutoScaleYEnabled( enabled ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimGridPlotWindow::columnCount() const +{ + if ( m_columnCountEnum() == COLUMNS_UNLIMITED ) + { + return static_cast( visiblePlots().size() ); + } + return static_cast( m_columnCountEnum() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimGridPlotWindow::columnCountField() +{ + return &m_columnCountEnum; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::zoomAll() +{ + setAutoScaleXEnabled( true ); + setAutoScaleYEnabled( true ); + updateZoom(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmUiGroup* RimGridPlotWindow::createPlotSettingsUiGroup( caf::PdmUiOrdering& uiOrdering ) +{ + caf::PdmUiGroup* titleAndLegendsGroup = RimPlotWindow::createPlotSettingsUiGroup( uiOrdering ); + titleAndLegendsGroup->add( &m_columnCountEnum ); + return titleAndLegendsGroup; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimGridPlotWindow::asciiDataForPlotExport() const +{ + QString out = description() + "\n"; + + for ( RimPlotInterface* plot : plots() ) + { + if ( plot->isChecked() ) + { + out += plot->asciiDataForPlotExport(); + } + } + + return out; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::onPlotAdditionOrRemoval() +{ + // updatePlotNames(); + updateColumnCount(); + updateConnectedEditors(); + updateLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QImage RimGridPlotWindow::snapshotWindowContent() +{ + QImage image; + + if ( m_viewer ) + { + m_viewer->setScrollbarVisible( false ); + m_viewer->setSelectionsVisible( false ); + QPixmap pix = m_viewer->grab(); + image = pix.toImage(); + m_viewer->setScrollbarVisible( true ); + m_viewer->setSelectionsVisible( true ); + } + + return image; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* RimGridPlotWindow::createViewWidget( QWidget* mainWindowParent ) +{ + m_viewer = new RiuGridPlotWindow( this, mainWindowParent ); + recreatePlotWidgets(); + return m_viewer; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::deleteViewWidget() +{ + detachAllCurves(); + + if ( m_viewer ) + { + m_viewer->deleteLater(); + m_viewer = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + RimPlotWindow::fieldChangedByUi( changedField, oldValue, newValue ); + + if ( changedField == &m_columnCountEnum ) + { + updateLayout(); + updateColumnCount(); + } + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + createPlotSettingsUiGroup( uiOrdering ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimGridPlotWindow::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) +{ + QList options = RimPlotWindow::calculateValueOptions( fieldNeedingOptions, useOptionsOnly ); + + if ( fieldNeedingOptions == &m_columnCountEnum ) + { + for ( size_t i = 0; i < ColumnCountEnum::size(); ++i ) + { + ColumnCount enumVal = ColumnCountEnum::fromIndex( i ); + if ( enumVal == COLUMNS_UNLIMITED ) + { + QString iconPath( ":/ColumnsUnlimited.png" ); + options.push_back( caf::PdmOptionItemInfo( ColumnCountEnum::uiText( enumVal ), + enumVal, + false, + caf::QIconProvider( iconPath ) ) ); + } + else + { + QString iconPath = QString( ":/Columns%1.png" ).arg( static_cast( enumVal ) ); + options.push_back( caf::PdmOptionItemInfo( ColumnCountEnum::uiText( enumVal ), + enumVal, + false, + caf::QIconProvider( iconPath ) ) ); + } + } + } + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::onLoadDataAndUpdate() +{ + updateMdiWindowVisibility(); + setPlotTitleInWidget( this->fullPlotTitle() ); + updatePlots(); + updateLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::initAfterRead() +{ + RimPlotWindow::initAfterRead(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updatePlotTitle() +{ + m_viewer->setTitleVisible( m_showTitleInPlot() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::setPlotTitleInWidget( const QString& title ) +{ + if ( m_viewer ) + { + m_viewer->setPlotTitle( title ); + } + updateMdiWindowTitle(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updatePlots() +{ + if ( m_showWindow ) + { + for ( RimPlotInterface* plot : plots() ) + { + plot->loadDataAndUpdate(); + } + this->updateZoom(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updateZoom() +{ + for ( RimPlotInterface* plot : plots() ) + { + plot->updateZoomInQwt(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::recreatePlotWidgets() +{ + CVF_ASSERT( m_viewer ); + + auto plotVector = plots(); + + for ( size_t tIdx = 0; tIdx < plotVector.size(); ++tIdx ) + { + plotVector[tIdx]->createPlotWidget(); + m_viewer->addPlot( plotVector[tIdx]->viewer() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridPlotWindow::hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const +{ + if ( fontSettingType == RiaDefines::PLOT_FONT && m_viewer ) + { + if ( m_viewer->fontSize() != defaultFontSize ) + { + return true; + } + for ( const RimPlotInterface* plot : plots() ) + { + if ( plot->hasCustomFontSizes( fontSettingType, defaultFontSize ) ) + { + return true; + } + } + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimGridPlotWindow::applyFontSize( RiaDefines::FontSettingType fontSettingType, + int oldFontSize, + int fontSize, + bool forceChange /*= false */ ) +{ + bool somethingChanged = false; + if ( fontSettingType == RiaDefines::PLOT_FONT && m_viewer ) + { + if ( oldFontSize == m_viewer->fontSize() || forceChange ) + { + m_viewer->setFontSize( fontSize ); + somethingChanged = true; + } + + for ( RimPlotInterface* plot : plots() ) + { + if ( plot->applyFontSize( fontSettingType, oldFontSize, fontSize, forceChange ) ) + { + somethingChanged = true; + } + } + if ( somethingChanged ) + { + m_viewer->scheduleUpdate(); + } + } + return somethingChanged; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::detachAllCurves() +{ + auto plotVector = plots(); + for ( size_t tIdx = 0; tIdx < plotVector.size(); ++tIdx ) + { + plotVector[tIdx]->detachAllCurves(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridPlotWindow::updateColumnCount() +{ + RiuPlotMainWindowTools::refreshToolbars(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotInterface* RimGridPlotWindow::toPlotInterfaceAsserted( caf::PdmObject* pdmObject ) +{ + RimPlotInterface* plotInterface = dynamic_cast( pdmObject ); + CAF_ASSERT( plotInterface ); + return plotInterface; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const RimPlotInterface* RimGridPlotWindow::toPlotInterfaceAsserted( const caf::PdmObject* pdmObject ) +{ + const RimPlotInterface* plotInterface = dynamic_cast( pdmObject ); + CAF_ASSERT( plotInterface ); + return plotInterface; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RimGridPlotWindow::toPdmObjectAsserted( RimPlotInterface* plotInterface ) +{ + caf::PdmObject* pdmObject = dynamic_cast( plotInterface ); + CAF_ASSERT( pdmObject ); + return pdmObject; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const caf::PdmObject* RimGridPlotWindow::toPdmObjectAsserted( const RimPlotInterface* plotInterface ) +{ + const caf::PdmObject* pdmObject = dynamic_cast( plotInterface ); + CAF_ASSERT( pdmObject ); + return pdmObject; +} diff --git a/ApplicationCode/ProjectDataModel/RimGridPlotWindow.h b/ApplicationCode/ProjectDataModel/RimGridPlotWindow.h new file mode 100644 index 0000000000..de0831d043 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimGridPlotWindow.h @@ -0,0 +1,132 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimPlotWindow.h" +#include "RiuGridPlotWindow.h" + +#include "cafAppEnum.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmChildField.h" +#include "cafPdmField.h" +#include "cafPdmFieldHandle.h" +#include "cafPdmObject.h" + +#include +#include + +class RimPlotInterface; + +class RimGridPlotWindow : public RimPlotWindow +{ + CAF_PDM_HEADER_INIT; + +public: + enum ColumnCount + { + COLUMNS_1 = 1, + COLUMNS_2 = 2, + COLUMNS_3 = 3, + COLUMNS_4 = 4, + COLUMNS_UNLIMITED = 1000, + }; + typedef caf::AppEnum ColumnCountEnum; + +public: + RimGridPlotWindow(); + ~RimGridPlotWindow(); + + RimGridPlotWindow& operator=( RimGridPlotWindow&& rhs ); + + QWidget* viewWidget() override; + + void addPlot( RimPlotInterface* plot ); + void insertPlot( RimPlotInterface* plot, size_t index ); + void removePlot( RimPlotInterface* plot ); + + size_t plotCount() const; + size_t plotIndex( const RimPlotInterface* plot ) const; + RimPlotInterface* plotByIndex( size_t index ) const; + + std::vector plots() const; + std::vector visiblePlots() const; + + void updateLayout() override; + // void updatePlotNames(); + void updatePlotOrderFromGridWidget(); + + virtual void setAutoScaleXEnabled( bool enabled ); + virtual void setAutoScaleYEnabled( bool enabled ); + + int columnCount() const; + caf::PdmFieldHandle* columnCountField(); + + void zoomAll() override; + + caf::PdmUiGroup* createPlotSettingsUiGroup( caf::PdmUiOrdering& uiOrdering ) override; + + QString asciiDataForPlotExport() const; + + virtual void onPlotAdditionOrRemoval(); + +protected: + QImage snapshotWindowContent() override; + + QWidget* createViewWidget( QWidget* mainWindowParent ) override; + void deleteViewWidget() override; + + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) override; + void onLoadDataAndUpdate() override; + void initAfterRead() override; + + void updatePlotTitle() override; + void setPlotTitleInWidget( const QString& plotTitle ); + void updatePlots(); + virtual void updateZoom(); + void recreatePlotWidgets(); + + bool hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const override; + bool applyFontSize( RiaDefines::FontSettingType fontSettingType, + int oldFontSize, + int fontSize, + bool forceChange = false ) override; + +private: + void detachAllCurves() override; + + void updateColumnCount(); + + static RimPlotInterface* toPlotInterfaceAsserted( caf::PdmObject* pdmObject ); + static const RimPlotInterface* toPlotInterfaceAsserted( const caf::PdmObject* pdmObject ); + static caf::PdmObject* toPdmObjectAsserted( RimPlotInterface* plotInterface ); + static const caf::PdmObject* toPdmObjectAsserted( const RimPlotInterface* plotInterface ); + +protected: + caf::PdmField m_columnCountEnum; + + friend class RiuGridPlotWindow; + QPointer m_viewer; + +private: + caf::PdmChildArrayField m_plots; +}; diff --git a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp index a5258bd1f9..475562a973 100644 --- a/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimGridTimeHistoryCurve.cpp @@ -44,8 +44,8 @@ #include "RiuFemTimeHistoryResultAccessor.h" #include "RiuQwtPlotCurve.h" -#include "qwt_plot.h" #include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h" +#include "qwt_plot.h" CAF_PDM_SOURCE_INIT( RimGridTimeHistoryCurve, "GridTimeHistoryCurve" ); @@ -336,7 +336,7 @@ QString RimGridTimeHistoryCurve::caseName() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- RimCase* RimGridTimeHistoryCurve::gridCase() const { diff --git a/ApplicationCode/ProjectDataModel/RimPlotInterface.cpp b/ApplicationCode/ProjectDataModel/RimPlotInterface.cpp new file mode 100644 index 0000000000..d32bf6d714 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPlotInterface.cpp @@ -0,0 +1,30 @@ +#include "RimPlotInterface.h" + +#include "RimPlotWindow.h" + +#include "RiuQwtPlotWidget.h" + +#define RI_PLOT_MIN_DEFAULT -10.0 +#define RI_PLOT_MAX_DEFAULT 100.0 + +namespace caf +{ +template <> +void RimPlotInterface::WidthScaleFactorEnum::setUp() +{ + addItem( RimPlotInterface::EXTRA_NARROW, "EXTRA_NARROW_TRACK", "Extra Narrow" ); + addItem( RimPlotInterface::NARROW, "NARROW_TRACK", "Narrow" ); + addItem( RimPlotInterface::NORMAL, "NORMAL_TRACK", "Normal" ); + addItem( RimPlotInterface::WIDE, "WIDE_TRACK", "Wide" ); + addItem( RimPlotInterface::EXTRA_WIDE, "EXTRA_WIDE_TRACK", "Extra wide" ); + setDefault( RimPlotInterface::NORMAL ); +} +} // namespace caf + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimPlotInterface::asciiDataForPlotExport() const +{ + return ""; +} diff --git a/ApplicationCode/ProjectDataModel/RimPlotInterface.h b/ApplicationCode/ProjectDataModel/RimPlotInterface.h new file mode 100644 index 0000000000..72c41ef12d --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPlotInterface.h @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RiaDefines.h" + +#include "cafAppEnum.h" +#include "cafPdmChildArrayField.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +#include + +class RiuQwtPlotWidget; +class RimPlotCurve; +class QwtPlotCurve; + +class RimPlotInterface +{ +public: + enum WidthScaleFactor + { + EXTRA_NARROW = 3, + NARROW = 4, + NORMAL = 5, + WIDE = 7, + EXTRA_WIDE = 10 + }; + + typedef caf::AppEnum WidthScaleFactorEnum; + +public: + virtual RiuQwtPlotWidget* viewer() = 0; + virtual bool isChecked() const = 0; + + virtual int widthScaleFactor() const + { + return NORMAL; + } + virtual void setWidthScaleFactor( WidthScaleFactor scaleFactor ) {} + + virtual bool hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const = 0; + virtual bool applyFontSize( RiaDefines::FontSettingType fontSettingType, + int oldFontSize, + int fontSize, + bool forceChange = false ) = 0; + + virtual void setAutoScaleXEnabled( bool enabled ) = 0; + virtual void setAutoScaleYEnabled( bool enabled ) = 0; + + virtual void updateZoomInQwt() = 0; + virtual void updateZoomFromQwt() = 0; + + virtual QString asciiDataForPlotExport() const; + + virtual void createPlotWidget() = 0; + virtual void detachAllCurves() = 0; + + virtual caf::PdmObject* findPdmObjectFromQwtCurve( const QwtPlotCurve* curve ) const = 0; + + virtual void loadDataAndUpdate() = 0; + + virtual void onAxisSelected( int axis, bool toggle ) {} + +protected: + virtual void updatePlotWindowLayout() {} + virtual void onWidthScaleFactorChange() {} +}; diff --git a/ApplicationCode/ProjectDataModel/RimPlotWindow.cpp b/ApplicationCode/ProjectDataModel/RimPlotWindow.cpp new file mode 100644 index 0000000000..5abbe14e17 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPlotWindow.cpp @@ -0,0 +1,173 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimPlotWindow.h" + +#include "cafPdmUiComboBoxEditor.h" + +CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPlotWindow, "RimPlotWindow" ); // Do not use. Abstract class + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotWindow::RimPlotWindow() +{ + CAF_PDM_InitObject( "Plot", "", "", "" ); + + CAF_PDM_InitField( &m_description, "PlotDescription", QString( "" ), "Name", "", "", "" ); + + CAF_PDM_InitField( &m_showTitleInPlot, "ShowTitleInPlot", false, "Show Title", "", "", "" ); + CAF_PDM_InitField( &m_showPlotLegends, "ShowTrackLegends", true, "Show Legends", "", "", "" ); + CAF_PDM_InitField( &m_plotLegendsHorizontal, "TrackLegendsHorizontal", false, "Legend Orientation", "", "", "" ); + m_plotLegendsHorizontal.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotWindow::~RimPlotWindow() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotWindow& RimPlotWindow::operator=( RimPlotWindow&& rhs ) +{ + m_showTitleInPlot = rhs.m_showTitleInPlot(); + m_showPlotLegends = rhs.m_showPlotLegends(); + m_plotLegendsHorizontal = rhs.m_plotLegendsHorizontal(); + return *this; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotWindow::setDescription( const QString& description ) +{ + m_description = description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimPlotWindow::description() const +{ + return m_description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimPlotWindow::fullPlotTitle() const +{ + return m_description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPlotWindow::isPlotTitleVisible() const +{ + return m_showTitleInPlot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotWindow::setPlotTitleVisible( bool visible ) +{ + m_showTitleInPlot = visible; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPlotWindow::legendsVisible() const +{ + return m_showPlotLegends(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotWindow::setLegendsVisible( bool doShow ) +{ + m_showPlotLegends = doShow; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPlotWindow::legendsHorizontal() const +{ + return m_plotLegendsHorizontal; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotWindow::setLegendsHorizontal( bool horizontal ) +{ + m_plotLegendsHorizontal = horizontal; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotWindow::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + RimViewWindow::fieldChangedByUi( changedField, oldValue, newValue ); + + if ( changedField == &m_showPlotLegends || changedField == &m_plotLegendsHorizontal ) + { + updateLayout(); + } + else if ( changedField == &m_showTitleInPlot ) + { + updatePlotTitle(); + } + + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimPlotWindow::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) +{ + QList options; + if ( fieldNeedingOptions == &m_plotLegendsHorizontal ) + { + options.push_back( caf::PdmOptionItemInfo( "Vertical", QVariant::fromValue( false ) ) ); + options.push_back( caf::PdmOptionItemInfo( "Horizontal", QVariant::fromValue( true ) ) ); + } + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmUiGroup* RimPlotWindow::createPlotSettingsUiGroup( caf::PdmUiOrdering& uiOrdering ) +{ + caf::PdmUiGroup* titleAndLegendsGroup = uiOrdering.addNewGroup( "Title and Legends" ); + titleAndLegendsGroup->add( &m_showPlotLegends ); + titleAndLegendsGroup->add( &m_plotLegendsHorizontal ); + titleAndLegendsGroup->add( &m_showTitleInPlot ); + return titleAndLegendsGroup; +} diff --git a/ApplicationCode/ProjectDataModel/RimPlotWindow.h b/ApplicationCode/ProjectDataModel/RimPlotWindow.h new file mode 100644 index 0000000000..375e57e2ed --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPlotWindow.h @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RimNameConfig.h" +#include "RimViewWindow.h" + +#include "cafPdmField.h" +#include "cafPdmFieldHandle.h" +#include "cafPdmObject.h" + +class QKeyEvent; + +class RimPlotWindow : public RimViewWindow +{ + CAF_PDM_HEADER_INIT; + +public: + RimPlotWindow(); + ~RimPlotWindow(); + + RimPlotWindow& operator=( RimPlotWindow&& rhs ); + + virtual void setDescription( const QString& description ); + virtual QString description() const; + virtual QString fullPlotTitle() const; + + bool isPlotTitleVisible() const; + void setPlotTitleVisible( bool visible ); + bool legendsVisible() const; + void setLegendsVisible( bool doShow ); + bool legendsHorizontal() const; + void setLegendsHorizontal( bool horizontal ); + + virtual void detachAllCurves() = 0; + virtual void handleKeyPressEvent( QKeyEvent* keyEvent ) {} + virtual void updateLayout() = 0; + +protected: + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) override; + + virtual caf::PdmUiGroup* createPlotSettingsUiGroup( caf::PdmUiOrdering& uiOrdering ); + virtual void updatePlotTitle() = 0; + +protected: + caf::PdmField m_description; + caf::PdmField m_showTitleInPlot; + caf::PdmField m_showPlotLegends; + caf::PdmField m_plotLegendsHorizontal; +}; diff --git a/ApplicationCode/ProjectDataModel/RimViewWindow.cpp b/ApplicationCode/ProjectDataModel/RimViewWindow.cpp index 1c6c43b0ee..849938293b 100644 --- a/ApplicationCode/ProjectDataModel/RimViewWindow.cpp +++ b/ApplicationCode/ProjectDataModel/RimViewWindow.cpp @@ -196,6 +196,14 @@ void RimViewWindow::viewNavigationChanged() //-------------------------------------------------------------------------------------------------- void RimViewWindow::onViewNavigationChanged() {} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimViewWindow::isWindowVisible() const +{ + return m_showWindow(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimViewWindow.h b/ApplicationCode/ProjectDataModel/RimViewWindow.h index f8c62ed6f0..3207a68745 100644 --- a/ApplicationCode/ProjectDataModel/RimViewWindow.h +++ b/ApplicationCode/ProjectDataModel/RimViewWindow.h @@ -113,10 +113,7 @@ protected: virtual void deleteViewWidget() = 0; virtual void onLoadDataAndUpdate() = 0; virtual void onViewNavigationChanged(); - virtual bool isWindowVisible() - { - return m_showWindow(); - } // Virtual To allow special visibility control + virtual bool isWindowVisible() const; // Virtual To allow special visibility control ////////// // Derived classes are not supposed to override this function. The intention is to always use m_showWindow diff --git a/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp b/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp index c2497d71e9..be270aeee6 100644 --- a/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp @@ -127,7 +127,7 @@ void RimWellBoreStabilityPlot::defineUiOrdering( QString uiConfigName, caf::PdmU { RimViewWindow::defineUiOrdering( uiConfigName, uiOrdering ); - m_commonDataSource->uiOrdering( uiConfigName, uiOrdering ); + m_commonDataSource->uiOrdering( RimWellLogCurveCommonDataSource::smoothingUiOrderinglabel(), uiOrdering ); caf::PdmUiGroup* parameterSources = uiOrdering.addNewGroup( "Parameter Sources" ); parameterSources->add( &m_porePressureSource ); @@ -137,7 +137,7 @@ void RimWellBoreStabilityPlot::defineUiOrdering( QString uiConfigName, caf::PdmU parameterSources->add( &m_userDefinedUcs ); uiOrderingForDepthAxis( uiOrdering ); - uiOrderingForPlotSettings( uiOrdering ); + createPlotSettingsUiGroup( uiOrdering ); uiOrdering.skipRemainingFields( true ); } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogCurve.cpp index 4ee7a51515..c4692e54e3 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogCurve.cpp @@ -26,7 +26,7 @@ #include "RimWellLogTrack.h" #include "RiuQwtPlotCurve.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" #include "cafPdmUiComboBoxEditor.h" @@ -84,6 +84,47 @@ bool RimWellLogCurve::xValueRangeInData( double* minimumValue, double* maximumVa return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellLogCurve::yValueRangeInData( double* minimumValue, double* maximumValue ) const +{ + CAF_ASSERT( minimumValue && maximumValue ); + + if ( !( minimumValue && maximumValue ) ) + { + return false; + } + + RimWellLogPlot* wellLogPlot = nullptr; + firstAncestorOrThisOfTypeAsserted( wellLogPlot ); + + if ( wellLogPlot->depthType() == RimWellLogPlot::MEASURED_DEPTH ) + { + if ( m_curveDataMDRange.first == -std::numeric_limits::infinity() || + m_curveDataMDRange.second == std::numeric_limits::infinity() ) + { + return false; + } + + *minimumValue = m_curveDataMDRange.first; + *maximumValue = m_curveDataMDRange.second; + } + else + { + if ( m_curveDataTVDRange.first == -std::numeric_limits::infinity() || + m_curveDataTVDRange.second == std::numeric_limits::infinity() ) + { + return false; + } + + *minimumValue = m_curveDataTVDRange.first; + *maximumValue = m_curveDataTVDRange.second; + } + + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -93,7 +134,7 @@ void RimWellLogCurve::setValuesAndMD( const std::vector& xValues, bool isExtractionCurve ) { m_curveData->setValuesAndMD( xValues, measuredDepths, depthUnit, isExtractionCurve ); - calculateCurveDataXRange(); + calculateCurveDataRanges(); } //-------------------------------------------------------------------------------------------------- @@ -106,7 +147,7 @@ void RimWellLogCurve::setValuesWithTVD( const std::vector& xValues, bool isExtractionCurve ) { m_curveData->setValuesWithTVD( xValues, measuredDepths, tvDepths, depthUnit, isExtractionCurve ); - calculateCurveDataXRange(); + calculateCurveDataRanges(); } //-------------------------------------------------------------------------------------------------- @@ -126,15 +167,8 @@ void RimWellLogCurve::updateZoomInParentPlot() firstAncestorOrThisOfType( wellLogPlot ); if ( wellLogPlot ) { - wellLogPlot->calculateAvailableDepthRange(); - wellLogPlot->updateDepthZoom(); - } - - RimWellLogTrack* plotTrack; - firstAncestorOrThisOfType( plotTrack ); - if ( plotTrack ) - { - plotTrack->calculateXZoomRangeAndUpdateQwt(); + wellLogPlot->setAutoScaleYEnabled( true ); + wellLogPlot->updateZoom(); } } @@ -162,11 +196,18 @@ void RimWellLogCurve::setOverrideCurveDataXRange( double minimumValue, double ma //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogCurve::calculateCurveDataXRange() +void RimWellLogCurve::calculateCurveDataRanges() { // Invalidate range first - m_curveDataXRange = std::make_pair( std::numeric_limits::infinity(), + m_curveDataXRange = std::make_pair( std::numeric_limits::infinity(), -std::numeric_limits::infinity() ); + m_curveDataMDRange = std::make_pair( std::numeric_limits::infinity(), + -std::numeric_limits::infinity() ); + m_curveDataTVDRange = std::make_pair( std::numeric_limits::infinity(), + -std::numeric_limits::infinity() ); + + m_curveData->calculateMDRange( &m_curveDataMDRange.first, &m_curveDataMDRange.second ); + m_curveData->calculateTVDRange( &m_curveDataTVDRange.first, &m_curveDataTVDRange.second ); for ( double xValue : m_curveData->xValues() ) { diff --git a/ApplicationCode/ProjectDataModel/RimWellLogCurve.h b/ApplicationCode/ProjectDataModel/RimWellLogCurve.h index f705572ff4..0f9beab563 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogCurve.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogCurve.h @@ -40,6 +40,7 @@ public: ~RimWellLogCurve() override; bool xValueRangeInData( double* minimumValue, double* maximumValue ) const; + bool yValueRangeInData( double* minimumValue, double* maximumValue ) const; void setValuesAndMD( const std::vector& xValues, const std::vector& measuredDepths, @@ -67,9 +68,11 @@ protected: void setOverrideCurveDataXRange( double minimumValue, double maximumValue ); private: - void calculateCurveDataXRange(); + void calculateCurveDataRanges(); private: cvf::ref m_curveData; std::pair m_curveDataXRange; + std::pair m_curveDataMDRange; + std::pair m_curveDataTVDRange; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp b/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp index 9fabcab384..a6bc521136 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.cpp @@ -679,6 +679,14 @@ std::vector RimWellLogCurveCommonDataSource::fieldsToShowI return fieldsToDisplay; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellLogCurveCommonDataSource::smoothingUiOrderinglabel() +{ + return "ApplySmoothing"; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -894,7 +902,7 @@ void RimWellLogCurveCommonDataSource::defineUiOrdering( QString uiConfigName, ca } group->add( &m_timeStep ); - if ( dynamic_cast( m_case() ) ) + if ( uiConfigName == smoothingUiOrderinglabel() ) { group->add( &m_wbsSmoothing ); group->add( &m_wbsSmoothingThreshold ); diff --git a/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.h b/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.h index 8ff1dd71cf..923112f833 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogCurveCommonDataSource.h @@ -87,6 +87,8 @@ public: void applyNextTimeStep(); std::vector fieldsToShowInToolbar(); + static QString smoothingUiOrderinglabel(); + protected: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, diff --git a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp index 3e85342424..1492db3a80 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogExtractionCurve.cpp @@ -59,7 +59,7 @@ #include "RiuPlotMainWindowTools.h" #include "RiuQwtPlotCurve.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" #include "cafPdmUiTreeOrdering.h" #include "cafUtils.h" @@ -371,10 +371,10 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate( bool updateParentPlot ) firstAncestorOrThisOfType( wellLogTrack ); CVF_ASSERT( wellLogTrack ); - RiuWellLogTrack* viewer = wellLogTrack->viewer(); + RiuQwtPlotWidget* viewer = wellLogTrack->viewer(); if ( viewer ) { - viewer->setDepthTitle( "PL/" + wellLogPlot->depthPlotTitle() ); + viewer->setYTitle( "PL/" + wellLogPlot->depthAxisTitle() ); } } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp index a529bc4d13..428d3d2a35 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogFileCurve.cpp @@ -34,7 +34,7 @@ #include "RimWellRftPlot.h" #include "RiuQwtPlotCurve.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" #include "RiaApplication.h" #include "RiaPreferences.h" diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp b/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp index cc759318f7..9e65858d7a 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlot.cpp @@ -30,10 +30,11 @@ #include "RimWellLogCurveCommonDataSource.h" #include "RimWellLogTrack.h" +#include "RiuGridPlotWindow.h" #include "RiuPlotMainWindow.h" #include "RiuPlotMainWindowTools.h" +#include "RiuQwtPlotWidget.h" #include "RiuWellLogPlot.h" -#include "RiuWellLogTrack.h" #include "cafPdmUiComboBoxEditor.h" #include "cvfAssert.h" @@ -57,17 +58,6 @@ void caf::AppEnum::setUp() setDefault( RimWellLogPlot::MEASURED_DEPTH ); } -template <> -void RimWellLogPlot::ColumnCountEnum::setUp() -{ - addItem( RimWellLogPlot::COLUMNS_1, "1", "1 Column" ); - addItem( RimWellLogPlot::COLUMNS_2, "2", "2 Columns" ); - addItem( RimWellLogPlot::COLUMNS_3, "3", "3 Columns" ); - addItem( RimWellLogPlot::COLUMNS_4, "4", "4 Columns" ); - addItem( RimWellLogPlot::COLUMNS_UNLIMITED, "UNLIMITED", "Unlimited" ); - setDefault( RimWellLogPlot::COLUMNS_UNLIMITED ); -} - template <> void RimWellLogPlot::AxisGridEnum::setUp() { @@ -88,11 +78,6 @@ RimWellLogPlot::RimWellLogPlot() { CAF_PDM_InitObject( "Well Log Plot", ":/WellLogPlot16x16.png", "", "" ); - m_viewer = nullptr; - - CAF_PDM_InitField( &m_userName_OBSOLETE, "PlotDescription", QString( "" ), "Name", "", "", "" ); - m_userName_OBSOLETE.xmlCapability()->setIOWritable( false ); - CAF_PDM_InitFieldNoDefault( &m_commonDataSource, "CommonDataSource", "Data Source", @@ -115,15 +100,6 @@ RimWellLogPlot::RimWellLogPlot() CAF_PDM_InitFieldNoDefault( &m_depthAxisGridVisibility, "ShowDepthGridLines", "Show Grid Lines", "", "", "" ); CAF_PDM_InitField( &m_isAutoScaleDepthEnabled, "AutoScaleDepthEnabled", true, "Auto Scale", "", "", "" ); m_isAutoScaleDepthEnabled.uiCapability()->setUiHidden( true ); - CAF_PDM_InitField( &m_showTitleInPlot, "ShowTitleInPlot", false, "Show Title", "", "", "" ); - CAF_PDM_InitField( &m_showTrackLegends, "ShowTrackLegends", true, "Show Legends", "", "", "" ); - CAF_PDM_InitField( &m_trackLegendsHorizontal, "TrackLegendsHorizontal", false, "Legend Orientation", "", "", "" ); - m_trackLegendsHorizontal.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() ); - - CAF_PDM_InitFieldNoDefault( &m_tracks, "Tracks", "", "", "", "" ); - m_tracks.uiCapability()->setUiHidden( true ); - - CAF_PDM_InitFieldNoDefault( &m_columnCountEnum, "NumberOfColumns", "Number of Columns", "", "", "" ); CAF_PDM_InitFieldNoDefault( &m_nameConfig, "NameConfig", "", "", "", "" ); m_nameConfig.uiCapability()->setUiTreeHidden( true ); @@ -142,8 +118,7 @@ RimWellLogPlot::RimWellLogPlot() //-------------------------------------------------------------------------------------------------- RimWellLogPlot& RimWellLogPlot::operator=( RimWellLogPlot&& rhs ) { - // Don't copy the obsoleted m_userName_OBSOLETE - // It had its own implementation in the RFT/PLT/WAP plots + RimGridPlotWindow::operator=( std::move( rhs ) ); auto dataSource = rhs.m_commonDataSource(); rhs.m_commonDataSource.removeChildObject( dataSource ); @@ -155,17 +130,6 @@ RimWellLogPlot& RimWellLogPlot::operator=( RimWellLogPlot&& rhs ) m_maxVisibleDepth = rhs.m_maxVisibleDepth(); m_depthAxisGridVisibility = rhs.m_depthAxisGridVisibility(); m_isAutoScaleDepthEnabled = rhs.m_isAutoScaleDepthEnabled(); - m_showTitleInPlot = rhs.m_showTitleInPlot(); - m_showTrackLegends = rhs.m_showTrackLegends(); - m_trackLegendsHorizontal = rhs.m_trackLegendsHorizontal(); - - // Move all tracks - std::vector tracks = rhs.m_tracks.childObjects(); - rhs.m_tracks.clear(); - for ( RimWellLogTrack* track : tracks ) - { - m_tracks.push_back( track ); - } auto nameConfig = rhs.m_nameConfig(); rhs.m_nameConfig.removeChildObject( nameConfig ); @@ -181,11 +145,6 @@ RimWellLogPlot& RimWellLogPlot::operator=( RimWellLogPlot&& rhs ) //-------------------------------------------------------------------------------------------------- RimWellLogPlot::~RimWellLogPlot() { - removeMdiWindowFromMdiArea(); - - m_tracks.deleteAllChildObjects(); - - deleteViewWidget(); delete m_commonDataSource; delete m_nameConfig; } @@ -193,257 +152,67 @@ RimWellLogPlot::~RimWellLogPlot() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QWidget* RimWellLogPlot::viewWidget() +QWidget* RimWellLogPlot::createPlotWidget( QWidget* mainWindowParent /*= nullptr */ ) { - return m_viewer; + return createViewWidget( mainWindowParent ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, - const QVariant& oldValue, - const QVariant& newValue ) +QString RimWellLogPlot::fullPlotTitle() const { - RimViewWindow::fieldChangedByUi( changedField, oldValue, newValue ); - - if ( changedField == &m_minVisibleDepth || changedField == &m_maxVisibleDepth ) - { - applyDepthZoomFromVisibleDepth(); - - m_isAutoScaleDepthEnabled = false; - } - else if ( changedField == &m_showTrackLegends || changedField == &m_trackLegendsHorizontal || - changedField == &m_depthAxisGridVisibility ) - { - updateTracks(); - } - else if ( changedField == &m_columnCountEnum ) - { - updateTracks(); - updateColumnCount(); - } - else if ( changedField == &m_showTitleInPlot ) - { - m_viewer->setTitleVisible( m_showTitleInPlot() ); - } - else if ( changedField == &m_isAutoScaleDepthEnabled ) - { - updateDepthZoom(); - } - else if ( changedField == &m_depthType ) - { - onDepthTypeChanged(); - updateTracks(); - updateDepthZoom(); - } - else if ( changedField == &m_depthUnit ) - { - updateTracks(); - updateDepthZoom(); - } - - updateConnectedEditors(); + return createAutoName(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList RimWellLogPlot::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, - bool* useOptionsOnly ) +void RimWellLogPlot::updateZoom() { - QList options; - - if ( fieldNeedingOptions == &m_depthType ) + if ( m_isAutoScaleDepthEnabled ) { - using DepthAppEnum = caf::AppEnum; - for ( size_t i = 0; i < DepthAppEnum::size(); ++i ) + calculateAvailableDepthRange(); + if ( m_minAvailableDepth < HUGE_VAL && m_maxAvailableDepth > -HUGE_VAL ) { - DepthTypeEnum enumVal = DepthAppEnum::fromIndex( i ); - - if ( m_availableDepthTypes.count( enumVal ) ) - { - options.push_back( caf::PdmOptionItemInfo( DepthAppEnum::uiText( enumVal ), enumVal ) ); - } - } - } - else if ( fieldNeedingOptions == &m_depthUnit ) - { - using UnitAppEnum = caf::AppEnum; - for ( auto depthUnit : m_availableDepthUnits ) - { - options.push_back( caf::PdmOptionItemInfo( UnitAppEnum::uiText( depthUnit ), depthUnit ) ); - } - } - else if ( fieldNeedingOptions == &m_trackLegendsHorizontal ) - { - options.push_back( caf::PdmOptionItemInfo( "Vertical", QVariant::fromValue( false ) ) ); - options.push_back( caf::PdmOptionItemInfo( "Horizontal", QVariant::fromValue( true ) ) ); - } - else if ( fieldNeedingOptions == &m_columnCountEnum ) - { - for ( size_t i = 0; i < ColumnCountEnum::size(); ++i ) - { - ColumnCount enumVal = ColumnCountEnum::fromIndex( i ); - if ( enumVal == COLUMNS_UNLIMITED ) - { - QString iconPath( ":/ColumnsUnlimited.png" ); - options.push_back( caf::PdmOptionItemInfo( ColumnCountEnum::uiText( enumVal ), - enumVal, - false, - caf::QIconProvider( iconPath ) ) ); - } - else - { - QString iconPath = QString( ":/Columns%1.png" ).arg( static_cast( enumVal ) ); - options.push_back( caf::PdmOptionItemInfo( ColumnCountEnum::uiText( enumVal ), - enumVal, - false, - caf::QIconProvider( iconPath ) ) ); - } + m_minVisibleDepth = m_minAvailableDepth; + m_maxVisibleDepth = m_maxAvailableDepth + 0.01 * ( m_maxAvailableDepth - m_minAvailableDepth ); } } - ( *useOptionsOnly ) = true; - return options; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QImage RimWellLogPlot::snapshotWindowContent() -{ - QImage image; - - if ( m_viewer ) + for ( RimPlotInterface* plot : plots() ) { - m_viewer->setScrollbarVisible( false ); - QPixmap pix = m_viewer->grab(); - image = pix.toImage(); - m_viewer->setScrollbarVisible( true ); + static_cast( plot )->setVisibleYRange( m_minVisibleDepth(), m_maxVisibleDepth() ); } + m_viewer->updateVerticalScrollBar( m_minVisibleDepth(), m_maxVisibleDepth(), m_minAvailableDepth, m_maxAvailableDepth ); - return image; + RimGridPlotWindow::updateZoom(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::addTrack( RimWellLogTrack* track ) -{ - m_tracks.push_back( track ); - if ( m_viewer ) - { - track->recreateViewer(); - m_viewer->addTrackPlot( track->viewer() ); - } - updateColumnCount(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::insertTrack( RimWellLogTrack* track, size_t index ) -{ - m_tracks.insert( index, track ); - - if ( m_viewer ) - { - track->recreateViewer(); - m_viewer->insertTrackPlot( track->viewer(), index ); - } - - updateTrackNames(); - updateColumnCount(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::removeTrack( RimWellLogTrack* track ) -{ - if ( track ) - { - if ( m_viewer ) m_viewer->removeTrackPlot( track->viewer() ); - m_tracks.removeChildObject( track ); - - updateColumnCount(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellLogTrack* RimWellLogPlot::trackByIndex( size_t index ) const -{ - return m_tracks[index]; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RimWellLogPlot::firstVisibleTrackIndex() const -{ - for ( size_t i = 0; i < m_tracks.size(); ++i ) - { - if ( m_tracks[i]->isVisible() ) - { - return i; - } - } - return std::numeric_limits::max(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimWellLogPlot::tracks() const -{ - return m_tracks.childObjects(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimWellLogPlot::visibleTracks() const -{ - std::vector tracks; - for ( RimWellLogTrack* track : m_tracks() ) - { - if ( track->isVisible() ) - { - tracks.push_back( track ); - } - } - return tracks; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setDepthZoomByFactorAndCenter( double zoomFactor, double zoomCenter ) +void RimWellLogPlot::setDepthAxisRangeByFactorAndCenter( double zoomFactor, double zoomCenter ) { double newMinimum = zoomCenter - ( zoomCenter - m_minVisibleDepth ) * zoomFactor; double newMaximum = zoomCenter + ( m_maxVisibleDepth - zoomCenter ) * zoomFactor; - setDepthZoomMinMax( newMinimum, newMaximum ); - setDepthAutoZoom( false ); + setDepthAxisRange( newMinimum, newMaximum ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::panDepth( double panFactor ) +void RimWellLogPlot::setDepthAxisRangeByPanDepth( double panFactor ) { double delta = panFactor * ( m_maxVisibleDepth - m_minVisibleDepth ); - setDepthZoomMinMax( m_minVisibleDepth + delta, m_maxVisibleDepth + delta ); - setDepthAutoZoom( false ); + setDepthAxisRange( m_minVisibleDepth + delta, m_maxVisibleDepth + delta ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setDepthZoomMinMax( double minimumDepth, double maximumDepth ) +void RimWellLogPlot::setDepthAxisRange( double minimumDepth, double maximumDepth ) { m_minVisibleDepth = minimumDepth; m_maxVisibleDepth = maximumDepth; @@ -451,7 +220,8 @@ void RimWellLogPlot::setDepthZoomMinMax( double minimumDepth, double maximumDept m_minVisibleDepth.uiCapability()->updateConnectedEditors(); m_maxVisibleDepth.uiCapability()->updateConnectedEditors(); - applyDepthZoomFromVisibleDepth(); + setAutoScaleYEnabled( false ); + updateZoom(); } //-------------------------------------------------------------------------------------------------- @@ -462,14 +232,16 @@ void RimWellLogPlot::calculateAvailableDepthRange() double minDepth = HUGE_VAL; double maxDepth = -HUGE_VAL; - for ( size_t tIdx = 0; tIdx < m_tracks.size(); tIdx++ ) + auto plots = this->plots(); + + for ( size_t tIdx = 0; tIdx < plots.size(); tIdx++ ) { double minTrackDepth = HUGE_VAL; double maxTrackDepth = -HUGE_VAL; - if ( m_tracks[tIdx]->isVisible() ) + if ( plots[tIdx]->isChecked() ) { - m_tracks[tIdx]->availableDepthRange( &minTrackDepth, &maxTrackDepth ); + static_cast( plots[tIdx] )->availableDepthRange( &minTrackDepth, &maxTrackDepth ); if ( minTrackDepth < minDepth ) { @@ -483,8 +255,11 @@ void RimWellLogPlot::calculateAvailableDepthRange() } } - m_minAvailableDepth = minDepth; - m_maxAvailableDepth = maxDepth; + if ( minDepth < HUGE_VAL && maxDepth > -HUGE_VAL ) + { + m_minAvailableDepth = minDepth; + m_maxAvailableDepth = maxDepth; + } } //-------------------------------------------------------------------------------------------------- @@ -492,40 +267,14 @@ void RimWellLogPlot::calculateAvailableDepthRange() //-------------------------------------------------------------------------------------------------- void RimWellLogPlot::availableDepthRange( double* minimumDepth, double* maximumDepth ) const { - if ( hasAvailableDepthRange() ) - { - *minimumDepth = m_minAvailableDepth; - *maximumDepth = m_maxAvailableDepth; - } - else - { - *minimumDepth = RI_LOGPLOT_MINDEPTH_DEFAULT; - *maximumDepth = RI_LOGPLOT_MAXDEPTH_DEFAULT; - } + *minimumDepth = m_minAvailableDepth; + *maximumDepth = m_maxAvailableDepth; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellLogPlot::hasAvailableDepthRange() const -{ - return m_minAvailableDepth < HUGE_VAL && m_maxAvailableDepth > -HUGE_VAL; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::zoomAll() -{ - setDepthAutoZoom( true ); - updateDepthZoom(); - updateTracks( true ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setDepthAutoZoom( bool on ) +void RimWellLogPlot::setAutoScaleYEnabled( bool on ) { m_isAutoScaleDepthEnabled = on; m_isAutoScaleDepthEnabled.uiCapability()->updateConnectedEditors(); @@ -539,92 +288,6 @@ void RimWellLogPlot::enableAllAutoNameTags( bool enable ) m_nameConfig->enableAllAutoNameTags( enable ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RimWellLogPlot::asciiDataForPlotExport() const -{ - QString out = description() + "\n"; - - for ( RimWellLogTrack* track : m_tracks ) - { - if ( !track->isVisible() ) continue; - - out += "\n" + track->description() + "\n"; - - std::vector curves = track->curvesVector(); - - std::vector curveNames; - std::vector curveDepths; - std::vector> curvesPlotXValues; - - for ( RimWellLogCurve* curve : curves ) - { - if ( !curve->isCurveVisible() ) continue; - - const RigWellLogCurveData* curveData = curve->curveData(); - if ( !curveData ) continue; - curveNames.push_back( curve->curveName() ); - - if ( curveNames.size() == 1 ) - { - if ( depthType() == TRUE_VERTICAL_DEPTH ) - { - curveDepths = curveData->trueDepthPlotValues( depthUnit() ); - } - else - { - curveDepths = curveData->measuredDepthPlotValues( depthUnit() ); - } - } - - std::vector xPlotValues = curveData->xPlotValues(); - if ( curveDepths.size() != xPlotValues.size() || xPlotValues.empty() ) - { - curveNames.pop_back(); - - if ( curveNames.empty() ) - { - curveDepths.clear(); - } - continue; - } - curvesPlotXValues.push_back( xPlotValues ); - } - - for ( size_t i = 0; i < curveDepths.size(); ++i ) - { - if ( i == 0 ) - { - if ( depthType() == CONNECTION_NUMBER ) - out += "Connection"; - else if ( depthType() == MEASURED_DEPTH ) - out += "MD "; - else if ( depthType() == PSEUDO_LENGTH ) - out += "PL "; - else if ( depthType() == TRUE_VERTICAL_DEPTH ) - out += "TVD "; - for ( QString name : curveNames ) - out += " \t" + name; - out += "\n"; - } - else if ( curveDepths[i] == curveDepths[i - 1] ) - { - continue; - } - - out += QString::number( curveDepths[i], 'f', 3 ); - for ( std::vector plotVector : curvesPlotXValues ) - { - out += " \t" + QString::number( plotVector[i], 'g' ); - } - out += "\n"; - } - } - - return out; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -650,14 +313,11 @@ void RimWellLogPlot::uiOrderingForDepthAxis( caf::PdmUiOrdering& uiOrdering ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::uiOrderingForPlotSettings( caf::PdmUiOrdering& uiOrdering ) +caf::PdmUiGroup* RimWellLogPlot::createPlotSettingsUiGroup( caf::PdmUiOrdering& uiOrdering ) { - caf::PdmUiGroup* titleAndLegendsGroup = uiOrdering.addNewGroup( "Title and Legends" ); - titleAndLegendsGroup->add( &m_showTrackLegends ); - titleAndLegendsGroup->add( &m_trackLegendsHorizontal ); - titleAndLegendsGroup->add( &m_showTitleInPlot ); - titleAndLegendsGroup->add( &m_columnCountEnum ); + caf::PdmUiGroup* titleAndLegendsGroup = RimGridPlotWindow::createPlotSettingsUiGroup( uiOrdering ); m_nameConfig->uiOrdering( "", *titleAndLegendsGroup ); + return titleAndLegendsGroup; } //-------------------------------------------------------------------------------------------------- @@ -738,13 +398,23 @@ QString RimWellLogPlot::createAutoName() const return generatedCurveName.join( ": " ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* RimWellLogPlot::createViewWidget( QWidget* mainWindowParent ) +{ + m_viewer = new RiuWellLogPlot( this, mainWindowParent ); + recreatePlotWidgets(); + return m_viewer; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogPlot::performAutoNameUpdate() { updateCommonDataSource(); - this->updatePlotTitle(); + this->setPlotTitleInWidget( this->createAutoName() ); } //-------------------------------------------------------------------------------------------------- @@ -825,36 +495,11 @@ void RimWellLogPlot::setAvailableDepthTypes( const std::set& dept //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::updateTrackOrderFromWidget() +void RimWellLogPlot::onPlotAdditionOrRemoval() { - std::sort( m_tracks.begin(), m_tracks.end(), [this]( RimWellLogTrack* lhs, RimWellLogTrack* rhs ) { - return m_viewer->indexOfTrackPlot( lhs->viewer() ) < m_viewer->indexOfTrackPlot( rhs->viewer() ); - } ); - updateTrackNames(); - updateConnectedEditors(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::depthZoomMinMax( double* minimumDepth, double* maximumDepth ) const -{ - *minimumDepth = m_minVisibleDepth; - *maximumDepth = m_maxVisibleDepth; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) -{ - RimViewWindow::defineUiOrdering( uiConfigName, uiOrdering ); - - m_commonDataSource->uiOrdering( uiConfigName, uiOrdering ); - uiOrderingForDepthAxis( uiOrdering ); - uiOrderingForPlotSettings( uiOrdering ); - - uiOrdering.skipRemainingFields( true ); + calculateAvailableDepthRange(); + updateZoom(); + RimGridPlotWindow::onPlotAdditionOrRemoval(); } //-------------------------------------------------------------------------------------------------- @@ -868,161 +513,88 @@ caf::PdmFieldHandle* RimWellLogPlot::userDescriptionField() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::onLoadDataAndUpdate() +void RimWellLogPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) { - updateMdiWindowVisibility(); - updatePlotTitle(); - updateTracks(); + RimGridPlotWindow::fieldChangedByUi( changedField, oldValue, newValue ); + + if ( changedField == &m_minVisibleDepth || changedField == &m_maxVisibleDepth ) + { + m_isAutoScaleDepthEnabled = false; + updateZoom(); + } + else if ( changedField == &m_depthAxisGridVisibility ) + { + updateLayout(); + } + else if ( changedField == &m_isAutoScaleDepthEnabled ) + { + if ( m_isAutoScaleDepthEnabled ) + { + updateZoom(); + } + } + else if ( changedField == &m_depthType ) + { + m_isAutoScaleDepthEnabled = true; + loadDataAndUpdate(); + } + else if ( changedField == &m_depthUnit ) + { + m_isAutoScaleDepthEnabled = true; + updateZoom(); + } + + updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::updateTracks( bool autoScaleXAxis ) +void RimWellLogPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { - if ( m_showWindow ) + RimGridPlotWindow::defineUiOrdering( uiConfigName, uiOrdering ); + + uiOrderingForDepthAxis( uiOrdering ); + createPlotSettingsUiGroup( uiOrdering ); + + uiOrdering.skipRemainingFields( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimWellLogPlot::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) +{ + QList options = RimGridPlotWindow::calculateValueOptions( fieldNeedingOptions, + useOptionsOnly ); + + if ( fieldNeedingOptions == &m_depthType ) { - for ( size_t tIdx = 0; tIdx < m_tracks.size(); ++tIdx ) + using DepthAppEnum = caf::AppEnum; + for ( size_t i = 0; i < DepthAppEnum::size(); ++i ) { - m_tracks[tIdx]->loadDataAndUpdate(); - if ( autoScaleXAxis ) + DepthTypeEnum enumVal = DepthAppEnum::fromIndex( i ); + + if ( m_availableDepthTypes.count( enumVal ) ) { - m_tracks[tIdx]->setAutoScaleXEnabled( true ); - m_tracks[tIdx]->calculateXZoomRangeAndUpdateQwt(); - m_tracks[tIdx]->updateAxisAndGridTickIntervals(); + options.push_back( caf::PdmOptionItemInfo( DepthAppEnum::uiText( enumVal ), enumVal ) ); } } - - calculateAvailableDepthRange(); - applyDepthZoomFromVisibleDepth(); - if ( m_viewer ) m_viewer->updateChildrenLayout(); } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::updateTrackNames() -{ - for ( size_t tIdx = 0; tIdx < m_tracks.size(); tIdx++ ) + else if ( fieldNeedingOptions == &m_depthUnit ) { - QString description = m_tracks[tIdx]->description(); - QRegularExpression regexp( "Track \\d+" ); - description.replace( regexp, QString( "Track %1" ).arg( tIdx + 1 ) ); - m_tracks[tIdx]->setDescription( description ); + using UnitAppEnum = caf::AppEnum; + for ( auto depthUnit : m_availableDepthUnits ) + { + options.push_back( caf::PdmOptionItemInfo( UnitAppEnum::uiText( depthUnit ), depthUnit ) ); + } } -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::updateDepthZoom() -{ - if ( m_isAutoScaleDepthEnabled ) - { - applyZoomAllDepths(); - } - else - { - applyDepthZoomFromVisibleDepth(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::applyDepthZoomFromVisibleDepth() -{ - if ( m_viewer ) - { - double minDepth = m_minVisibleDepth < HUGE_VAL ? m_minVisibleDepth : RI_LOGPLOT_MINDEPTH_DEFAULT; - double maxDepth = m_maxVisibleDepth > -HUGE_VAL ? m_maxVisibleDepth : RI_LOGPLOT_MAXDEPTH_DEFAULT; - - m_viewer->setDepthZoomAndReplot( minDepth, maxDepth ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::applyZoomAllDepths() -{ - calculateAvailableDepthRange(); - - if ( hasAvailableDepthRange() ) - { - setDepthZoomMinMax( m_minAvailableDepth, - m_maxAvailableDepth + 0.01 * ( m_maxAvailableDepth - m_minAvailableDepth ) ); - } - else - { - setDepthZoomMinMax( RI_LOGPLOT_MINDEPTH_DEFAULT, RI_LOGPLOT_MAXDEPTH_DEFAULT ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::recreateTrackPlots() -{ - CVF_ASSERT( m_viewer ); - - for ( size_t tIdx = 0; tIdx < m_tracks.size(); ++tIdx ) - { - m_tracks[tIdx]->recreateViewer(); - m_viewer->addTrackPlot( m_tracks[tIdx]->viewer() ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::detachAllCurves() -{ - for ( size_t tIdx = 0; tIdx < m_tracks.size(); ++tIdx ) - { - m_tracks[tIdx]->detachAllCurves(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setDescription( const QString& description ) -{ - m_nameConfig->setCustomName( description ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RimWellLogPlot::description() const -{ - return m_nameConfig->customName(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QWidget* RimWellLogPlot::createViewWidget( QWidget* mainWindowParent ) -{ - m_viewer = new RiuWellLogPlot( this, mainWindowParent ); - recreateTrackPlots(); - return m_viewer; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::deleteViewWidget() -{ - detachAllCurves(); - - if ( m_viewer ) - { - m_viewer->deleteLater(); - m_viewer = nullptr; - } + ( *useOptionsOnly ) = true; + return options; } //-------------------------------------------------------------------------------------------------- @@ -1030,12 +602,12 @@ void RimWellLogPlot::deleteViewWidget() //-------------------------------------------------------------------------------------------------- void RimWellLogPlot::initAfterRead() { - RimViewWindow::initAfterRead(); + RimGridPlotWindow::initAfterRead(); updateCommonDataSource(); - if ( !m_userName_OBSOLETE().isEmpty() ) + if ( !m_description().isEmpty() ) { - m_nameConfig->setCustomName( m_userName_OBSOLETE() ); + m_nameConfig->setCustomName( m_description() ); } } @@ -1083,7 +655,7 @@ RiaDefines::DepthUnitType RimWellLogPlot::depthUnit() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellLogPlot::depthPlotTitle() const +QString RimWellLogPlot::depthAxisTitle() const { QString depthTitle = "Depth"; @@ -1127,7 +699,7 @@ QString RimWellLogPlot::depthPlotTitle() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::enableDepthGridLines( AxisGridVisibility gridVisibility ) +void RimWellLogPlot::enableDepthAxisGridLines( AxisGridVisibility gridVisibility ) { m_depthAxisGridVisibility = gridVisibility; } @@ -1135,87 +707,11 @@ void RimWellLogPlot::enableDepthGridLines( AxisGridVisibility gridVisibility ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellLogPlot::AxisGridVisibility RimWellLogPlot::depthGridLinesVisibility() const +RimWellLogPlot::AxisGridVisibility RimWellLogPlot::depthAxisGridLinesEnabled() const { return m_depthAxisGridVisibility(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellLogPlot::isPlotTitleVisible() const -{ - return m_showTitleInPlot(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setPlotTitleVisible( bool visible ) -{ - m_showTitleInPlot = visible; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellLogPlot::areTrackLegendsVisible() const -{ - return m_showTrackLegends(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setTrackLegendsVisible( bool doShow ) -{ - m_showTrackLegends = doShow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellLogPlot::areTrackLegendsHorizontal() const -{ - return m_trackLegendsHorizontal; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::setTrackLegendsHorizontal( bool horizontal ) -{ - m_trackLegendsHorizontal = horizontal; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RimWellLogPlot::columnCount() const -{ - if ( m_columnCountEnum() == COLUMNS_UNLIMITED ) - { - return static_cast( visibleTracks().size() ); - } - return static_cast( m_columnCountEnum() ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimWellLogPlot::columnCountField() -{ - return &m_columnCountEnum; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RimWellLogPlot::trackIndex( const RimWellLogTrack* track ) const -{ - return m_tracks.index( track ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1223,30 +719,5 @@ void RimWellLogPlot::setDepthUnit( RiaDefines::DepthUnitType depthUnit ) { m_depthUnit = depthUnit; - updateTracks(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::updatePlotTitle() -{ - if ( m_viewer ) - { - m_viewer->setPlotTitle( this->createAutoName() ); - } - updateMdiWindowTitle(); -} - -//-------------------------------------------------------------------------------------------------- -/// Default empty implementation -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::onDepthTypeChanged() {} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogPlot::updateColumnCount() -{ - RiuPlotMainWindowTools::refreshToolbars(); + updateLayout(); } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlot.h b/ApplicationCode/ProjectDataModel/RimWellLogPlot.h index d88b422f5d..5198b461de 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlot.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlot.h @@ -27,8 +27,7 @@ #include "cafPdmObject.h" #include "RiaDefines.h" -#include "RimPlot.h" -#include "RimViewWindow.h" +#include "RimGridPlotWindow.h" #include "RimWellLogPlotNameConfig.h" #include @@ -36,15 +35,15 @@ #include class RimWellLogCurveCommonDataSource; -class RiuWellLogPlot; -class RimWellLogTrack; +class RiuGridPlotWindow; +class RimPlotInterface; class QKeyEvent; //================================================================================================== /// /// //================================================================================================== -class RimWellLogPlot : public RimPlot, public RimNameConfigHolderInterface +class RimWellLogPlot : public RimGridPlotWindow, public RimNameConfigHolderInterface { CAF_PDM_HEADER_INIT; @@ -57,16 +56,6 @@ public: CONNECTION_NUMBER }; - enum ColumnCount - { - COLUMNS_1 = 1, - COLUMNS_2 = 2, - COLUMNS_3 = 3, - COLUMNS_4 = 4, - COLUMNS_UNLIMITED = 1000, - }; - typedef caf::AppEnum ColumnCountEnum; - enum AxisGridVisibility { AXIS_GRID_NONE, @@ -80,114 +69,66 @@ public: RimWellLogPlot(); ~RimWellLogPlot() override; + QWidget* createPlotWidget( QWidget* mainWindowParent = nullptr ); + QString fullPlotTitle() const override; + RimWellLogPlot& operator=( RimWellLogPlot&& rhs ); - QWidget* viewWidget() override; - - void setDescription( const QString& description ); - QString description() const; - DepthTypeEnum depthType() const; void setDepthType( DepthTypeEnum depthType ); RiaDefines::DepthUnitType depthUnit() const; void setDepthUnit( RiaDefines::DepthUnitType depthUnit ); - QString depthPlotTitle() const; - void enableDepthGridLines( AxisGridVisibility gridVisibility ); - AxisGridVisibility depthGridLinesVisibility() const; + QString depthAxisTitle() const; + void enableDepthAxisGridLines( AxisGridVisibility gridVisibility ); + AxisGridVisibility depthAxisGridLinesEnabled() const; - bool isPlotTitleVisible() const; - void setPlotTitleVisible( bool visible ); - bool areTrackLegendsVisible() const; - void setTrackLegendsVisible( bool doShow ); - bool areTrackLegendsHorizontal() const; - void setTrackLegendsHorizontal( bool horizontal ); - int columnCount() const; - caf::PdmFieldHandle* columnCountField(); - - void addTrack( RimWellLogTrack* track ); - void insertTrack( RimWellLogTrack* track, size_t index ); - size_t trackCount() const - { - return m_tracks.size(); - } - - void removeTrack( RimWellLogTrack* track ); - size_t trackIndex( const RimWellLogTrack* track ) const; - RimWellLogTrack* trackByIndex( size_t index ) const; - size_t firstVisibleTrackIndex() const; - std::vector tracks() const; - std::vector visibleTracks() const; - void updateTracks( bool autoScaleXAxis = false ); - void updateTrackNames(); - - void updateDepthZoom(); - void setDepthZoomByFactorAndCenter( double zoomFactor, double zoomCenter ); - void panDepth( double panFactor ); - void setDepthZoomMinMax( double minimumDepth, double maximumDepth ); - void depthZoomMinMax( double* minimumDepth, double* maximumDepth ) const; + void updateZoom() override; + void setDepthAxisRangeByFactorAndCenter( double zoomFactor, double zoomCenter ); + void setDepthAxisRangeByPanDepth( double panFactor ); + void setDepthAxisRange( double minimumDepth, double maximumDepth ); void calculateAvailableDepthRange(); void availableDepthRange( double* minimumDepth, double* maximumDepth ) const; - bool hasAvailableDepthRange() const; - void zoomAll() override; - void setDepthAutoZoom( bool on ); + void setAutoScaleYEnabled( bool enabled ) override; void enableAllAutoNameTags( bool enable ); - QString asciiDataForPlotExport() const; - - void uiOrderingForDepthAxis( caf::PdmUiOrdering& uiOrdering ); - void uiOrderingForPlotSettings( caf::PdmUiOrdering& uiOrdering ); + void uiOrderingForDepthAxis( caf::PdmUiOrdering& uiOrdering ); + caf::PdmUiGroup* createPlotSettingsUiGroup( caf::PdmUiOrdering& uiOrdering ); QString createAutoName() const override; - void handleKeyPressEvent( QKeyEvent* keyEvent ); RimWellLogCurveCommonDataSource* commonDataSource() const; void updateCommonDataSource(); void setAvailableDepthUnits( const std::set& depthUnits ); void setAvailableDepthTypes( const std::set& depthTypes ); - void updateTrackOrderFromWidget(); + + void onPlotAdditionOrRemoval() override; protected: - void performAutoNameUpdate() override; + QWidget* createViewWidget( QWidget* mainWindowParent ) override; + void performAutoNameUpdate() override; + void handleKeyPressEvent( QKeyEvent* keyEvent ) override; + caf::PdmFieldHandle* userDescriptionField() override; // Overridden PDM methods void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; - caf::PdmFieldHandle* userDescriptionField() override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) override; - void onLoadDataAndUpdate() override; - - QImage snapshotWindowContent() override; - - QWidget* createViewWidget( QWidget* mainWindowParent ) override; - void deleteViewWidget() override; void initAfterRead() override; void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; -private: - void applyZoomAllDepths(); - void applyDepthZoomFromVisibleDepth(); - void recreateTrackPlots(); - void detachAllCurves(); - - void updatePlotTitle(); - virtual void onDepthTypeChanged(); - void updateColumnCount(); - protected: - caf::PdmField m_userName_OBSOLETE; caf::PdmChildField m_commonDataSource; - caf::PdmChildArrayField m_tracks; caf::PdmField> m_depthType; caf::PdmField> m_depthUnit; @@ -196,11 +137,6 @@ protected: caf::PdmField m_depthAxisGridVisibility; caf::PdmField m_isAutoScaleDepthEnabled; - caf::PdmField m_showTitleInPlot; - caf::PdmField m_showTrackLegends; - caf::PdmField m_trackLegendsHorizontal; - caf::PdmField m_columnCountEnum; - caf::PdmChildField m_nameConfig; std::set m_availableDepthUnits; @@ -208,7 +144,4 @@ protected: double m_minAvailableDepth; double m_maxAvailableDepth; - - friend class RiuWellLogPlot; - QPointer m_viewer; }; diff --git a/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h b/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h index 1c42d74e5b..3068277bd0 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogPlotCollection.h @@ -33,7 +33,6 @@ class RigGeoMechCaseData; class RigWellPath; class RimWellPath; class RimEclipseCase; -class RiuWellLogPlot; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp b/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp index c142a78aeb..0a4391b3be 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogRftCurve.cpp @@ -50,7 +50,7 @@ #include "RimWellRftPlot.h" #include "RiuQwtPlotCurve.h" -#include "RiuWellLogTrack.h" +#include "RiuQwtPlotWidget.h" #include "cafPdmObject.h" #include "cafVecIjk.h" @@ -459,24 +459,24 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot ) firstAncestorOrThisOfType( wellLogTrack ); CVF_ASSERT( wellLogTrack ); - RiuWellLogTrack* viewer = wellLogTrack->viewer(); + RiuQwtPlotWidget* viewer = wellLogTrack->viewer(); if ( viewer ) { if ( m_derivedMDSource == NO_SOURCE ) { - viewer->setDepthTitle( "TVDMSL" ); + viewer->setYTitle( "TVDMSL" ); } else if ( m_derivedMDSource == PSEUDO_LENGTH ) { - viewer->setDepthTitle( "PL/" + wellLogPlot->depthPlotTitle() ); + viewer->setYTitle( "PL/" + wellLogPlot->depthAxisTitle() ); } else if ( m_derivedMDSource == WELL_PATH ) { - viewer->setDepthTitle( "WELL/" + wellLogPlot->depthPlotTitle() ); + viewer->setYTitle( "WELL/" + wellLogPlot->depthAxisTitle() ); } else { - viewer->setDepthTitle( "OBS/" + wellLogPlot->depthPlotTitle() ); + viewer->setYTitle( "OBS/" + wellLogPlot->depthAxisTitle() ); } } } diff --git a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp index 65730e65cf..956841e16b 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellLogTrack.cpp @@ -66,21 +66,21 @@ #include "RimWellPltPlot.h" #include "RimWellRftPlot.h" +#include "RiuGridPlotWindow.h" #include "RiuMainWindow.h" #include "RiuPlotAnnotationTool.h" #include "RiuPlotMainWindowTools.h" -#include "RiuWellLogPlot.h" +#include "RiuQwtPlotWidget.h" #include "RiuWellLogTrack.h" #include "RiuWellPathComponentPlotItem.h" #include "RiuQwtLinearScaleEngine.h" #include "cafPdmUiSliderEditor.h" +#include "cafSelectionManager.h" #include "cvfAssert.h" - #define RI_LOGPLOTTRACK_MINX_DEFAULT -10.0 #define RI_LOGPLOTTRACK_MAXX_DEFAULT 100.0 -#define RI_LOGPLOTTRACK_MINOR_TICK_DEFAULT CAF_PDM_SOURCE_INIT( RimWellLogTrack, "WellLogPlotTrack" ); @@ -122,17 +122,6 @@ void AppEnum::setUp() setDefault( RigWellPathFormations::ALL ); } -template <> -void AppEnum::setUp() -{ - addItem( RimWellLogTrack::EXTRA_NARROW_TRACK, "EXTRA_NARROW_TRACK", "Extra Narrow" ); - addItem( RimWellLogTrack::NARROW_TRACK, "NARROW_TRACK", "Narrow" ); - addItem( RimWellLogTrack::NORMAL_TRACK, "NORMAL_TRACK", "Normal" ); - addItem( RimWellLogTrack::WIDE_TRACK, "WIDE_TRACK", "Wide" ); - addItem( RimWellLogTrack::EXTRA_WIDE_TRACK, "EXTRA_WIDE_TRACK", "Extra wide" ); - setDefault( RimWellLogTrack::NORMAL_TRACK ); -} - template <> void AppEnum::setUp() { @@ -161,17 +150,25 @@ RimWellLogTrack::RimWellLogTrack() { CAF_PDM_InitObject( "Track", ":/WellLogTrack16x16.png", "", "" ); - CAF_PDM_InitFieldNoDefault( &m_userName, "TrackDescription", "Name", "", "", "" ); - m_userName.uiCapability()->setUiReadOnly( true ); - - CAF_PDM_InitField( &m_show, "Show", true, "Show Track", "", "", "" ); + CAF_PDM_InitField( &m_show, "Show", true, "Show Plot", "", "", "" ); m_show.uiCapability()->setUiHidden( true ); - CAF_PDM_InitFieldNoDefault( &curves, "Curves", "", "", "", "" ); - curves.uiCapability()->setUiHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_description, "TrackDescription", "Name", "", "", "" ); + + m_description.uiCapability()->setUiReadOnly( true ); + CAF_PDM_InitFieldNoDefault( &m_widthScaleFactor, "Width", "Track Width", "", "Set width of track. ", "" ); + + CAF_PDM_InitFieldNoDefault( &m_curves, "Curves", "", "", "", "" ); + m_curves.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_visibleXRangeMin, "VisibleXRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min", "", "", "" ); CAF_PDM_InitField( &m_visibleXRangeMax, "VisibleXRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max", "", "", "" ); + CAF_PDM_InitField( &m_visibleYRangeMin, "VisibleYRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min", "", "", "" ); + CAF_PDM_InitField( &m_visibleYRangeMax, "VisibleYRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max", "", "", "" ); + m_visibleYRangeMin.uiCapability()->setUiHidden( true ); + m_visibleYRangeMin.xmlCapability()->disableIO(); + m_visibleYRangeMax.uiCapability()->setUiHidden( true ); + m_visibleYRangeMax.xmlCapability()->disableIO(); CAF_PDM_InitField( &m_isAutoScaleXEnabled, "AutoScaleX", true, "Auto Scale", "", "", "" ); m_isAutoScaleXEnabled.uiCapability()->setUiHidden( true ); @@ -252,8 +249,6 @@ RimWellLogTrack::RimWellLogTrack() CAF_PDM_InitFieldNoDefault( &m_wellPathComponentSource, "AttributesWellPathSource", "Well Path", "", "", "" ); CAF_PDM_InitFieldNoDefault( &m_wellPathAttributeCollection, "AttributesCollection", "Well Attributes", "", "", "" ); - CAF_PDM_InitFieldNoDefault( &m_widthScaleFactor, "Width", "Track Width", "", "Set width of track. ", "" ); - m_formationsForCaseWithSimWellOnly = false; } @@ -262,13 +257,31 @@ RimWellLogTrack::RimWellLogTrack() //-------------------------------------------------------------------------------------------------- RimWellLogTrack::~RimWellLogTrack() { - curves.deleteAllChildObjects(); + m_curves.deleteAllChildObjects(); +} - if ( m_wellLogTrackPlotWidget ) - { - m_wellLogTrackPlotWidget->deleteLater(); - m_wellLogTrackPlotWidget = nullptr; - } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellLogTrack::isChecked() const +{ + return m_show(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setChecked( bool checked ) +{ + m_show = checked; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QString RimWellLogTrack::description() const +{ + return m_description; } //-------------------------------------------------------------------------------------------------- @@ -276,7 +289,23 @@ RimWellLogTrack::~RimWellLogTrack() //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::setDescription( const QString& description ) { - m_userName = description; + m_description = description; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimWellLogTrack::widthScaleFactor() const +{ + return static_cast( m_widthScaleFactor() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setWidthScaleFactor( WidthScaleFactor scaleFactor ) +{ + m_widthScaleFactor = scaleFactor; } //-------------------------------------------------------------------------------------------------- @@ -303,6 +332,165 @@ void RimWellLogTrack::simWellOptionItems( QList* options } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::calculateXZoomRange() +{ + std::map> stackCurveGroups = visibleStackedCurves(); + for ( const std::pair>& curveGroup : stackCurveGroups ) + { + for ( RimWellFlowRateCurve* stCurve : curveGroup.second ) + stCurve->updateStackedPlotData(); + } + + if ( !m_isAutoScaleXEnabled() ) + { + return; + } + + double minValue = HUGE_VAL; + double maxValue = -HUGE_VAL; + + size_t visibleCurves = 0u; + for ( auto curve : m_curves ) + { + double minCurveValue = HUGE_VAL; + double maxCurveValue = -HUGE_VAL; + + if ( curve->isCurveVisible() ) + { + visibleCurves++; + if ( curve->xValueRangeInData( &minCurveValue, &maxCurveValue ) ) + { + if ( minCurveValue < minValue ) + { + minValue = minCurveValue; + } + + if ( maxCurveValue > maxValue ) + { + maxValue = maxCurveValue; + } + } + } + } + + if ( minValue == HUGE_VAL ) + { + if ( visibleCurves ) + { + minValue = RI_LOGPLOTTRACK_MINX_DEFAULT; + maxValue = RI_LOGPLOTTRACK_MAXX_DEFAULT; + } + else + { + // Empty axis when there are no curves + minValue = 0; + maxValue = 0; + } + } + + if ( m_minorTickInterval() != 0.0 ) + { + std::tie( minValue, maxValue ) = adjustXRange( minValue, maxValue, m_minorTickInterval() ); + } + + m_visibleXRangeMin = minValue; + m_visibleXRangeMax = maxValue; + + computeAndSetXRangeMinForLogarithmicScale(); + updateEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::calculateYZoomRange() +{ + double minDepth = HUGE_VAL; + double maxDepth = -HUGE_VAL; + + for ( RimWellLogCurve* curve : m_curves ) + { + double minCurveDepth = HUGE_VAL; + double maxCurveDepth = -HUGE_VAL; + + if ( curve->isCurveVisible() && curve->yValueRangeInData( &minCurveDepth, &maxCurveDepth ) ) + { + if ( minCurveDepth < minDepth ) + { + minDepth = minCurveDepth; + } + + if ( maxCurveDepth > maxDepth ) + { + maxDepth = maxCurveDepth; + } + } + } + + if ( m_showWellPathAttributes || m_showWellPathCompletions ) + { + for ( const std::unique_ptr& plotObject : m_wellPathAttributePlotObjects ) + { + double minObjectDepth = HUGE_VAL; + double maxObjectDepth = -HUGE_VAL; + if ( plotObject->yValueRange( &minObjectDepth, &maxObjectDepth ) ) + { + if ( minObjectDepth < minDepth ) + { + minDepth = minObjectDepth; + } + + if ( maxObjectDepth > maxDepth ) + { + maxDepth = maxObjectDepth; + } + } + } + } + + m_visibleYRangeMin = minDepth; + m_visibleYRangeMax = maxDepth; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateXZoom() +{ + if ( !m_plotWidget ) return; + + if ( m_isAutoScaleXEnabled ) + { + calculateXZoomRange(); + } + + updateXAxisAndGridTickIntervals(); + + // Attribute range. Fixed range where well components are positioned [-1, 1]. + // Set an extended range here to allow for some label space. + double componentRangeMax = 1.5 * ( 10.0 / ( m_widthScaleFactor() ) ); + double componentRangeMin = -0.25; + if ( m_showWellPathComponentsBothSides ) + { + componentRangeMin = -1.5; + } + + m_plotWidget->setXRange( componentRangeMin, componentRangeMax, QwtPlot::xBottom ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateYZoom() +{ + if ( !m_plotWidget ) return; + + m_plotWidget->setYRange( m_visibleYRangeMin(), m_visibleYRangeMax() ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -312,60 +500,62 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, { if ( changedField == &m_show ) { - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { - m_wellLogTrackPlotWidget->setVisible( m_show() ); + m_plotWidget->setVisible( m_show() ); } - updateParentPlotLayout(); + updatePlotWindowLayout(); + } + else if ( changedField == &m_description ) + { + updatePlotWindowLayout(); } else if ( changedField == &m_widthScaleFactor ) { - updateParentPlotLayout(); - updateAxisAndGridTickIntervals(); - applyXZoomFromVisibleRange(); + onWidthScaleFactorChange(); + updatePlotWindowLayout(); } else if ( changedField == &m_explicitTickIntervals ) { - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { - m_majorTickInterval = m_wellLogTrackPlotWidget->getCurrentMajorTickInterval(); - m_minorTickInterval = m_wellLogTrackPlotWidget->getCurrentMinorTickInterval(); + m_majorTickInterval = m_plotWidget->getCurrentMajorTickInterval(); + m_minorTickInterval = m_plotWidget->getCurrentMinorTickInterval(); } m_majorTickInterval.uiCapability()->setUiHidden( !m_explicitTickIntervals() ); m_minorTickInterval.uiCapability()->setUiHidden( !m_explicitTickIntervals() ); if ( !m_explicitTickIntervals() ) { - updateAxisAndGridTickIntervals(); + updateXAxisAndGridTickIntervals(); } } else if ( changedField == &m_xAxisGridVisibility || changedField == &m_majorTickInterval || changedField == &m_minorTickInterval ) { - updateAxisAndGridTickIntervals(); + updateXAxisAndGridTickIntervals(); } else if ( changedField == &m_visibleXRangeMin || changedField == &m_visibleXRangeMax ) { - m_wellLogTrackPlotWidget->setXRange( m_visibleXRangeMin, m_visibleXRangeMax ); - m_wellLogTrackPlotWidget->replot(); - m_isAutoScaleXEnabled = false; - bool emptyRange = std::abs( m_visibleXRangeMax() - m_visibleXRangeMin ) < + bool emptyRange = std::abs( m_visibleXRangeMax() - m_visibleXRangeMin ) < 1.0e-6 * std::max( 1.0, std::max( m_visibleXRangeMax(), m_visibleXRangeMin() ) ); m_explicitTickIntervals.uiCapability()->setUiReadOnly( emptyRange ); m_xAxisGridVisibility.uiCapability()->setUiReadOnly( emptyRange ); + m_isAutoScaleXEnabled = false; + + updateXZoom(); + m_plotWidget->scheduleReplot(); + updateEditors(); - updateParentPlotLayout(); - updateAxisAndGridTickIntervals(); } else if ( changedField == &m_isAutoScaleXEnabled ) { if ( m_isAutoScaleXEnabled() ) { - this->calculateXZoomRangeAndUpdateQwt(); - computeAndSetXRangeMinForLogarithmicScale(); - - if ( m_wellLogTrackPlotWidget ) m_wellLogTrackPlotWidget->replot(); + calculateXZoomRange(); + updateXZoom(); + m_plotWidget->scheduleReplot(); } } else if ( changedField == &m_isLogarithmicScaleEnabled ) @@ -377,12 +567,9 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, } m_explicitTickIntervals.uiCapability()->setUiHidden( m_isLogarithmicScaleEnabled() ); - this->calculateXZoomRangeAndUpdateQwt(); - computeAndSetXRangeMinForLogarithmicScale(); - - m_wellLogTrackPlotWidget->setXRange( m_visibleXRangeMin, m_visibleXRangeMax ); - - m_wellLogTrackPlotWidget->replot(); + calculateXZoomRange(); + updateXZoom(); + m_plotWidget->scheduleReplot(); } else if ( changedField == &m_regionAnnotationType || changedField == &m_regionAnnotationDisplay || changedField == &m_formationSource || changedField == &m_colorShadingTransparency || @@ -402,26 +589,10 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, } } - loadDataAndUpdate( true ); - - RimWellRftPlot* rftPlot( nullptr ); - - firstAncestorOrThisOfType( rftPlot ); - - if ( rftPlot ) - { - rftPlot->updateConnectedEditors(); - } - else - { - RimWellPltPlot* pltPlot( nullptr ); - firstAncestorOrThisOfType( pltPlot ); - - if ( pltPlot ) - { - pltPlot->updateConnectedEditors(); - } - } + loadDataAndUpdate(); + updatePlotWindowLayout(); + updateConnectedEditors(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_showRegionLabels ) { @@ -437,15 +608,21 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, m_formationSimWellName = QString( "None" ); } - loadDataAndUpdate( true ); + loadDataAndUpdate(); + updatePlotWindowLayout(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_formationWellPathForSourceCase ) { - loadDataAndUpdate( true ); + loadDataAndUpdate(); + updatePlotWindowLayout(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_formationSimWellName ) { - loadDataAndUpdate( true ); + loadDataAndUpdate(); + updatePlotWindowLayout(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_formationTrajectoryType ) { @@ -462,7 +639,9 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, } } - loadDataAndUpdate( true ); + loadDataAndUpdate(); + updatePlotWindowLayout(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_formationBranchIndex || changedField == &m_formationBranchDetection ) { @@ -470,11 +649,15 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, m_formationBranchIndex, m_formationBranchDetection ); - loadDataAndUpdate( true ); + loadDataAndUpdate(); + updatePlotWindowLayout(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_formationWellPathForSourceWellPath ) { - loadDataAndUpdate( true ); + loadDataAndUpdate(); + updatePlotWindowLayout(); + RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_formationLevel ) { @@ -489,14 +672,14 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, changedField == &m_wellPathAttributesInLegend || changedField == &m_wellPathCompletionsInLegend ) { updateWellPathAttributesOnPlot(); - updateParentPlotLayout(); + updatePlotWindowLayout(); RiuPlotMainWindowTools::refreshToolbars(); } else if ( changedField == &m_wellPathComponentSource ) { updateWellPathAttributesCollection(); updateWellPathAttributesOnPlot(); - updateParentPlotLayout(); + updatePlotWindowLayout(); RiuPlotMainWindowTools::refreshToolbars(); } } @@ -504,89 +687,76 @@ void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::updateParentPlotLayout() +void RimWellLogTrack::updateXAxisAndGridTickIntervals() { - RimWellLogPlot* wellLogPlot; - this->firstAncestorOrThisOfType( wellLogPlot ); - if ( wellLogPlot ) - { - RiuWellLogPlot* wellLogPlotViewer = dynamic_cast( wellLogPlot->viewWidget() ); - if ( wellLogPlotViewer ) - { - wellLogPlotViewer->updateChildrenLayout(); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::updateAxisAndGridTickIntervals() -{ - if ( !m_wellLogTrackPlotWidget ) return; + if ( !m_plotWidget ) return; if ( m_explicitTickIntervals ) { - m_wellLogTrackPlotWidget->setMajorAndMinorTickIntervals( m_majorTickInterval(), m_minorTickInterval() ); + m_plotWidget->setMajorAndMinorTickIntervals( m_majorTickInterval(), + m_minorTickInterval(), + m_visibleXRangeMin(), + m_visibleXRangeMax() ); } else { - int xMajorTickIntervals = 3; - int xMinorTickIntervals = 0; + int majorTickIntervals = 3; + int minorTickIntervals = 0; switch ( m_widthScaleFactor() ) { - case EXTRA_NARROW_TRACK: - xMajorTickIntervals = 3; - xMinorTickIntervals = 2; + case EXTRA_NARROW: + majorTickIntervals = 3; + minorTickIntervals = 2; break; - case NARROW_TRACK: - xMajorTickIntervals = 3; - xMinorTickIntervals = 5; + case NARROW: + majorTickIntervals = 3; + minorTickIntervals = 5; break; - case NORMAL_TRACK: - xMajorTickIntervals = 5; - xMinorTickIntervals = 5; + case NORMAL: + majorTickIntervals = 5; + minorTickIntervals = 5; break; - case WIDE_TRACK: - xMajorTickIntervals = 5; - xMinorTickIntervals = 10; + case WIDE: + majorTickIntervals = 5; + minorTickIntervals = 10; break; - case EXTRA_WIDE_TRACK: - xMajorTickIntervals = 10; - xMinorTickIntervals = 10; + case EXTRA_WIDE: + majorTickIntervals = 10; + minorTickIntervals = 10; break; } - m_wellLogTrackPlotWidget->setAutoTickIntervalCounts( xMajorTickIntervals, xMinorTickIntervals ); + m_plotWidget->setAutoTickIntervalCounts( majorTickIntervals, minorTickIntervals ); + m_plotWidget->setXRange( m_visibleXRangeMin, m_visibleXRangeMax ); } switch ( m_xAxisGridVisibility() ) { case RimWellLogPlot::AXIS_GRID_NONE: - m_wellLogTrackPlotWidget->enableXGridLines( false, false ); + m_plotWidget->enableXGridLines( false, false ); break; case RimWellLogPlot::AXIS_GRID_MAJOR: - m_wellLogTrackPlotWidget->enableXGridLines( true, false ); + m_plotWidget->enableXGridLines( true, false ); break; case RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR: - m_wellLogTrackPlotWidget->enableXGridLines( true, true ); + m_plotWidget->enableXGridLines( true, true ); + break; + } + RimWellLogPlot* plot = nullptr; + this->firstAncestorOrThisOfTypeAsserted( plot ); + switch ( plot->depthAxisGridLinesEnabled() ) + { + case RimWellLogPlot::AXIS_GRID_NONE: + m_plotWidget->enableYGridLines( false, false ); + break; + case RimWellLogPlot::AXIS_GRID_MAJOR: + m_plotWidget->enableYGridLines( true, false ); + break; + case RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR: + m_plotWidget->enableYGridLines( true, true ); break; } - RimWellLogPlot* plot = nullptr; - this->firstAncestorOrThisOfTypeAsserted( plot ); - switch ( plot->depthGridLinesVisibility() ) - { - case RimWellLogPlot::AXIS_GRID_NONE: - m_wellLogTrackPlotWidget->enableDepthGridLines( false, false ); - break; - case RimWellLogPlot::AXIS_GRID_MAJOR: - m_wellLogTrackPlotWidget->enableDepthGridLines( true, false ); - break; - case RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR: - m_wellLogTrackPlotWidget->enableDepthGridLines( true, true ); - break; - } - m_wellLogTrackPlotWidget->replot(); + m_plotWidget->scheduleReplot(); } //-------------------------------------------------------------------------------------------------- @@ -595,9 +765,161 @@ void RimWellLogTrack::updateAxisAndGridTickIntervals() void RimWellLogTrack::updateAllLegendItems() { reattachAllCurves(); - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { - m_wellLogTrackPlotWidget->updateLegend(); + m_plotWidget->updateLegend(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellLogTrack::asciiDataForPlotExport() const +{ + QString out = "\n" + this->description() + "\n"; + + std::vector curveNames; + std::vector curveDepths; + std::vector> curvesPlotXValues; + + auto depthType = parentWellLogPlot()->depthType(); + auto depthUnit = parentWellLogPlot()->depthUnit(); + + for ( RimWellLogCurve* curve : m_curves() ) + { + if ( !curve->isCurveVisible() ) continue; + + const RigWellLogCurveData* curveData = curve->curveData(); + if ( !curveData ) continue; + curveNames.push_back( curve->curveName() ); + + if ( curveNames.size() == 1 ) + { + if ( depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH ) + { + curveDepths = curveData->trueDepthPlotValues( depthUnit ); + } + else + { + curveDepths = curveData->measuredDepthPlotValues( depthUnit ); + } + } + + std::vector xPlotValues = curveData->xPlotValues(); + if ( curveDepths.size() != xPlotValues.size() || xPlotValues.empty() ) + { + curveNames.pop_back(); + + if ( curveNames.empty() ) + { + curveDepths.clear(); + } + continue; + } + curvesPlotXValues.push_back( xPlotValues ); + } + + for ( size_t i = 0; i < curveDepths.size(); ++i ) + { + if ( i == 0 ) + { + if ( depthType == RimWellLogPlot::CONNECTION_NUMBER ) + out += "Connection"; + else if ( depthType == RimWellLogPlot::MEASURED_DEPTH ) + out += "MD "; + else if ( depthType == RimWellLogPlot::PSEUDO_LENGTH ) + out += "PL "; + else if ( depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH ) + out += "TVD "; + for ( QString name : curveNames ) + out += " \t" + name; + out += "\n"; + } + else if ( curveDepths[i] == curveDepths[i - 1] ) + { + continue; + } + + out += QString::number( curveDepths[i], 'f', 3 ); + for ( std::vector plotVector : curvesPlotXValues ) + { + out += " \t" + QString::number( plotVector[i], 'g' ); + } + out += "\n"; + } + return out; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellLogTrack::hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const +{ + if ( fontSettingType == RiaDefines::PLOT_FONT && m_plotWidget ) + { + return defaultFontSize != m_plotWidget->fontSize(); + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellLogTrack::applyFontSize( RiaDefines::FontSettingType fontSettingType, + int oldFontSize, + int fontSize, + bool forceChange /*= false*/ ) +{ + if ( fontSettingType == RiaDefines::PLOT_FONT && m_plotWidget ) + { + if ( oldFontSize == m_plotWidget->fontSize() || forceChange ) + { + m_plotWidget->setFontSize( fontSize ); + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateZoomFromQwt() +{ + QwtInterval xInterval = m_plotWidget->axisRange( QwtPlot::xTop ); + QwtInterval depthInterval = m_plotWidget->axisRange( QwtPlot::yLeft ); + + m_visibleXRangeMin = xInterval.minValue(); + m_visibleXRangeMax = xInterval.maxValue(); + m_visibleYRangeMin = depthInterval.minValue(); + m_visibleYRangeMax = depthInterval.maxValue(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updatePlotWindowLayout() +{ + RimGridPlotWindow* plotWindow; + this->firstAncestorOrThisOfType( plotWindow ); + if ( plotWindow ) + { + plotWindow->updateLayout(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::onAxisSelected( int axis, bool toggle ) +{ + if ( toggle ) + { + RiuPlotMainWindowTools::toggleItemInSelection( this ); + } + else + { + RiuPlotMainWindowTools::selectAsCurrentItem( this ); } } @@ -705,32 +1027,16 @@ QList RimWellLogTrack::calculateValueOptions( const caf: return options; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimWellLogTrack::objectToggleField() -{ - return &m_show; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimWellLogTrack::userDescriptionField() -{ - return &m_userName; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::addCurve( RimWellLogCurve* curve ) { - curves.push_back( curve ); + m_curves.push_back( curve ); - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { - curve->setParentQwtPlotAndReplot( m_wellLogTrackPlotWidget ); + curve->setParentQwtPlotAndReplot( m_plotWidget ); } } @@ -739,12 +1045,12 @@ void RimWellLogTrack::addCurve( RimWellLogCurve* curve ) //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::insertCurve( RimWellLogCurve* curve, size_t index ) { - curves.insert( index, curve ); + m_curves.insert( index, curve ); // Todo: Mark curve data to use either TVD or MD - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { - curve->setParentQwtPlotAndReplot( m_wellLogTrackPlotWidget ); + curve->setParentQwtPlotAndReplot( m_plotWidget ); } } @@ -753,11 +1059,11 @@ void RimWellLogTrack::insertCurve( RimWellLogCurve* curve, size_t index ) //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::takeOutCurve( RimWellLogCurve* curve ) { - size_t index = curves.index( curve ); - if ( index < curves.size() ) + size_t index = m_curves.index( curve ); + if ( index < m_curves.size() ) { - curves[index]->detachQwtCurve(); - curves.removeChildObject( curve ); + m_curves[index]->detachQwtCurve(); + m_curves.removeChildObject( curve ); } } @@ -766,15 +1072,25 @@ void RimWellLogTrack::takeOutCurve( RimWellLogCurve* curve ) //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::deleteAllCurves() { - curves.deleteAllChildObjects(); + m_curves.deleteAllChildObjects(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuWellLogTrack* RimWellLogTrack::viewer() +RiuQwtPlotWidget* RimWellLogTrack::viewer() { - return m_wellLogTrackPlotWidget; + return m_plotWidget; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::availableXAxisRange( double* minX, double* maxX ) +{ + calculateXZoomRange(); + *minX = m_visibleXRangeMin; + *maxX = m_visibleXRangeMax; } //-------------------------------------------------------------------------------------------------- @@ -782,69 +1098,28 @@ RiuWellLogTrack* RimWellLogTrack::viewer() //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::availableDepthRange( double* minimumDepth, double* maximumDepth ) { - double minDepth = HUGE_VAL; - double maxDepth = -HUGE_VAL; - - for ( RimPlotCurve* curve : curves ) - { - double minCurveDepth = HUGE_VAL; - double maxCurveDepth = -HUGE_VAL; - - if ( curve->isCurveVisible() && curve->yValueRangeInQwt( &minCurveDepth, &maxCurveDepth ) ) - { - if ( minCurveDepth < minDepth ) - { - minDepth = minCurveDepth; - } - - if ( maxCurveDepth > maxDepth ) - { - maxDepth = maxCurveDepth; - } - } - } - - if ( m_showWellPathAttributes || m_showWellPathCompletions ) - { - for ( const std::unique_ptr& plotObject : m_wellPathAttributePlotObjects ) - { - double minObjectDepth = HUGE_VAL; - double maxObjectDepth = -HUGE_VAL; - if ( plotObject->yValueRange( &minObjectDepth, &maxObjectDepth ) ) - { - if ( minObjectDepth < minDepth ) - { - minDepth = minObjectDepth; - } - - if ( maxObjectDepth > maxDepth ) - { - maxDepth = maxObjectDepth; - } - } - } - } - - *minimumDepth = minDepth; - *maximumDepth = maxDepth; + calculateYZoomRange(); + *minimumDepth = m_visibleYRangeMin; + *maximumDepth = m_visibleYRangeMax; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::loadDataAndUpdate( bool updateParentPlotAndToolbars ) +void RimWellLogTrack::loadDataAndUpdate() { RimWellLogPlot* wellLogPlot = nullptr; firstAncestorOrThisOfType( wellLogPlot ); - if ( wellLogPlot && m_wellLogTrackPlotWidget ) + if ( wellLogPlot && m_plotWidget ) { - m_wellLogTrackPlotWidget->setXTitle( m_xAxisTitle ); + m_plotWidget->setXTitle( m_xAxisTitle ); + m_plotWidget->setYTitle( wellLogPlot->depthAxisTitle() ); } - for ( size_t cIdx = 0; cIdx < curves.size(); ++cIdx ) + for ( size_t cIdx = 0; cIdx < m_curves.size(); ++cIdx ) { - curves[cIdx]->loadDataAndUpdate( false ); + m_curves[cIdx]->loadDataAndUpdate( false ); } if ( m_regionAnnotationType == RiuPlotAnnotationTool::FORMATION_ANNOTATIONS ) @@ -859,18 +1134,18 @@ void RimWellLogTrack::loadDataAndUpdate( bool updateParentPlotAndToolbars ) m_regionAnnotationDisplay.uiCapability()->setUiReadOnly( noAnnotations ); m_showRegionLabels.uiCapability()->setUiReadOnly( noAnnotations ); - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { this->updateWellPathAttributesCollection(); this->updateWellPathAttributesOnPlot(); - m_wellLogTrackPlotWidget->updateLegend(); + m_plotWidget->updateLegend(); this->updateAxisScaleEngine(); this->updateRegionAnnotationsOnPlot(); - this->applyXZoomFromVisibleRange(); + this->updateXZoom(); } - this->updateAxisAndGridTickIntervals(); + this->updateXAxisAndGridTickIntervals(); m_majorTickInterval.uiCapability()->setUiHidden( !m_explicitTickIntervals() ); m_minorTickInterval.uiCapability()->setUiHidden( !m_explicitTickIntervals() ); @@ -880,12 +1155,6 @@ void RimWellLogTrack::loadDataAndUpdate( bool updateParentPlotAndToolbars ) m_xAxisGridVisibility.uiCapability()->setUiReadOnly( emptyRange ); updateAllLegendItems(); - - if ( updateParentPlotAndToolbars ) - { - updateParentPlotLayout(); - RiuPlotMainWindowTools::refreshToolbars(); - } } //-------------------------------------------------------------------------------------------------- @@ -947,6 +1216,11 @@ void RimWellLogTrack::setAutoScaleXEnabled( bool enabled ) m_isAutoScaleXEnabled = enabled; } +//-------------------------------------------------------------------------------------------------- +/// Empty implementation as Well Log Tracks always has depth set by Well Log Plot +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setAutoScaleYEnabled( bool enabled ) {} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -958,28 +1232,12 @@ void RimWellLogTrack::setXAxisTitle( const QString& text ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellLogTrack::depthPlotTitle() const +QString RimWellLogTrack::yAxisTitle() const { RimWellLogPlot* parent; this->firstAncestorOrThisOfTypeAsserted( parent ); - return parent->depthPlotTitle(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RimWellLogTrack::widthScaleFactor() const -{ - return static_cast( m_widthScaleFactor() ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::setWidthScaleFactor( WidthScaleFactor scaleFactor ) -{ - m_widthScaleFactor = scaleFactor; + return parent->depthAxisTitle(); } //-------------------------------------------------------------------------------------------------- @@ -1081,19 +1339,21 @@ RimWellLogTrack::TrajectoryType RimWellLogTrack::formationTrajectoryType() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::recreateViewer() +void RimWellLogTrack::createPlotWidget() { - if ( m_wellLogTrackPlotWidget == nullptr ) + if ( m_plotWidget == nullptr ) { - m_wellLogTrackPlotWidget = new RiuWellLogTrack( this ); + m_plotWidget = new RiuWellLogTrack( this ); + m_plotWidget->setAxisInverted( QwtPlot::yLeft ); + updateAxisScaleEngine(); - for ( size_t cIdx = 0; cIdx < curves.size(); ++cIdx ) + for ( size_t cIdx = 0; cIdx < m_curves.size(); ++cIdx ) { - curves[cIdx]->setParentQwtPlotNoReplot( this->m_wellLogTrackPlotWidget ); + m_curves[cIdx]->setParentQwtPlotNoReplot( this->m_plotWidget ); } - this->m_wellLogTrackPlotWidget->replot(); + m_plotWidget->scheduleReplot(); } } @@ -1102,7 +1362,7 @@ void RimWellLogTrack::recreateViewer() //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::detachAllCurves() { - for ( RimPlotCurve* curve : curves ) + for ( RimPlotCurve* curve : m_curves ) { curve->detachQwtCurve(); } @@ -1117,7 +1377,7 @@ void RimWellLogTrack::detachAllCurves() //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::reattachAllCurves() { - for ( RimPlotCurve* curve : curves ) + for ( RimPlotCurve* curve : m_curves ) { curve->reattachQwtCurve(); } @@ -1132,120 +1392,17 @@ void RimWellLogTrack::reattachAllCurves() //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::updateParentPlotZoom() { - if ( m_wellLogTrackPlotWidget ) + if ( m_plotWidget ) { RimWellLogPlot* wellLogPlot; firstAncestorOrThisOfType( wellLogPlot ); if ( wellLogPlot ) { - wellLogPlot->updateDepthZoom(); + wellLogPlot->updateZoom(); } } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::calculateXZoomRangeAndUpdateQwt() -{ - this->calculateXZoomRange(); - this->applyXZoomFromVisibleRange(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::applyXZoomFromVisibleRange() -{ - if ( !m_wellLogTrackPlotWidget ) return; - - m_wellLogTrackPlotWidget->setXRange( m_visibleXRangeMin, m_visibleXRangeMax ); - - // Attribute range. Fixed range where well components are positioned [-1, 1]. - // Set an extended range here to allow for some label space. - double componentRangeMax = 1.5 * ( 10.0 / ( m_widthScaleFactor() ) ); - double componentRangeMin = -0.25; - if ( m_showWellPathComponentsBothSides ) - { - componentRangeMin = -1.5; - } - - m_wellLogTrackPlotWidget->setXRange( componentRangeMin, componentRangeMax, QwtPlot::xBottom ); - - m_wellLogTrackPlotWidget->replot(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::calculateXZoomRange() -{ - std::map> stackCurveGroups = visibleStackedCurves(); - for ( const std::pair>& curveGroup : stackCurveGroups ) - { - for ( RimWellFlowRateCurve* stCurve : curveGroup.second ) - stCurve->updateStackedPlotData(); - } - - if ( !m_isAutoScaleXEnabled() ) - { - return; - } - - double minValue = HUGE_VAL; - double maxValue = -HUGE_VAL; - - size_t visibleCurves = 0u; - for ( auto curve : curves ) - { - double minCurveValue = HUGE_VAL; - double maxCurveValue = -HUGE_VAL; - - if ( curve->isCurveVisible() ) - { - visibleCurves++; - if ( curve->xValueRangeInData( &minCurveValue, &maxCurveValue ) ) - { - if ( minCurveValue < minValue ) - { - minValue = minCurveValue; - } - - if ( maxCurveValue > maxValue ) - { - maxValue = maxCurveValue; - } - } - } - } - - if ( minValue == HUGE_VAL ) - { - if ( visibleCurves ) - { - minValue = RI_LOGPLOTTRACK_MINX_DEFAULT; - maxValue = RI_LOGPLOTTRACK_MAXX_DEFAULT; - } - else - { - // Empty axis when there are no curves - minValue = 0; - maxValue = 0; - } - } - - if ( m_minorTickInterval() != 0.0 ) - { - std::tie( minValue, maxValue ) = adjustXRange( minValue, maxValue, m_minorTickInterval() ); - } - - m_visibleXRangeMin = minValue; - m_visibleXRangeMax = maxValue; - - computeAndSetXRangeMinForLogarithmicScale(); - updateEditors(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1287,6 +1444,25 @@ void RimWellLogTrack::setVisibleXRange( double minValue, double maxValue ) m_visibleXRangeMax = maxValue; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::setVisibleYRange( double minValue, double maxValue ) +{ + m_visibleYRangeMin = minValue; + m_visibleYRangeMax = maxValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::updateZoomInQwt() +{ + updateXZoom(); + updateYZoom(); + m_plotWidget->scheduleReplot(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1389,13 +1565,13 @@ RimWellPath* RimWellLogTrack::wellPathAttributeSource() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve( const QwtPlotCurve* curve ) const +caf::PdmObject* RimWellLogTrack::findPdmObjectFromQwtCurve( const QwtPlotCurve* curve ) const { - for ( size_t idx = 0; idx < curves.size(); idx++ ) + for ( size_t idx = 0; idx < m_curves.size(); idx++ ) { - if ( curves[idx]->qwtPlotCurve() == curve ) + if ( m_curves[idx]->qwtPlotCurve() == curve ) { - return curves[idx]; + return m_curves[idx]; } } @@ -1407,7 +1583,9 @@ RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve( const QwtPlotCurve* //-------------------------------------------------------------------------------------------------- void RimWellLogTrack::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { - uiOrdering.add( &m_userName ); + uiOrdering.add( &m_description ); + uiOrdering.add( &m_widthScaleFactor ); + caf::PdmUiGroup* annotationGroup = uiOrdering.addNewGroup( "Regions/Annotations" ); annotationGroup->add( &m_regionAnnotationType ); @@ -1479,9 +1657,6 @@ void RimWellLogTrack::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering uiOrderingForXAxisSettings( uiOrdering ); - caf::PdmUiGroup* trackSettingsGroup = uiOrdering.addNewGroup( "Track Settings" ); - trackSettingsGroup->add( &m_widthScaleFactor ); - uiOrdering.skipRemainingFields( true ); } @@ -1515,28 +1690,28 @@ void RimWellLogTrack::defineEditorAttribute( const caf::PdmFieldHandle* field, } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimWellLogTrack::objectToggleField() +{ + return &m_show; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimWellLogTrack::userDescriptionField() +{ + return &m_description; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimWellLogTrack::curveIndex( RimWellLogCurve* curve ) { - return curves.index( curve ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellLogTrack::isVisible() -{ - return m_show; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellLogTrack::setVisible( bool visible ) -{ - m_show = visible; + return m_curves.index( curve ); } //-------------------------------------------------------------------------------------------------- @@ -1546,17 +1721,17 @@ void RimWellLogTrack::updateAxisScaleEngine() { if ( m_isLogarithmicScaleEnabled ) { - m_wellLogTrackPlotWidget->setAxisScaleEngine( QwtPlot::xTop, new QwtLogScaleEngine ); + m_plotWidget->setAxisScaleEngine( QwtPlot::xTop, new QwtLogScaleEngine ); // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work - m_wellLogTrackPlotWidget->setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine ); + m_plotWidget->setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine ); } else { - m_wellLogTrackPlotWidget->setAxisScaleEngine( QwtPlot::xTop, new RiuQwtLinearScaleEngine ); + m_plotWidget->setAxisScaleEngine( QwtPlot::xTop, new RiuQwtLinearScaleEngine ); // NB! Must assign scale engine to bottom in order to make QwtPlotGrid work - m_wellLogTrackPlotWidget->setAxisScaleEngine( QwtPlot::xBottom, new RiuQwtLinearScaleEngine ); + m_plotWidget->setAxisScaleEngine( QwtPlot::xBottom, new RiuQwtLinearScaleEngine ); } } @@ -1565,10 +1740,10 @@ void RimWellLogTrack::updateAxisScaleEngine() //-------------------------------------------------------------------------------------------------- bool RimWellLogTrack::isFirstVisibleTrackInPlot() const { - RimWellLogPlot* plot = nullptr; - firstAncestorOrThisOfTypeAsserted( plot ); - size_t ownIndex = plot->trackIndex( this ); - return plot->firstVisibleTrackIndex() == ownIndex; + RimGridPlotWindow* plotWindow = nullptr; + firstAncestorOrThisOfTypeAsserted( plotWindow ); + std::vector visiblePlots = plotWindow->visiblePlots(); + return visiblePlots.empty() ? false : visiblePlots.front() == this; } //-------------------------------------------------------------------------------------------------- @@ -1600,6 +1775,24 @@ void RimWellLogTrack::updateWellPathAttributesCollection() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogTrack::onWidthScaleFactorChange() +{ + updateXZoom(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogPlot* RimWellLogTrack::parentWellLogPlot() const +{ + RimWellLogPlot* wellLogPlot = nullptr; + this->firstAncestorOrThisOfTypeAsserted( wellLogPlot ); + return wellLogPlot; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1610,11 +1803,11 @@ void RimWellLogTrack::computeAndSetXRangeMinForLogarithmicScale() double pos = HUGE_VAL; double neg = -HUGE_VAL; - for ( size_t cIdx = 0; cIdx < curves.size(); cIdx++ ) + for ( size_t cIdx = 0; cIdx < m_curves.size(); cIdx++ ) { - if ( curves[cIdx]->isCurveVisible() && curves[cIdx]->curveData() ) + if ( m_curves[cIdx]->isCurveVisible() && m_curves[cIdx]->curveData() ) { - RigStatisticsCalculator::posNegClosestToZero( curves[cIdx]->curveData()->xPlotValues(), pos, neg ); + RigStatisticsCalculator::posNegClosestToZero( m_curves[cIdx]->curveData()->xPlotValues(), pos, neg ); } } @@ -1642,7 +1835,7 @@ void RimWellLogTrack::setLogarithmicScale( bool enable ) std::map> RimWellLogTrack::visibleStackedCurves() { std::map> stackedCurves; - for ( RimWellLogCurve* curve : curves ) + for ( RimWellLogCurve* curve : m_curves ) { if ( curve && curve->isCurveVisible() ) { @@ -1660,34 +1853,19 @@ std::map> RimWellLogTrack::visibleStacke //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellLogTrack::description() +std::vector RimWellLogTrack::curves() const { - return m_userName; + return m_curves.childObjects(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellLogTrack::curvesVector() +std::vector RimWellLogTrack::visibleCurves() const { std::vector curvesVector; - for ( RimWellLogCurve* curve : curves ) - { - curvesVector.push_back( curve ); - } - - return curvesVector; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimWellLogTrack::visibleCurvesVector() -{ - std::vector curvesVector; - - for ( RimWellLogCurve* curve : curves ) + for ( RimWellLogCurve* curve : m_curves.childObjects() ) { if ( curve->isCurveVisible() ) { @@ -2104,7 +2282,7 @@ void RimWellLogTrack::updateCurveDataRegionsOnPlot() caf::ColorTable colorTable( RimRegularLegendConfig::colorArrayFromColorType( m_colorShadingPalette() ) ); std::vector sourceNames = - {"", "PP=Grid", "PP=Las-File", "PP=Element Property Table", "", "PP=Hydrostatic"}; + { "", "PP=Grid", "PP=Las-File", "PP=Element Property Table", "", "PP=Hydrostatic" }; curveData.data = ppValues; std::vector sourceNamesToPlot; @@ -2128,12 +2306,12 @@ void RimWellLogTrack::updateCurveDataRegionsOnPlot() caf::ColorTable colorTable( RimRegularLegendConfig::colorArrayFromColorType( m_colorShadingPalette() ) ); std::vector sourceNames = - {"", - "", - "Poisson=Las-File", - "Poisson=Element Property Table", - QString( "Poisson=%1" ).arg( wellBoreStabilityPlot->userDefinedPoissonRatio() ), - ""}; + { "", + "", + "Poisson=Las-File", + "Poisson=Element Property Table", + QString( "Poisson=%1" ).arg( wellBoreStabilityPlot->userDefinedPoissonRatio() ), + "" }; curveData.data = poissonValues; std::vector sourceNamesToPlot; @@ -2156,12 +2334,12 @@ void RimWellLogTrack::updateCurveDataRegionsOnPlot() { caf::ColorTable colorTable( RimRegularLegendConfig::colorArrayFromColorType( m_colorShadingPalette() ) ); - std::vector sourceNames = {"", - "", - "UCS=Las-File", - "UCS=Element Property Table", - QString( "UCS=%1" ).arg( wellBoreStabilityPlot->userDefinedUcs() ), - ""}; + std::vector sourceNames = { "", + "", + "UCS=Las-File", + "UCS=Element Property Table", + QString( "UCS=%1" ).arg( wellBoreStabilityPlot->userDefinedUcs() ), + "" }; curveData.data = ucsValues; @@ -2231,16 +2409,16 @@ void RimWellLogTrack::updateWellPathAttributesOnPlot() } } - const std::map sortIndices = {{RiaDefines::WELL_PATH, 0}, - {RiaDefines::CASING, 1}, - {RiaDefines::LINER, 2}, - {RiaDefines::PERFORATION_INTERVAL, 3}, - {RiaDefines::FISHBONES, 4}, - {RiaDefines::FRACTURE, 5}, - {RiaDefines::PACKER, 6}, - {RiaDefines::ICD, 7}, - {RiaDefines::AICD, 8}, - {RiaDefines::ICV, 9}}; + const std::map sortIndices = { { RiaDefines::WELL_PATH, 0 }, + { RiaDefines::CASING, 1 }, + { RiaDefines::LINER, 2 }, + { RiaDefines::PERFORATION_INTERVAL, 3 }, + { RiaDefines::FISHBONES, 4 }, + { RiaDefines::FRACTURE, 5 }, + { RiaDefines::PACKER, 6 }, + { RiaDefines::ICD, 7 }, + { RiaDefines::AICD, 8 }, + { RiaDefines::ICV, 9 } }; std::stable_sort( allWellPathComponents.begin(), allWellPathComponents.end(), @@ -2271,10 +2449,10 @@ void RimWellLogTrack::updateWellPathAttributesOnPlot() attributePlotObject->setDepthType( depthType ); attributePlotObject->setShowLabel( m_showWellPathComponentLabels() ); attributePlotObject->loadDataAndUpdate( false ); - attributePlotObject->setParentQwtPlotNoReplot( m_wellLogTrackPlotWidget ); + attributePlotObject->setParentQwtPlotNoReplot( m_plotWidget ); } } - applyXZoomFromVisibleRange(); + updateXZoom(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellLogTrack.h b/ApplicationCode/ProjectDataModel/RimWellLogTrack.h index efc9b12f96..b9a6bbdd6f 100644 --- a/ApplicationCode/ProjectDataModel/RimWellLogTrack.h +++ b/ApplicationCode/ProjectDataModel/RimWellLogTrack.h @@ -24,6 +24,7 @@ #include "RigWellPathFormations.h" #include "RiuPlotAnnotationTool.h" +#include "RimPlotInterface.h" #include "RimRegularLegendConfig.h" #include "cafPdmChildArrayField.h" @@ -31,6 +32,8 @@ #include "cafPdmObject.h" #include "cafPdmPtrField.h" +#include "qwt_plot.h" + #include #include @@ -64,7 +67,7 @@ struct CurveSamplingPointData /// /// //================================================================================================== -class RimWellLogTrack : public caf::PdmObject +class RimWellLogTrack : public caf::PdmObject, public RimPlotInterface { CAF_PDM_HEADER_INIT; @@ -82,21 +85,17 @@ public: CASE, WELL_PICK_FILTER }; - enum WidthScaleFactor - { - EXTRA_NARROW_TRACK = 3, - NARROW_TRACK = 4, - NORMAL_TRACK = 5, - WIDE_TRACK = 7, - EXTRA_WIDE_TRACK = 10 - }; typedef caf::AppEnum RegionAnnotationTypeEnum; typedef caf::AppEnum RegionAnnotationDisplayEnum; - void setDescription( const QString& description ); - bool isVisible(); - void setVisible( bool visible ); + bool isChecked() const override; + void setChecked( bool checked ); + const QString description() const; + void setDescription( const QString& description ); + int widthScaleFactor() const override; + void setWidthScaleFactor( WidthScaleFactor scaleFactor ) override; + void addCurve( RimWellLogCurve* curve ); void insertCurve( RimWellLogCurve* curve, size_t index ); void takeOutCurve( RimWellLogCurve* curve ); @@ -105,13 +104,11 @@ public: size_t curveIndex( RimWellLogCurve* curve ); size_t curveCount() { - return curves.size(); + return m_curves.size(); } void setXAxisTitle( const QString& text ); - QString depthPlotTitle() const; - int widthScaleFactor() const; - void setWidthScaleFactor( WidthScaleFactor scaleFactor ); + QString yAxisTitle() const; void setFormationWellPath( RimWellPath* wellPath ); RimWellPath* formationWellPath() const; @@ -126,11 +123,11 @@ public: void setFormationTrajectoryType( TrajectoryType trajectoryType ); TrajectoryType formationTrajectoryType() const; - void recreateViewer(); + void createPlotWidget(); void detachAllCurves(); void reattachAllCurves(); - void loadDataAndUpdate( bool updateParentPlotAndToolbars = false ); + void loadDataAndUpdate() override; void setAndUpdateWellPathFormationNamesData( RimCase* rimCase, RimWellPath* wellPath ); @@ -140,14 +137,22 @@ public: bool useBranchDetection ); void setAndUpdateSimWellFormationNamesData( RimCase* rimCase, const QString& simWellName ); - void setAutoScaleXEnabled( bool enabled ); + void setAutoScaleXEnabled( bool enabled ) override; + void setAutoScaleYEnabled( bool enabled ) override; + + void availableXAxisRange( double* minX, double* maxX ); void availableDepthRange( double* minimumDepth, double* maximumDepth ); - void updateParentPlotZoom(); - void calculateXZoomRangeAndUpdateQwt(); - void applyXZoomFromVisibleRange(); - void calculateXZoomRange(); - void updateEditors(); + void setVisibleXRange( double minValue, double maxValue ); + void setVisibleYRange( double minValue, double maxValue ); + + void updateZoomInQwt() override; + void updateZoomFromQwt() override; + + void updateParentPlotZoom(); + + void updateEditors(); + void setTickIntervals( double majorTickInterval, double minorTickInterval ); void setXAxisGridVisibility( RimWellLogPlot::AxisGridVisibility gridLines ); @@ -165,42 +170,60 @@ public: void setShowWellPathAttributes( bool on ); void setWellPathAttributesSource( RimWellPath* wellPath ); - RimWellPath* wellPathAttributeSource() const; - RiuWellLogTrack* viewer(); + RimWellPath* wellPathAttributeSource() const; + RiuQwtPlotWidget* viewer() override; - RimWellLogCurve* curveDefinitionFromCurve( const QwtPlotCurve* curve ) const; + caf::PdmObject* findPdmObjectFromQwtCurve( const QwtPlotCurve* curve ) const override; void setLogarithmicScale( bool enable ); std::map> visibleStackedCurves(); - QString description(); - std::vector curvesVector(); - std::vector visibleCurvesVector(); + std::vector curves() const; + std::vector visibleCurves() const; void uiOrderingForRftPltFormations( caf::PdmUiOrdering& uiOrdering ); void uiOrderingForXAxisSettings( caf::PdmUiOrdering& uiOrdering ); void setFormationsForCaseWithSimWellOnly( bool caseWithSimWellOnly ); - void updateAxisAndGridTickIntervals(); + void updateXAxisAndGridTickIntervals(); void updateAllLegendItems(); + QString asciiDataForPlotExport() const; + + bool hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const override; + bool applyFontSize( RiaDefines::FontSettingType fontSettingType, + int oldFontSize, + int fontSize, + bool forceChange = false ) override; + + void updatePlotWindowLayout() override; + + void onAxisSelected( int axis, bool toggle ) override; + private: - void fieldChangedByUi( const caf::PdmFieldHandle* changedField, - const QVariant& oldValue, - const QVariant& newValue ) override; - void updateParentPlotLayout(); + void calculateXZoomRange(); + void calculateYZoomRange(); + + void updateXZoom(); + void updateYZoom(); + + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void initAfterRead() override; + void defineEditorAttribute( const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute ) override; + caf::PdmFieldHandle* objectToggleField() override; caf::PdmFieldHandle* userDescriptionField() override; - void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; - void initAfterRead() override; - void defineEditorAttribute( const caf::PdmFieldHandle* field, - QString uiConfigName, - caf::PdmUiEditorAttribute* attribute ) override; void computeAndSetXRangeMinForLogarithmicScale(); @@ -239,14 +262,23 @@ private: void updateWellPathAttributesCollection(); + void onWidthScaleFactorChange() override; + + RimWellLogPlot* parentWellLogPlot() const; + private: QString m_xAxisTitle; - caf::PdmField m_show; - caf::PdmField m_userName; - caf::PdmChildArrayField curves; - caf::PdmField m_visibleXRangeMin; - caf::PdmField m_visibleXRangeMax; + caf::PdmField m_show; + caf::PdmField m_description; + caf::PdmField m_widthScaleFactor; + + caf::PdmChildArrayField m_curves; + caf::PdmField m_visibleXRangeMin; + caf::PdmField m_visibleXRangeMax; + caf::PdmField m_visibleYRangeMin; + caf::PdmField m_visibleYRangeMax; + caf::PdmField m_isAutoScaleXEnabled; caf::PdmField m_isLogarithmicScaleEnabled; caf::PdmField m_xAxisGridVisibility; @@ -268,7 +300,6 @@ private: caf::PdmField m_formationBranchIndex; caf::PdmField> m_formationLevel; caf::PdmField m_showformationFluids; - caf::PdmField> m_widthScaleFactor; caf::PdmField m_formationBranchDetection; caf::PdmField m_showWellPathAttributes; caf::PdmField m_showWellPathCompletions; @@ -285,7 +316,6 @@ private: bool m_formationsForCaseWithSimWellOnly; - QPointer m_wellLogTrackPlotWidget; - + QPointer m_plotWidget; std::unique_ptr m_annotationTool; }; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index d663f940c9..db10040f17 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -186,10 +186,10 @@ RimEnsembleCurveSet::~RimEnsembleCurveSet() RimSummaryPlot* parentPlot; firstAncestorOrThisOfType( parentPlot ); - if ( parentPlot && parentPlot->qwtPlot() ) + if ( parentPlot && parentPlot->viewer() ) { m_qwtPlotCurveForLegendText->detach(); - parentPlot->qwtPlot()->removeEnsembleCurveSetLegend( this ); + parentPlot->removeEnsembleCurveSetLegend( this ); } delete m_qwtPlotCurveForLegendText; @@ -272,7 +272,7 @@ void RimEnsembleCurveSet::reattachQwtCurves() firstAncestorOrThisOfType( plot ); if ( plot ) { - m_qwtPlotCurveForLegendText->attach( plot->qwtPlot() ); + m_qwtPlotCurveForLegendText->attach( plot->viewer() ); } } @@ -285,7 +285,7 @@ void RimEnsembleCurveSet::addCurve( RimSummaryCurve* curve ) { RimSummaryPlot* plot; firstAncestorOrThisOfType( plot ); - if ( plot ) curve->setParentQwtPlotNoReplot( plot->qwtPlot() ); + if ( plot ) curve->setParentQwtPlotNoReplot( plot->viewer() ); curve->setColor( m_color ); m_curves.push_back( curve ); @@ -635,7 +635,7 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector Y" ); curveDataGroup->add( &m_yValuesSummaryCaseCollection ); curveDataGroup->add( &m_yValuesSummaryAddressUiField ); - curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, {false, 1, 0} ); + curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { false, 1, 0 } ); curveDataGroup->add( &m_plotAxis ); } @@ -946,18 +946,18 @@ void RimEnsembleCurveSet::updateCurveColors() RimSummaryPlot* plot; firstAncestorOrThisOfType( plot ); - if ( plot && plot->qwtPlot() ) + if ( plot && plot->viewer() ) { if ( m_yValuesSummaryCaseCollection() && isCurvesVisible() && m_colorMode == BY_ENSEMBLE_PARAM && m_legendConfig->showLegend() ) { - plot->qwtPlot()->addOrUpdateEnsembleCurveSetLegend( this ); + plot->addOrUpdateEnsembleCurveSetLegend( this ); } else { - plot->qwtPlot()->removeEnsembleCurveSetLegend( this ); + plot->removeEnsembleCurveSetLegend( this ); } - plot->qwtPlot()->replot(); + plot->viewer()->scheduleReplot(); } } @@ -1011,13 +1011,13 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vectorqwtPlot() ) m_qwtPlotCurveForLegendText->attach( plot->qwtPlot() ); + if ( plot->viewer() ) m_qwtPlotCurveForLegendText->attach( plot->viewer() ); } - if ( plot->qwtPlot() ) + if ( plot->viewer() ) { - plot->qwtPlot()->updateLegend(); - plot->qwtPlot()->replot(); + plot->viewer()->updateLegend(); + plot->viewer()->scheduleReplot(); plot->updateAxes(); plot->updatePlotInfoLabel(); } @@ -1079,7 +1079,7 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vectorsetParentQwtPlotNoReplot( plot->qwtPlot() ); + curve->setParentQwtPlotNoReplot( plot->viewer() ); m_curves.push_back( curve ); curve->setColor( m_statistics->color() ); curve->setColor( m_statistics->color() ); @@ -1103,9 +1103,9 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vectorupdateQwtPlotAxis(); } - if ( plot->qwtPlot() ) + if ( plot->viewer() ) { - plot->qwtPlot()->updateLegend(); + plot->viewer()->updateLegend(); plot->updateAxes(); } } @@ -1163,7 +1163,7 @@ void RimEnsembleCurveSet::updateAllTextInPlot() RimSummaryPlot* summaryPlot = nullptr; this->firstAncestorOrThisOfTypeAsserted( summaryPlot ); - if ( summaryPlot->qwtPlot() ) + if ( summaryPlot->viewer() ) { summaryPlot->updatePlotTitle(); } diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index 978d177ec8..2d4c9b031e 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -637,10 +637,10 @@ void RimSummaryCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering QString curveDataGroupName = "Summary Vector"; if ( isCrossPlotCurve() ) curveDataGroupName += " Y"; caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroupWithKeyword( curveDataGroupName, "Summary Vector Y" ); - curveDataGroup->add( &m_yValuesSummaryCase, {true, 3, 1} ); - curveDataGroup->add( &m_yValuesSummaryAddressUiField, {true, 2, 1} ); - curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, {false, 1, 0} ); - curveDataGroup->add( &m_plotAxis, {true, 3, 1} ); + curveDataGroup->add( &m_yValuesSummaryCase, { true, 3, 1 } ); + curveDataGroup->add( &m_yValuesSummaryAddressUiField, { true, 2, 1 } ); + curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { false, 1, 0 } ); + curveDataGroup->add( &m_plotAxis, { true, 3, 1 } ); if ( isCrossPlotCurve() ) m_showErrorBars = false; @@ -651,9 +651,9 @@ void RimSummaryCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering if ( isCrossPlotCurve() ) { caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector X" ); - curveDataGroup->add( &m_xValuesSummaryCase, {true, 3, 1} ); - curveDataGroup->add( &m_xValuesSummaryAddressUiField, {true, 2, 1} ); - curveDataGroup->add( &m_xPushButtonSelectSummaryAddress, {false, 1, 0} ); + curveDataGroup->add( &m_xValuesSummaryCase, { true, 3, 1 } ); + curveDataGroup->add( &m_xValuesSummaryAddressUiField, { true, 2, 1 } ); + curveDataGroup->add( &m_xPushButtonSelectSummaryAddress, { false, 1, 0 } ); } caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup( "Appearance" ); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp index e3ea88a78e..5120e7f0a1 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp @@ -309,7 +309,7 @@ void RimSummaryCurveCollection::updateCaseNameHasChanged() firstAncestorOrThisOfTypeAsserted( parentPlot ); parentPlot->updatePlotTitle(); - if ( parentPlot->qwtPlot() ) parentPlot->qwtPlot()->updateLegend(); + if ( parentPlot->viewer() ) parentPlot->viewer()->updateLegend(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index af677dd272..bf4835a238 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -139,10 +139,12 @@ CurvesData concatCurvesData( const std::vector& curvesData ); /// //-------------------------------------------------------------------------------------------------- RimSummaryPlot::RimSummaryPlot() + : RimPlotWindow() { CAF_PDM_InitObject( "Summary Plot", ":/SummaryPlotLight16x16.png", "", "" ); - CAF_PDM_InitField( &m_userDefinedPlotTitle, "PlotDescription", QString( "Summary Plot" ), "Title", "", "", "" ); + m_description = "Summary Plot"; + CAF_PDM_InitField( &m_showPlotTitle, "ShowPlotTitle", true, "Plot Title", "", "", "" ); m_showPlotTitle.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); CAF_PDM_InitField( &m_showLegend, "ShowLegend", true, "Legend", "", "", "" ); @@ -238,8 +240,8 @@ RimSummaryPlot::~RimSummaryPlot() //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAxes() { - updateAxis( RiaDefines::PLOT_AXIS_LEFT ); - updateAxis( RiaDefines::PLOT_AXIS_RIGHT ); + updateYAxis( RiaDefines::PLOT_AXIS_LEFT ); + updateYAxis( RiaDefines::PLOT_AXIS_RIGHT ); if ( m_isCrossPlot ) { @@ -300,7 +302,15 @@ time_t RimSummaryPlot::firstTimeStepOfFirstCurve() //-------------------------------------------------------------------------------------------------- QWidget* RimSummaryPlot::viewWidget() { - return m_qwtPlot; + return m_plotWidget; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuQwtPlotWidget* RimSummaryPlot::viewer() +{ + return m_plotWidget; } //-------------------------------------------------------------------------------------------------- @@ -325,7 +335,7 @@ QString RimSummaryPlot::asciiDataForPlotExport( DateTimePeriod resamplingPeriod, populateTimeHistoryCurvesData( m_gridTimeHistoryCurves.childObjects(), &timeHistoryCurvesData ); // Export observed data - appendToExportData( out, {summaryCurvesObsData}, showTimeAsLongString ); + appendToExportData( out, { summaryCurvesObsData }, showTimeAsLongString ); std::vector exportData( 2 ); @@ -347,12 +357,105 @@ QString RimSummaryPlot::asciiDataForPlotExport( DateTimePeriod resamplingPeriod, CurvesData asciiCurvesData; populateAsciiDataCurvesData( m_asciiDataCurves.childObjects(), &asciiCurvesData ); - appendToExportData( out, {asciiCurvesData}, showTimeAsLongString ); + appendToExportData( out, { asciiCurvesData }, showTimeAsLongString ); } return out; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::createPlotWidget() +{ + createViewWidget( nullptr ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RimSummaryPlot::findPdmObjectFromQwtCurve( const QwtPlotCurve* qwtCurve ) const +{ + for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) + { + if ( curve->qwtPlotCurve() == qwtCurve ) + { + return curve; + } + } + + for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) + { + if ( curve->qwtPlotCurve() == qwtCurve ) + { + return curve; + } + } + + if ( m_summaryCurveCollection ) + { + RimSummaryCurve* foundCurve = m_summaryCurveCollection->findRimCurveFromQwtCurve( qwtCurve ); + + if ( foundCurve ) + { + m_summaryCurveCollection->setCurrentSummaryCurve( foundCurve ); + + return foundCurve; + } + } + + if ( m_ensembleCurveSetCollection ) + { + RimEnsembleCurveSet* foundCurveSet = m_ensembleCurveSetCollection->findRimCurveSetFromQwtCurve( qwtCurve ); + + if ( foundCurveSet ) + { + m_ensembleCurveSetCollection->setCurrentSummaryCurveSet( foundCurveSet ); + + return foundCurveSet; + } + } + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::onAxisSelected( int axis, bool toggle ) +{ + RiuPlotMainWindowTools::showPlotMainWindow(); + + caf::PdmObject* itemToSelect = nullptr; + if ( axis == QwtPlot::yLeft ) + { + itemToSelect = m_leftYAxisProperties; + } + else if ( axis == QwtPlot::yRight ) + { + itemToSelect = m_rightYAxisProperties; + } + else if ( axis == QwtPlot::xBottom ) + { + if ( m_isCrossPlot ) + { + itemToSelect = m_bottomAxisProperties; + } + else + { + itemToSelect = m_timeAxisProperties; + } + } + + if ( toggle ) + { + RiuPlotMainWindowTools::toggleItemInSelection( itemToSelect ); + } + else + { + RiuPlotMainWindowTools::selectAsCurrentItem( itemToSelect ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -408,14 +511,6 @@ RimSummaryCurveCollection* RimSummaryPlot::summaryCurveCollection() const return m_summaryCurveCollection(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuSummaryQwtPlot* RimSummaryPlot::qwtPlot() const -{ - return m_qwtPlot; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -433,7 +528,7 @@ void RimSummaryPlot::updatePlotTitle() if ( m_useAutoPlotTitle ) { - m_userDefinedPlotTitle = m_nameHelperAllCurves->plotTitle(); + m_description = m_nameHelperAllCurves->plotTitle(); } updateCurveNames(); @@ -486,10 +581,10 @@ void RimSummaryPlot::copyAxisPropertiesFromOther( const RimSummaryPlot& sourceSu //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAll() { - if ( qwtPlot() ) + if ( m_plotWidget ) { updatePlotTitle(); - qwtPlot()->updateLegend(); + m_plotWidget->updateLegend(); updateAxes(); updateZoomInQwt(); } @@ -501,9 +596,9 @@ void RimSummaryPlot::updateAll() void RimSummaryPlot::updateAllLegendItems() { reattachAllCurves(); - if ( qwtPlot() ) + if ( m_plotWidget ) { - qwtPlot()->updateLegend(); + m_plotWidget->updateLegend(); } } @@ -530,7 +625,7 @@ void RimSummaryPlot::setPlotInfoLabel( const QString& label ) void RimSummaryPlot::showPlotInfoLabel( bool show ) { if ( show ) - m_plotInfoLabel->attach( m_qwtPlot ); + m_plotInfoLabel->attach( m_plotWidget ); else m_plotInfoLabel->detach(); } @@ -614,20 +709,21 @@ void RimSummaryPlot::applyDefaultCurveAppearances() //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::hasCustomFontSizes( RiaDefines::FontSettingType fontSettingType, int defaultFontSize ) const { - if ( fontSettingType != RiaDefines::PLOT_FONT ) return false; - - for ( auto plotAxis : allPlotAxes() ) + if ( fontSettingType == RiaDefines::PLOT_FONT && m_plotWidget ) { - if ( plotAxis->titleFontSize() != defaultFontSize || plotAxis->valuesFontSize() != defaultFontSize ) + for ( auto plotAxis : allPlotAxes() ) + { + if ( plotAxis->titleFontSize() != defaultFontSize || plotAxis->valuesFontSize() != defaultFontSize ) + { + return true; + } + } + + if ( m_legendFontSize() != defaultFontSize ) { return true; } } - - if ( m_legendFontSize() != defaultFontSize ) - { - return true; - } return false; } @@ -639,31 +735,32 @@ bool RimSummaryPlot::applyFontSize( RiaDefines::FontSettingType fontSettingType, int fontSize, bool forceChange /*= false*/ ) { - if ( fontSettingType != RiaDefines::PLOT_FONT ) return false; - bool anyChange = false; - for ( auto plotAxis : allPlotAxes() ) + + if ( fontSettingType == RiaDefines::PLOT_FONT && m_plotWidget ) { - if ( forceChange || plotAxis->titleFontSize() == oldFontSize ) + for ( auto plotAxis : allPlotAxes() ) { - plotAxis->setTitleFontSize( fontSize ); - anyChange = true; + if ( forceChange || plotAxis->titleFontSize() == oldFontSize ) + { + plotAxis->setTitleFontSize( fontSize ); + anyChange = true; + } + if ( forceChange || plotAxis->valuesFontSize() == oldFontSize ) + { + plotAxis->setValuesFontSize( fontSize ); + anyChange = true; + } } - if ( forceChange || plotAxis->valuesFontSize() == oldFontSize ) + + if ( forceChange || m_legendFontSize() == oldFontSize ) { - plotAxis->setValuesFontSize( fontSize ); - anyChange = true; + m_legendFontSize = fontSize; + anyChange = true; } + + if ( anyChange ) loadDataAndUpdate(); } - - if ( forceChange || m_legendFontSize() == oldFontSize ) - { - m_legendFontSize = fontSize; - anyChange = true; - } - - if ( anyChange ) loadDataAndUpdate(); - return anyChange; } @@ -686,25 +783,9 @@ bool RimSummaryPlot::isNormalizationEnabled() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::updateAxisScaling() +void RimSummaryPlot::updateYAxis( RiaDefines::PlotAxis plotAxis ) { - loadDataAndUpdate(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::updateAxisDisplay() -{ - updateAxes(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::updateAxis( RiaDefines::PlotAxis plotAxis ) -{ - if ( !m_qwtPlot ) return; + if ( !m_plotWidget ) return; QwtPlot::Axis qwtAxis = QwtPlot::yLeft; if ( plotAxis == RiaDefines::PLOT_AXIS_LEFT ) @@ -719,7 +800,7 @@ void RimSummaryPlot::updateAxis( RiaDefines::PlotAxis plotAxis ) RimPlotAxisProperties* yAxisProperties = yAxisPropertiesLeftOrRight( plotAxis ); if ( yAxisProperties->isActive() && hasVisibleCurvesForAxis( plotAxis ) ) { - m_qwtPlot->enableAxis( qwtAxis, true ); + m_plotWidget->enableAxis( qwtAxis, true ); std::set timeHistoryQuantities; @@ -732,11 +813,11 @@ void RimSummaryPlot::updateAxis( RiaDefines::PlotAxis plotAxis ) visibleSummaryCurvesForAxis( plotAxis ), visibleAsciiDataCurvesForAxis( plotAxis ), timeHistoryQuantities ); - calc.applyYAxisPropertiesToPlot( m_qwtPlot ); + calc.applyYAxisPropertiesToPlot( m_plotWidget ); } else { - m_qwtPlot->enableAxis( qwtAxis, false ); + m_plotWidget->enableAxis( qwtAxis, false ); } } @@ -751,26 +832,26 @@ void RimSummaryPlot::updateZoomForAxis( RiaDefines::PlotAxis plotAxis ) { if ( m_bottomAxisProperties->isAutoZoom() ) { - m_qwtPlot->setAxisAutoScale( QwtPlot::xBottom, true ); + m_plotWidget->setAxisAutoScale( QwtPlot::xBottom, true ); } else { - m_qwtPlot->setAxisScale( QwtPlot::xBottom, - m_bottomAxisProperties->visibleRangeMin(), - m_bottomAxisProperties->visibleRangeMax() ); + m_plotWidget->setAxisScale( QwtPlot::xBottom, + m_bottomAxisProperties->visibleRangeMin(), + m_bottomAxisProperties->visibleRangeMax() ); } } else { if ( m_timeAxisProperties->isAutoZoom() ) { - m_qwtPlot->setAxisAutoScale( QwtPlot::xBottom, true ); + m_plotWidget->setAxisAutoScale( QwtPlot::xBottom, true ); } else { - m_qwtPlot->setAxisScale( QwtPlot::xBottom, - m_timeAxisProperties->visibleRangeMin(), - m_timeAxisProperties->visibleRangeMax() ); + m_plotWidget->setAxisScale( QwtPlot::xBottom, + m_timeAxisProperties->visibleRangeMin(), + m_timeAxisProperties->visibleRangeMax() ); } } } @@ -808,21 +889,21 @@ void RimSummaryPlot::updateZoomForAxis( RiaDefines::PlotAxis plotAxis ) std::swap( min, max ); } - m_qwtPlot->setAxisScale( yAxisProps->qwtPlotAxisType(), min, max ); + m_plotWidget->setAxisScale( yAxisProps->qwtPlotAxisType(), min, max ); } else { - m_qwtPlot->setAxisAutoScale( yAxisProps->qwtPlotAxisType(), true ); + m_plotWidget->setAxisAutoScale( yAxisProps->qwtPlotAxisType(), true ); } } else { - m_qwtPlot->setAxisScale( yAxisProps->qwtPlotAxisType(), - yAxisProps->visibleRangeMin(), - yAxisProps->visibleRangeMax() ); + m_plotWidget->setAxisScale( yAxisProps->qwtPlotAxisType(), + yAxisProps->visibleRangeMin(), + yAxisProps->visibleRangeMax() ); } - m_qwtPlot->axisScaleEngine( yAxisProps->qwtPlotAxisType() ) + m_plotWidget->axisScaleEngine( yAxisProps->qwtPlotAxisType() ) ->setAttribute( QwtScaleEngine::Inverted, yAxisProps->isAxisInverted() ); } } @@ -969,11 +1050,11 @@ std::vector RimSummaryPlot::visibleAsciiDataCurvesForAxis( R //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateTimeAxis() { - if ( !m_qwtPlot ) return; + if ( !m_plotWidget ) return; if ( !m_timeAxisProperties->isActive() ) { - m_qwtPlot->enableAxis( QwtPlot::xBottom, false ); + m_plotWidget->enableAxis( QwtPlot::xBottom, false ); return; } @@ -986,20 +1067,20 @@ void RimSummaryPlot::updateTimeAxis() QString dateFormat = m_timeAxisProperties->dateFormat(); QString timeFormat = m_timeAxisProperties->timeFormat(); - m_qwtPlot->useDateBasedTimeAxis( dateFormat, timeFormat, dateComponents, timeComponents ); + m_plotWidget->useDateBasedTimeAxis( dateFormat, timeFormat, dateComponents, timeComponents ); } else { - m_qwtPlot->useTimeBasedTimeAxis(); + m_plotWidget->useTimeBasedTimeAxis(); } - m_qwtPlot->enableAxis( QwtPlot::xBottom, true ); + m_plotWidget->enableAxis( QwtPlot::xBottom, true ); { QString axisTitle; if ( m_timeAxisProperties->showTitle ) axisTitle = m_timeAxisProperties->title(); - QwtText timeAxisTitle = m_qwtPlot->axisTitle( QwtPlot::xBottom ); + QwtText timeAxisTitle = m_plotWidget->axisTitle( QwtPlot::xBottom ); QFont font = timeAxisTitle.font(); font.setBold( true ); @@ -1018,14 +1099,14 @@ void RimSummaryPlot::updateTimeAxis() break; } - m_qwtPlot->setAxisTitle( QwtPlot::xBottom, timeAxisTitle ); + m_plotWidget->setAxisTitle( QwtPlot::xBottom, timeAxisTitle ); } { - QFont timeAxisFont = m_qwtPlot->axisFont( QwtPlot::xBottom ); + QFont timeAxisFont = m_plotWidget->axisFont( QwtPlot::xBottom ); timeAxisFont.setBold( false ); timeAxisFont.setPointSize( m_timeAxisProperties->valuesFontSize() ); - m_qwtPlot->setAxisFont( QwtPlot::xBottom, timeAxisFont ); + m_plotWidget->setAxisFont( QwtPlot::xBottom, timeAxisFont ); } } @@ -1034,7 +1115,7 @@ void RimSummaryPlot::updateTimeAxis() //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateBottomXAxis() { - if ( !m_qwtPlot ) return; + if ( !m_plotWidget ) return; QwtPlot::Axis qwtAxis = QwtPlot::xBottom; @@ -1042,7 +1123,7 @@ void RimSummaryPlot::updateBottomXAxis() if ( bottomAxisProperties->isActive() ) { - m_qwtPlot->enableAxis( qwtAxis, true ); + m_plotWidget->enableAxis( qwtAxis, true ); std::set timeHistoryQuantities; @@ -1050,11 +1131,11 @@ void RimSummaryPlot::updateBottomXAxis() visibleSummaryCurvesForAxis( RiaDefines::PLOT_AXIS_BOTTOM ), visibleAsciiDataCurvesForAxis( RiaDefines::PLOT_AXIS_BOTTOM ), timeHistoryQuantities ); - calc.applyYAxisPropertiesToPlot( m_qwtPlot ); + calc.applyYAxisPropertiesToPlot( m_plotWidget ); } else { - m_qwtPlot->enableAxis( qwtAxis, false ); + m_plotWidget->enableAxis( qwtAxis, false ); } } @@ -1074,9 +1155,9 @@ void RimSummaryPlot::updateCaseNameHasChanged() //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::zoomAll() { - setAutoZoomForAllAxes( true ); + setAutoScaleXEnabled( true ); + setAutoScaleYEnabled( true ); updateZoomInQwt(); - updateAxisRangesFromQwt(); } //-------------------------------------------------------------------------------------------------- @@ -1088,9 +1169,9 @@ void RimSummaryPlot::addCurveAndUpdate( RimSummaryCurve* curve ) { m_summaryCurveCollection->addCurve( curve ); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - curve->setParentQwtPlotAndReplot( m_qwtPlot ); + curve->setParentQwtPlotAndReplot( m_plotWidget ); this->updateAxes(); } } @@ -1105,9 +1186,9 @@ void RimSummaryPlot::addCurveNoUpdate( RimSummaryCurve* curve ) { m_summaryCurveCollection->addCurve( curve ); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - curve->setParentQwtPlotNoReplot( m_qwtPlot ); + curve->setParentQwtPlotNoReplot( m_plotWidget ); } } } @@ -1117,7 +1198,7 @@ void RimSummaryPlot::addCurveNoUpdate( RimSummaryCurve* curve ) //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteCurve( RimSummaryCurve* curve ) { - deleteCurves( {curve} ); + deleteCurves( { curve } ); } //-------------------------------------------------------------------------------------------------- @@ -1149,9 +1230,9 @@ void RimSummaryPlot::deleteCurves( const std::vector& curves ) curveSet->deleteCurve( curve ); if ( curveSet->curves().empty() ) { - if ( curveSet->colorMode() == RimEnsembleCurveSet::BY_ENSEMBLE_PARAM && qwtPlot() ) + if ( curveSet->colorMode() == RimEnsembleCurveSet::BY_ENSEMBLE_PARAM && m_plotWidget ) { - qwtPlot()->removeEnsembleCurveSetLegend( curveSet ); + m_plotWidget->removeEnsembleCurveSetLegend( curveSet ); } m_ensembleCurveSetCollection->deleteCurveSet( curveSet ); } @@ -1194,9 +1275,9 @@ void RimSummaryPlot::addGridTimeHistoryCurve( RimGridTimeHistoryCurve* curve ) CVF_ASSERT( curve ); m_gridTimeHistoryCurves.push_back( curve ); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - curve->setParentQwtPlotAndReplot( m_qwtPlot ); + curve->setParentQwtPlotAndReplot( m_plotWidget ); this->updateAxes(); } } @@ -1209,9 +1290,9 @@ void RimSummaryPlot::addGridTimeHistoryCurveNoUpdate( RimGridTimeHistoryCurve* c CVF_ASSERT( curve ); m_gridTimeHistoryCurves.push_back( curve ); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - curve->setParentQwtPlotNoReplot( m_qwtPlot ); + curve->setParentQwtPlotNoReplot( m_plotWidget ); } } @@ -1231,19 +1312,27 @@ void RimSummaryPlot::addAsciiDataCruve( RimAsciiDataCurve* curve ) CVF_ASSERT( curve ); m_asciiDataCurves.push_back( curve ); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - curve->setParentQwtPlotAndReplot( m_qwtPlot ); + curve->setParentQwtPlotAndReplot( m_plotWidget ); this->updateAxes(); } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::loadDataAndUpdate() +{ + onLoadDataAndUpdate(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimSummaryPlot::userDescriptionField() { - return &m_userDefinedPlotTitle; + return &m_description; } //-------------------------------------------------------------------------------------------------- @@ -1306,7 +1395,7 @@ void RimSummaryPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, { RimViewWindow::fieldChangedByUi( changedField, oldValue, newValue ); - if ( changedField == &m_userDefinedPlotTitle || changedField == &m_showPlotTitle || changedField == &m_showLegend || + if ( changedField == &m_description || changedField == &m_showPlotTitle || changedField == &m_showLegend || changedField == &m_legendFontSize || changedField == &m_useAutoPlotTitle ) { updatePlotTitle(); @@ -1354,9 +1443,9 @@ QImage RimSummaryPlot::snapshotWindowContent() #endif QImage image; - if ( m_qwtPlot ) + if ( m_plotWidget ) { - QPixmap pix = m_qwtPlot->grab(); + QPixmap pix = m_plotWidget->grab(); image = pix.toImage(); } @@ -1429,7 +1518,7 @@ void RimSummaryPlot::onLoadDataAndUpdate() curve->loadDataAndUpdate( false ); } - if ( m_qwtPlot ) m_qwtPlot->updateLegend(); + if ( m_plotWidget ) m_plotWidget->updateLegend(); this->updateAxes(); } @@ -1438,82 +1527,28 @@ void RimSummaryPlot::onLoadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomInQwt() { - if ( m_qwtPlot ) + if ( m_plotWidget ) { updateZoomForAxis( RiaDefines::PLOT_AXIS_BOTTOM ); updateZoomForAxis( RiaDefines::PLOT_AXIS_LEFT ); updateZoomForAxis( RiaDefines::PLOT_AXIS_RIGHT ); - m_qwtPlot->replot(); - - updateAxisRangesFromQwt(); + m_plotWidget->updateAxes(); + updateZoomFromQwt(); + m_plotWidget->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::updateZoomWindowFromQwt() +void RimSummaryPlot::updateZoomFromQwt() { - updateAxisRangesFromQwt(); - setAutoZoomForAllAxes( false ); -} + if ( !m_plotWidget ) return; -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::selectAxisInPropertyEditor( int axis ) -{ - RiuPlotMainWindowTools::showPlotMainWindow(); - if ( axis == QwtPlot::yLeft ) - { - RiuPlotMainWindowTools::selectAsCurrentItem( m_leftYAxisProperties ); - } - else if ( axis == QwtPlot::yRight ) - { - RiuPlotMainWindowTools::selectAsCurrentItem( m_rightYAxisProperties ); - } - else if ( axis == QwtPlot::xBottom ) - { - if ( m_isCrossPlot ) - { - RiuPlotMainWindowTools::selectAsCurrentItem( m_bottomAxisProperties ); - } - else - { - RiuPlotMainWindowTools::selectAsCurrentItem( m_timeAxisProperties ); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::setAutoZoomForAllAxes( bool enableAutoZoom ) -{ - m_leftYAxisProperties->setAutoZoom( enableAutoZoom ); - m_rightYAxisProperties->setAutoZoom( enableAutoZoom ); - - if ( m_isCrossPlot ) - { - m_bottomAxisProperties->setAutoZoom( enableAutoZoom ); - } - else - { - m_timeAxisProperties->setAutoZoom( enableAutoZoom ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::updateAxisRangesFromQwt() -{ - if ( !m_qwtPlot ) return; - - QwtInterval leftAxis = m_qwtPlot->currentAxisRange( QwtPlot::yLeft ); - QwtInterval rightAxis = m_qwtPlot->currentAxisRange( QwtPlot::yRight ); - QwtInterval timeAxis = m_qwtPlot->currentAxisRange( QwtPlot::xBottom ); + QwtInterval leftAxis = m_plotWidget->axisRange( QwtPlot::yLeft ); + QwtInterval rightAxis = m_plotWidget->axisRange( QwtPlot::yRight ); + QwtInterval timeAxis = m_plotWidget->axisRange( QwtPlot::xBottom ); m_leftYAxisProperties->visibleRangeMax = leftAxis.maxValue(); m_leftYAxisProperties->visibleRangeMin = leftAxis.minValue(); @@ -1542,7 +1577,29 @@ void RimSummaryPlot::updateAxisRangesFromQwt() //-------------------------------------------------------------------------------------------------- std::set RimSummaryPlot::allPlotAxes() const { - return {m_timeAxisProperties, m_bottomAxisProperties, m_leftYAxisProperties, m_rightYAxisProperties}; + return { m_timeAxisProperties, m_bottomAxisProperties, m_leftYAxisProperties, m_rightYAxisProperties }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::addOrUpdateEnsembleCurveSetLegend( RimEnsembleCurveSet* curveSet ) +{ + if ( m_plotWidget ) + { + m_plotWidget->addOrUpdateEnsembleCurveSetLegend( curveSet ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::removeEnsembleCurveSetLegend( RimEnsembleCurveSet* curveSet ) +{ + if ( m_plotWidget ) + { + m_plotWidget->removeEnsembleCurveSetLegend( curveSet ); + } } //-------------------------------------------------------------------------------------------------- @@ -1558,7 +1615,7 @@ void RimSummaryPlot::deleteAllGridTimeHistoryCurves() //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setDescription( const QString& description ) { - m_userDefinedPlotTitle = description; + m_description = description; } //-------------------------------------------------------------------------------------------------- @@ -1566,7 +1623,15 @@ void RimSummaryPlot::setDescription( const QString& description ) //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::description() const { - return m_userDefinedPlotTitle(); + return m_description(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSummaryPlot::isChecked() const +{ + return isWindowVisible(); } //-------------------------------------------------------------------------------------------------- @@ -1614,9 +1679,9 @@ void RimSummaryPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& if ( m_showPlotTitle ) { mainOptions->add( &m_useAutoPlotTitle ); - mainOptions->add( &m_userDefinedPlotTitle ); + mainOptions->add( &m_description ); } - m_userDefinedPlotTitle.uiCapability()->setUiReadOnly( m_useAutoPlotTitle ); + m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle ); mainOptions->add( &m_showLegend ); if ( m_showLegend() ) @@ -1641,32 +1706,32 @@ void RimSummaryPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& //-------------------------------------------------------------------------------------------------- QWidget* RimSummaryPlot::createViewWidget( QWidget* mainWindowParent ) { - if ( !m_qwtPlot ) + if ( !m_plotWidget ) { - m_qwtPlot = new RiuSummaryQwtPlot( this, mainWindowParent ); + m_plotWidget = new RiuSummaryQwtPlot( this, mainWindowParent ); for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { - curve->setParentQwtPlotNoReplot( m_qwtPlot ); + curve->setParentQwtPlotNoReplot( m_plotWidget ); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { - curve->setParentQwtPlotNoReplot( m_qwtPlot ); + curve->setParentQwtPlotNoReplot( m_plotWidget ); } if ( m_summaryCurveCollection ) { - m_summaryCurveCollection->setParentQwtPlotAndReplot( m_qwtPlot ); + m_summaryCurveCollection->setParentQwtPlotAndReplot( m_plotWidget ); } if ( m_ensembleCurveSetCollection ) { - m_ensembleCurveSetCollection->setParentQwtPlotAndReplot( m_qwtPlot ); + m_ensembleCurveSetCollection->setParentQwtPlotAndReplot( m_plotWidget ); } } - return m_qwtPlot; + return m_plotWidget; } //-------------------------------------------------------------------------------------------------- @@ -1676,10 +1741,10 @@ void RimSummaryPlot::deleteViewWidget() { detachAllCurves(); - if ( m_qwtPlot ) + if ( m_plotWidget ) { - m_qwtPlot->deleteLater(); - m_qwtPlot = nullptr; + m_plotWidget->deleteLater(); + m_plotWidget = nullptr; } } @@ -1711,7 +1776,8 @@ void RimSummaryPlot::initAfterRead() if ( !m_isAutoZoom_OBSOLETE() ) { - setAutoZoomForAllAxes( false ); + setAutoScaleXEnabled( false ); + setAutoScaleYEnabled( false ); } RimProject* proj = nullptr; @@ -1730,34 +1796,34 @@ void RimSummaryPlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateMdiWindowTitle() { - if ( m_qwtPlot ) + if ( m_plotWidget ) { QString plotTitle = description(); - m_qwtPlot->setWindowTitle( plotTitle ); + m_plotWidget->setWindowTitle( plotTitle ); if ( m_showPlotTitle ) { - m_qwtPlot->setTitle( plotTitle ); + m_plotWidget->setTitle( plotTitle ); } else { - m_qwtPlot->setTitle( "" ); + m_plotWidget->setTitle( "" ); } if ( m_showLegend ) { // Will be released in plot destructor or when a new legend is set - QwtLegend* legend = new QwtLegend( m_qwtPlot ); + QwtLegend* legend = new QwtLegend( m_plotWidget ); auto font = legend->font(); font.setPointSize( m_legendFontSize() ); legend->setFont( font ); - m_qwtPlot->insertLegend( legend, QwtPlot::BottomLegend ); + m_plotWidget->insertLegend( legend, QwtPlot::BottomLegend ); } else { - m_qwtPlot->insertLegend( nullptr ); + m_plotWidget->insertLegend( nullptr ); } } } @@ -1805,6 +1871,14 @@ void RimSummaryPlot::updateNameHelperWithCurveData( RimSummaryPlotNameHelper* na nameHelper->setEnsembleCases( ensembleCases ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::updateLayout() +{ + this->loadDataAndUpdate(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1870,53 +1944,6 @@ void RimSummaryPlot::reattachAllCurves() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -caf::PdmObject* RimSummaryPlot::findRimPlotObjectFromQwtCurve( const QwtPlotCurve* qwtCurve ) const -{ - for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) - { - if ( curve->qwtPlotCurve() == qwtCurve ) - { - return curve; - } - } - - for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) - { - if ( curve->qwtPlotCurve() == qwtCurve ) - { - return curve; - } - } - - if ( m_summaryCurveCollection ) - { - RimSummaryCurve* foundCurve = m_summaryCurveCollection->findRimCurveFromQwtCurve( qwtCurve ); - - if ( foundCurve ) - { - m_summaryCurveCollection->setCurrentSummaryCurve( foundCurve ); - - return foundCurve; - } - } - - if ( m_ensembleCurveSetCollection ) - { - RimEnsembleCurveSet* foundCurveSet = m_ensembleCurveSetCollection->findRimCurveSetFromQwtCurve( qwtCurve ); - - if ( foundCurveSet ) - { - m_ensembleCurveSetCollection->setCurrentSummaryCurveSet( foundCurveSet ); - - return foundCurveSet; - } - } - return nullptr; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2039,6 +2066,30 @@ std::vector RimSummaryPlot::fieldsToShowInToolbar() return toolBarFields; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::setAutoScaleXEnabled( bool enabled ) +{ + if ( m_isCrossPlot ) + { + m_bottomAxisProperties->setAutoZoom( enabled ); + } + else + { + m_timeAxisProperties->setAutoZoom( enabled ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryPlot::setAutoScaleYEnabled( bool enabled ) +{ + m_leftYAxisProperties->setAutoZoom( enabled ); + m_rightYAxisProperties->setAutoZoom( enabled ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2087,13 +2138,13 @@ void populateTimeHistoryCurvesData( std::vector curves if ( curveCaseName == curvesData->caseNames[i] ) casePosInList = i; } - CurveData curveData = {curve->curveExportDescription(), RifEclipseSummaryAddress(), curve->yValues()}; + CurveData curveData = { curve->curveExportDescription(), RifEclipseSummaryAddress(), curve->yValues() }; if ( casePosInList == cvf::UNDEFINED_SIZE_T ) { curvesData->caseNames.push_back( curveCaseName ); curvesData->timeSteps.push_back( curve->timeStepValues() ); - curvesData->allCurveData.push_back( std::vector( {curveData} ) ); + curvesData->allCurveData.push_back( std::vector( { curveData } ) ); } else { @@ -2119,13 +2170,13 @@ void populateAsciiDataCurvesData( std::vector curves, Curves size_t casePosInList = cvf::UNDEFINED_SIZE_T; - CurveData curveData = {curve->curveExportDescription(), RifEclipseSummaryAddress(), curve->yValues()}; + CurveData curveData = { curve->curveExportDescription(), RifEclipseSummaryAddress(), curve->yValues() }; if ( casePosInList == cvf::UNDEFINED_SIZE_T ) { curvesData->caseNames.push_back( "" ); curvesData->timeSteps.push_back( curve->timeSteps() ); - curvesData->allCurveData.push_back( std::vector( {curveData} ) ); + curvesData->allCurveData.push_back( std::vector( { curveData } ) ); } else { @@ -2161,7 +2212,7 @@ void populateSummaryCurvesData( std::vector curves, SummaryCur if ( curveCaseName == curvesData->caseNames[i] ) casePosInList = i; } - CurveData curveData = {curve->curveExportDescription(), curve->summaryAddressY(), curve->valuesY()}; + CurveData curveData = { curve->curveExportDescription(), curve->summaryAddressY(), curve->valuesY() }; CurveData errorCurveData; // Error data @@ -2177,7 +2228,7 @@ void populateSummaryCurvesData( std::vector curves, SummaryCur if ( casePosInList == cvf::UNDEFINED_SIZE_T ) { - auto curveDataList = std::vector( {curveData} ); + auto curveDataList = std::vector( { curveData } ); if ( hasErrorData ) curveDataList.push_back( errorCurveData ); curvesData->caseNames.push_back( curveCaseName ); diff --git a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h index a26b6fcda6..4e99642aed 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -24,7 +24,8 @@ #include "RifEclipseSummaryAddress.h" -#include "RimPlot.h" +#include "RimPlotInterface.h" +#include "RimPlotWindow.h" #include "RimRiuQwtPlotOwnerInterface.h" #include "qwt_plot_textlabel.h" @@ -64,7 +65,7 @@ class QKeyEvent; /// /// //================================================================================================== -class RimSummaryPlot : public RimPlot, public RimRiuQwtPlotOwnerInterface +class RimSummaryPlot : public RimPlotWindow, public RimPlotInterface { CAF_PDM_HEADER_INIT; @@ -74,6 +75,7 @@ public: void setDescription( const QString& description ); QString description() const; + bool isChecked() const override; void enableShowPlotTitle( bool enable ); void enableAutoPlotTitle( bool enable ); @@ -104,16 +106,14 @@ public: void updateCaseNameHasChanged(); void updateAxes(); - void zoomAll() override; - - void updateZoomInQwt(); bool isLogarithmicScaleEnabled( RiaDefines::PlotAxis plotAxis ) const; RimSummaryTimeAxisProperties* timeAxisProperties(); time_t firstTimeStepOfFirstCurve(); - QWidget* viewWidget() override; + QWidget* viewWidget() override; + RiuQwtPlotWidget* viewer() override; QString asciiDataForPlotExport( DateTimePeriod resamplingPeriod, bool showTimeAsLongString ) const; @@ -122,11 +122,10 @@ public: std::vector summaryCurves() const; void deleteAllSummaryCurves(); RimSummaryCurveCollection* summaryCurveCollection() const; - RiuSummaryQwtPlot* qwtPlot() const; std::vector curveSets() const; - void updatePlotTitle(); + void updatePlotTitle() override; const RimSummaryPlotNameHelper* activePlotTitleHelperAllCurves() const; void updateCurveNames(); @@ -134,6 +133,8 @@ public: void copyAxisPropertiesFromOther( const RimSummaryPlot& sourceSummaryPlot ); + void updateLayout() override; + void updateAll(); void updateAllLegendItems(); @@ -163,14 +164,21 @@ public: virtual RimSummaryPlotSourceStepping* sourceSteppingObjectForKeyEventHandling() const; virtual std::vector fieldsToShowInToolbar(); -public: - // Rim2dPlotInterface overrides - void updateAxisScaling() override; - void updateAxisDisplay() override; - void updateZoomWindowFromQwt() override; - void selectAxisInPropertyEditor( int axis ) override; - void setAutoZoomForAllAxes( bool enableAutoZoom ) override; - caf::PdmObject* findRimPlotObjectFromQwtCurve( const QwtPlotCurve* curve ) const override; + void setAutoScaleXEnabled( bool enabled ) override; + void setAutoScaleYEnabled( bool enabled ) override; + + void zoomAll() override; + void updateZoomInQwt() override; + void updateZoomFromQwt() override; + + void createPlotWidget() override; + caf::PdmObject* findPdmObjectFromQwtCurve( const QwtPlotCurve* curve ) const override; + + void onAxisSelected( int axis, bool toggle ) override; + void loadDataAndUpdate(); + + void addOrUpdateEnsembleCurveSetLegend( RimEnsembleCurveSet* curveSet ); + void removeEnsembleCurveSetLegend( RimEnsembleCurveSet* curveSet ); public: // RimViewWindow overrides @@ -208,15 +216,13 @@ private: bool hasVisibleCurvesForAxis( RiaDefines::PlotAxis plotAxis ) const; RimPlotAxisProperties* yAxisPropertiesLeftOrRight( RiaDefines::PlotAxis leftOrRightPlotAxis ) const; - void updateAxis( RiaDefines::PlotAxis plotAxis ); + void updateYAxis( RiaDefines::PlotAxis plotAxis ); void updateZoomForAxis( RiaDefines::PlotAxis plotAxis ); void updateTimeAxis(); void updateBottomXAxis(); - void updateAxisRangesFromQwt(); - std::set allPlotAxes() const; private: @@ -226,8 +232,7 @@ private: caf::PdmField m_legendFontSize; - caf::PdmField m_useAutoPlotTitle; - caf::PdmField m_userDefinedPlotTitle; + caf::PdmField m_useAutoPlotTitle; caf::PdmChildArrayField m_gridTimeHistoryCurves; caf::PdmChildField m_summaryCurveCollection; @@ -245,7 +250,7 @@ private: caf::PdmChildField m_textCurveSetEditor; - QPointer m_qwtPlot; + QPointer m_plotWidget; std::unique_ptr m_plotInfoLabel; bool m_isCrossPlot; diff --git a/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.cpp b/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.cpp index 0a5b3eb7d4..917aaf345e 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.cpp @@ -356,6 +356,42 @@ bool RigWellLogCurveData::calculateMDRange( double* minimumDepth, double* maximu return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigWellLogCurveData::calculateTVDRange( double* minTVD, double* maxTVD ) const +{ + CVF_ASSERT( minTVD && maxTVD ); + + double minValue = HUGE_VAL; + double maxValue = -HUGE_VAL; + + for ( size_t vIdx = 0; vIdx < m_tvDepths.size(); vIdx++ ) + { + double value = m_tvDepths[vIdx]; + + if ( value < minValue ) + { + minValue = value; + } + + if ( value > maxValue ) + { + maxValue = value; + } + } + + if ( maxValue >= minValue ) + { + *minTVD = minValue; + *maxTVD = maxValue; + + return true; + } + + return false; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.h b/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.h index d97bd98fe6..1e49fce51c 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.h +++ b/ApplicationCode/ReservoirDataModel/RigWellLogCurveData.h @@ -51,6 +51,7 @@ public: const std::vector& measuredDepths() const; const std::vector& tvDepths() const; bool calculateMDRange( double* minMD, double* maxMD ) const; + bool calculateTVDRange( double* minTVD, double* maxTVD ) const; RiaDefines::DepthUnitType depthUnit() const; diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index 9989e0da46..48fa95c6ec 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -37,7 +37,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuRmsNavigation.h ${CMAKE_CURRENT_LIST_DIR}/RiuSelectionChangedHandler.h ${CMAKE_CURRENT_LIST_DIR}/Riu3dSelectionManager.h ${CMAKE_CURRENT_LIST_DIR}/RiuSimpleHistogramWidget.h -${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuDockedQwtPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuGridCrossQwtPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQwtPlot.h @@ -52,6 +51,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuViewerCommands.h ${CMAKE_CURRENT_LIST_DIR}/RiuPickItemInfo.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h +${CMAKE_CURRENT_LIST_DIR}/RiuGridPlotWindow.h +${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.h +${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.h ${CMAKE_CURRENT_LIST_DIR}/RiuPlotAnnotationTool.h ${CMAKE_CURRENT_LIST_DIR}/RiuGeoMechXfTensorResultAccessor.h ${CMAKE_CURRENT_LIST_DIR}/RiuFemTimeHistoryResultAccessor.h @@ -123,7 +125,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuRmsNavigation.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuSelectionChangedHandler.cpp ${CMAKE_CURRENT_LIST_DIR}/Riu3dSelectionManager.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuSimpleHistogramWidget.cpp -${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlot.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuDockedQwtPlot.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuGridCrossQwtPlot.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQwtPlot.cpp @@ -135,8 +136,11 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuTreeViewEventFilter.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuViewer.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuViewerCommands.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuPickItemInfo.cpp -${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuGridPlotWindow.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.cpp +${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuPlotAnnotationTool.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuGeoMechXfTensorResultAccessor.cpp ${CMAKE_CURRENT_LIST_DIR}/RiuFemTimeHistoryResultAccessor.cpp @@ -195,8 +199,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuViewerCommands.h ${CMAKE_CURRENT_LIST_DIR}/RiuTreeViewEventFilter.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h +${CMAKE_CURRENT_LIST_DIR}/RiuGridPlotWindow.h +${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.h +${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.h ${CMAKE_CURRENT_LIST_DIR}/RiuRecentFileActionProvider.h -${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuDockedQwtPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuGridCrossQwtPlot.h ${CMAKE_CURRENT_LIST_DIR}/RiuSummaryQwtPlot.h diff --git a/ApplicationCode/UserInterface/RiuDragDrop.cpp b/ApplicationCode/UserInterface/RiuDragDrop.cpp index f92af40e87..3e1227fe45 100644 --- a/ApplicationCode/UserInterface/RiuDragDrop.cpp +++ b/ApplicationCode/UserInterface/RiuDragDrop.cpp @@ -27,6 +27,7 @@ #include "RimCaseCollection.h" #include "RimEclipseCase.h" #include "RimEclipseResultCase.h" +#include "RimGridPlotWindow.h" #include "RimIdenticalGridCaseGroup.h" #include "RimMimeData.h" #include "RimSummaryCase.h" @@ -57,15 +58,15 @@ class RiuTypedPdmObjects public: explicit RiuTypedPdmObjects( const caf::PdmObjectGroup& objectGroup ) { - objectGroup.objectsByType( &m_typedObjects ); + objectGroup.objectsByType( &m_objects ); } explicit RiuTypedPdmObjects( const std::vector>& objectHandles ) { for ( size_t i = 0; i < objectHandles.size(); i++ ) { - T* obj = dynamic_cast( objectHandles[i].p() ); - if ( obj ) m_typedObjects.push_back( obj ); + caf::PdmObject* obj = dynamic_cast( objectHandles[i].p() ); + if ( obj ) m_objects.push_back( obj ); } } @@ -91,16 +92,20 @@ private: std::vector typedObjects() { std::vector typedObjectsVec; - for ( size_t i = 0; i < m_typedObjects.size(); i++ ) + for ( size_t i = 0; i < m_objects.size(); i++ ) { - typedObjectsVec.push_back( m_typedObjects[i].p() ); + T* typedObject = dynamic_cast( m_objects[i].p() ); + if ( typedObject ) + { + typedObjectsVec.push_back( typedObject ); + } } return typedObjectsVec; } private: - std::vector> m_typedObjects; + std::vector> m_objects; }; //-------------------------------------------------------------------------------------------------- @@ -284,11 +289,11 @@ bool RiuDragDrop::dropMimeData( const QMimeData* data, Qt::DropAction action, in return handleWellLogPlotTrackDrop( action, draggedObjects, wellLogPlotTrack, row ); } - RimWellLogPlot* wellLogPlot; - dropTarget->firstAncestorOrThisOfType( wellLogPlot ); - if ( wellLogPlot ) + RimGridPlotWindow* gridPlotWindow; + dropTarget->firstAncestorOrThisOfType( gridPlotWindow ); + if ( gridPlotWindow ) { - return handleWellLogPlotDrop( action, draggedObjects, wellLogPlot, row ); + return handleGridPlotWindowDrop( action, draggedObjects, gridPlotWindow, row ); } RimSummaryCaseCollection* summaryCaseCollection; @@ -404,7 +409,7 @@ bool RiuDragDrop::handleWellLogPlotTrackDrop( Qt::DropAction action, RimWellLogCurve* insertAfter = nullptr; if ( insertAtPosition > 0 ) { - auto visibleCurves = trackTarget->visibleCurvesVector(); + auto visibleCurves = trackTarget->visibleCurves(); if ( !visibleCurves.empty() ) { int insertAfterPosition = std::min( insertAtPosition - 1, (int)visibleCurves.size() - 1 ); @@ -424,7 +429,7 @@ bool RiuDragDrop::handleWellLogPlotTrackDrop( Qt::DropAction action, { RimWellLogPlot* wellLogPlot; trackTarget->firstAncestorOrThisOfType( wellLogPlot ); - return handleWellLogPlotDrop( action, draggedObjects, wellLogPlot, insertAtPosition ); + return handleGridPlotWindowDrop( action, draggedObjects, wellLogPlot, insertAtPosition ); } } @@ -434,28 +439,27 @@ bool RiuDragDrop::handleWellLogPlotTrackDrop( Qt::DropAction action, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RiuDragDrop::handleWellLogPlotDrop( Qt::DropAction action, - caf::PdmObjectGroup& draggedObjects, - RimWellLogPlot* wellLogPlotTarget, - int insertAtPosition ) +bool RiuDragDrop::handleGridPlotWindowDrop( Qt::DropAction action, + caf::PdmObjectGroup& draggedObjects, + RimGridPlotWindow* gridPlotWindow, + int insertAtPosition ) { - std::vector wellLogPlotTracks = RiuTypedPdmObjects::typedObjectsFromGroup( - draggedObjects ); - if ( wellLogPlotTracks.size() > 0 ) + std::vector plots = RiuTypedPdmObjects::typedObjectsFromGroup( draggedObjects ); + if ( plots.size() > 0 ) { if ( action == Qt::MoveAction ) { - RimWellLogTrack* insertAfter = nullptr; + RimPlotInterface* insertAfter = nullptr; if ( insertAtPosition > 0 ) { - auto visibleTracks = wellLogPlotTarget->visibleTracks(); + auto visibleTracks = gridPlotWindow->visiblePlots(); if ( !visibleTracks.empty() ) { int insertAfterPosition = std::min( insertAtPosition - 1, (int)visibleTracks.size() - 1 ); - insertAfter = visibleTracks[insertAfterPosition]; + insertAfter = dynamic_cast( visibleTracks[insertAfterPosition] ); } } - RicWellLogPlotTrackFeatureImpl::moveTracksToWellLogPlot( wellLogPlotTarget, wellLogPlotTracks, insertAfter ); + RicWellLogPlotTrackFeatureImpl::movePlotsToGridPlotWindow( gridPlotWindow, plots, insertAfter ); return true; } } diff --git a/ApplicationCode/UserInterface/RiuDragDrop.h b/ApplicationCode/UserInterface/RiuDragDrop.h index 972f31d20b..c7fdc28510 100644 --- a/ApplicationCode/UserInterface/RiuDragDrop.h +++ b/ApplicationCode/UserInterface/RiuDragDrop.h @@ -29,6 +29,7 @@ namespace caf class PdmObjectHandle; } +class RimGridPlotWindow; class RimIdenticalGridCaseGroup; class RimSummaryCaseCollection; class RimSummaryCaseMainCollection; @@ -64,10 +65,10 @@ private: caf::PdmObjectGroup& objectGroup, RimWellLogTrack* wellLogPlotTrack, int insertAtPosition ); - bool handleWellLogPlotDrop( Qt::DropAction action, - caf::PdmObjectGroup& objectGroup, - RimWellLogPlot* wellLogPlot, - int insertAtPosition ); + bool handleGridPlotWindowDrop( Qt::DropAction action, + caf::PdmObjectGroup& objectGroup, + RimGridPlotWindow* gridPlotWindow, + int insertAtPosition ); bool handleWellLogPlotCurveDrop( Qt::DropAction action, caf::PdmObjectGroup& objectGroup, RimWellLogCurve* wellLogPlotCurve ); diff --git a/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp b/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp index 463b7a4e9e..9bd13a1011 100644 --- a/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.cpp @@ -21,12 +21,16 @@ #include "RiuCvfOverlayItemWidget.h" #include "RiuQwtCurvePointTracker.h" +#include "RiuQwtPlotTools.h" +#include "RiuQwtPlotWheelZoomer.h" +#include "RiuQwtPlotZoomer.h" #include "RiuRimQwtPlotCurve.h" #include "RiuWidgetDragger.h" #include "RimGridCrossPlot.h" #include "RimGridCrossPlotCurve.h" #include "RimGridCrossPlotDataSet.h" +#include "RimPlotInterface.h" #include "RimRegularLegendConfig.h" #include "cafCmdFeatureMenuBuilder.h" @@ -38,12 +42,12 @@ #include "RimPlotAxisProperties.h" #include "RiuPlotAnnotationTool.h" +#include "qwt_plot_panner.h" #include "qwt_scale_draw.h" #include "qwt_scale_widget.h" #include "qwt_text.h" #include "qwt_text_engine.h" -#include #include #include #include @@ -52,9 +56,35 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuGridCrossQwtPlot::RiuGridCrossQwtPlot( RimViewWindow* ownerViewWindow, QWidget* parent /*= nullptr*/ ) - : RiuQwtPlot( ownerViewWindow, parent ) +RiuGridCrossQwtPlot::RiuGridCrossQwtPlot( RimPlotInterface* plotDefinition, QWidget* parent /*= nullptr*/ ) + : RiuQwtPlotWidget( plotDefinition, parent ) { + // LeftButton for the zooming + m_zoomerLeft = new RiuQwtPlotZoomer( canvas() ); + m_zoomerLeft->setRubberBandPen( QColor( Qt::black ) ); + m_zoomerLeft->setTrackerMode( QwtPicker::AlwaysOff ); + m_zoomerLeft->setTrackerPen( QColor( Qt::black ) ); + m_zoomerLeft->initMousePattern( 1 ); + m_zoomerLeft->setMousePattern( QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier ); + + // Attach a zoomer for the right axis + m_zoomerRight = new RiuQwtPlotZoomer( canvas() ); + m_zoomerRight->setAxis( xTop, yRight ); + m_zoomerRight->setTrackerMode( QwtPicker::AlwaysOff ); + m_zoomerRight->initMousePattern( 1 ); + m_zoomerRight->setMousePattern( QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier ); + + // MidButton for the panning + QwtPlotPanner* panner = new QwtPlotPanner( canvas() ); + panner->setMouseButton( Qt::MidButton ); + + auto wheelZoomer = new RiuQwtPlotWheelZoomer( this ); + + connect( wheelZoomer, SIGNAL( zoomUpdated() ), SLOT( onZoomedSlot() ) ); + connect( m_zoomerLeft, SIGNAL( zoomed( const QRectF& ) ), SLOT( onZoomedSlot() ) ); + connect( m_zoomerRight, SIGNAL( zoomed( const QRectF& ) ), SLOT( onZoomedSlot() ) ); + connect( panner, SIGNAL( panned( int, int ) ), SLOT( onZoomedSlot() ) ); + m_annotationTool = std::unique_ptr( new RiuPlotAnnotationTool() ); m_infoBox = new RiuDraggableOverlayFrame( this, canvas() ); @@ -69,21 +99,11 @@ RiuGridCrossQwtPlot::RiuGridCrossQwtPlot( RimViewWindow* ownerViewWindow, QWidge m_selectedPointMarker->setLabelAlignment( Qt::AlignRight | Qt::AlignVCenter ); m_selectedPointMarker->setSpacing( 3 ); - canvas()->setContentsMargins( 0, 0, 0, 0 ); - QFrame* canvasFrame = dynamic_cast( canvas() ); - canvasFrame->setFrameShape( QFrame::Box ); - canvasFrame->setStyleSheet( "border: 1px solid black" ); + RiuQwtPlotTools::setCommonPlotBehaviour( this ); + RiuQwtPlotTools::setDefaultAxes( this ); - QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect( canvas() ); - dropShadowEffect->setOffset( 1.0, 1.0 ); - dropShadowEffect->setBlurRadius( 3.0 ); - dropShadowEffect->setColor( QColor( 60, 60, 60, 60 ) ); - canvas()->setGraphicsEffect( dropShadowEffect ); - - axisScaleDraw( QwtPlot::xBottom )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); - axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); - axisWidget( QwtPlot::xBottom )->setMargin( 0 ); - axisWidget( QwtPlot::yLeft )->setMargin( 0 ); + this->installEventFilter( this ); + this->canvas()->installEventFilter( this ); } //-------------------------------------------------------------------------------------------------- @@ -174,7 +194,7 @@ void RiuGridCrossQwtPlot::removeDanglingDataSetLegends() //-------------------------------------------------------------------------------------------------- void RiuGridCrossQwtPlot::updateLegendSizesToMatchPlot() { - RimGridCrossPlot* crossPlot = dynamic_cast( ownerPlotDefinition() ); + RimGridCrossPlot* crossPlot = dynamic_cast( plotDefinition() ); if ( !crossPlot ) return; bool anyLegendResized = false; @@ -215,6 +235,14 @@ void RiuGridCrossQwtPlot::updateAnnotationObjects( RimPlotAxisProperties* axisPr } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimViewWindow* RiuGridCrossQwtPlot::ownerViewWindow() const +{ + return dynamic_cast( plotDefinition() ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -230,7 +258,7 @@ void RiuGridCrossQwtPlot::updateLayout() //-------------------------------------------------------------------------------------------------- void RiuGridCrossQwtPlot::updateInfoBoxLayout() { - RimGridCrossPlot* crossPlot = dynamic_cast( ownerPlotDefinition() ); + RimGridCrossPlot* crossPlot = dynamic_cast( plotDefinition() ); if ( !crossPlot ) return; bool showInfo = false; @@ -300,7 +328,7 @@ void RiuGridCrossQwtPlot::updateLegendLayout() removeDanglingDataSetLegends(); - RimGridCrossPlot* crossPlot = dynamic_cast( ownerPlotDefinition() ); + RimGridCrossPlot* crossPlot = dynamic_cast( plotDefinition() ); if ( !crossPlot ) return; @@ -402,9 +430,9 @@ void RiuGridCrossQwtPlot::contextMenuEvent( QContextMenuEvent* event ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuGridCrossQwtPlot::selectSample( QwtPlotCurve* curve, int sampleNumber ) +void RiuGridCrossQwtPlot::selectPoint( QwtPlotCurve* curve, int pointNumber ) { - QPointF sample = curve->sample( sampleNumber ); + QPointF sample = curve->sample( pointNumber ); m_selectedPointMarker->setValue( sample ); m_selectedPointMarker->setAxes( QwtPlot::xBottom, QwtPlot::yLeft ); m_selectedPointMarker->attach( this ); @@ -426,7 +454,7 @@ void RiuGridCrossQwtPlot::selectSample( QwtPlotCurve* curve, int sampleNumber ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuGridCrossQwtPlot::clearSampleSelection() +void RiuGridCrossQwtPlot::clearPointSelection() { m_selectedPointMarker->detach(); } @@ -472,3 +500,11 @@ void RiuGridCrossQwtPlot::applyFontSizeToOverlayItem( caf::TitledOverlayFrame* o cvf::ref cafFont = RiaFontCache::getFont( RiaFontCache::fontSizeEnumFromPointSize( fontSize ) ); overlayItem->setFont( cafFont.p() ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridCrossQwtPlot::onZoomedSlot() +{ + plotDefinition()->updateZoomFromQwt(); +} diff --git a/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.h b/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.h index b0508c50b5..cd2124bfe1 100644 --- a/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuGridCrossQwtPlot.h @@ -19,7 +19,7 @@ #include "RiuInterfaceToViewWindow.h" #include "RiuPlotAnnotationTool.h" -#include "RiuQwtPlot.h" +#include "RiuQwtPlotWidget.h" #include "cafPdmPointer.h" @@ -29,9 +29,11 @@ class RimGridCrossPlotDataSet; class RimPlotAxisProperties; +class RimPlotInterface; class RiuCvfOverlayItemWidget; class RiuDraggableOverlayFrame; class RiuPlotAnnotationTool; +class RiuQwtPlotZoomer; namespace caf { @@ -43,12 +45,12 @@ class TitledOverlayFrame; // // //================================================================================================== -class RiuGridCrossQwtPlot : public RiuQwtPlot +class RiuGridCrossQwtPlot : public RiuQwtPlotWidget, public RiuInterfaceToViewWindow { Q_OBJECT; public: - RiuGridCrossQwtPlot( RimViewWindow* ownerViewWindow, QWidget* parent = nullptr ); + RiuGridCrossQwtPlot( RimPlotInterface* plotDefinition, QWidget* parent = nullptr ); ~RiuGridCrossQwtPlot(); void addOrUpdateDataSetLegend( RimGridCrossPlotDataSet* dataSetToShowLegendFor ); void removeDataSetLegend( RimGridCrossPlotDataSet* dataSetToShowLegendFor ); @@ -56,6 +58,8 @@ public: void updateLegendSizesToMatchPlot(); void updateAnnotationObjects( RimPlotAxisProperties* axisProperties ); + RimViewWindow* ownerViewWindow() const override; + protected: void updateLayout() override; void updateInfoBoxLayout(); @@ -64,11 +68,14 @@ protected: bool resizeOverlayItemToFitPlot( caf::TitledOverlayFrame* overlayItem ); void contextMenuEvent( QContextMenuEvent* ) override; - void selectSample( QwtPlotCurve* curve, int sampleNumber ) override; - void clearSampleSelection() override; + void selectPoint( QwtPlotCurve* curve, int pointNumber ) override; + void clearPointSelection() override; bool curveText( const QwtPlotCurve* curve, QString* curveTitle, QString* xParamName, QString* yParamName ) const; void applyFontSizeToOverlayItem( caf::TitledOverlayFrame* overlayItem ); +private slots: + void onZoomedSlot(); + private: typedef caf::PdmPointer DataSetPtr; typedef QPointer LegendPtr; @@ -78,4 +85,7 @@ private: std::map m_legendWidgets; std::unique_ptr m_annotationTool; QwtPlotMarker* m_selectedPointMarker; + + QPointer m_zoomerLeft; + QPointer m_zoomerRight; }; diff --git a/ApplicationCode/UserInterface/RiuGridPlotWindow.cpp b/ApplicationCode/UserInterface/RiuGridPlotWindow.cpp new file mode 100644 index 0000000000..16932beeb2 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuGridPlotWindow.cpp @@ -0,0 +1,687 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RiuGridPlotWindow.h" + +#include "RiaApplication.h" +#include "RiaPlotWindowRedrawScheduler.h" +#include "RiaPreferences.h" + +#include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h" + +#include "RimContextCommandBuilder.h" +#include "RimGridPlotWindow.h" +#include "RimWellLogTrack.h" + +#include "RiuMainWindow.h" +#include "RiuPlotMainWindow.h" +#include "RiuPlotObjectPicker.h" +#include "RiuQwtPlotLegend.h" +#include "RiuQwtPlotWidget.h" + +#include "cafCmdFeatureMenuBuilder.h" +#include "cafSelectionManager.h" + +#include "cvfAssert.h" + +#include "qwt_legend.h" +#include "qwt_plot_layout.h" +#include "qwt_scale_draw.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuGridPlotWindow::RiuGridPlotWindow( RimGridPlotWindow* plotDefinition, QWidget* parent ) + : QWidget( parent ) +{ + Q_ASSERT( plotDefinition ); + m_plotDefinition = plotDefinition; + + m_layout = new QVBoxLayout( this ); + m_layout->setMargin( 0 ); + m_layout->setSpacing( 2 ); + + m_plotTitle = createTitleLabel(); + m_layout->addWidget( m_plotTitle ); + + m_plotLayout = new QHBoxLayout; + m_layout->addLayout( m_plotLayout ); + + m_plotWidgetFrame = new QFrame; + m_plotWidgetFrame->setVisible( true ); + m_plotLayout->addWidget( m_plotWidgetFrame, 1 ); + + m_gridLayout = new QGridLayout( m_plotWidgetFrame ); + m_gridLayout->setMargin( 0 ); + m_gridLayout->setSpacing( 2 ); + + QPalette newPalette( palette() ); + newPalette.setColor( QPalette::Background, Qt::white ); + setPalette( newPalette ); + + setAutoFillBackground( true ); + + m_scrollBar = new QScrollBar( nullptr ); + m_scrollBar->setOrientation( Qt::Vertical ); + m_scrollBar->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ); + + m_scrollBarLayout = new QVBoxLayout; + m_scrollBarLayout->addWidget( m_scrollBar, 0 ); + + new RiuPlotObjectPicker( m_plotTitle, m_plotDefinition ); + + this->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); + + setFocusPolicy( Qt::StrongFocus ); + + setAcceptDrops( true ); + + RiaApplication* app = RiaApplication::instance(); + int defaultFontSize = RiaFontCache::pointSizeFromFontSizeEnum( app->preferences()->defaultPlotFontSize() ); + setFontSize( defaultFontSize ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuGridPlotWindow::~RiuGridPlotWindow() +{ + if ( m_plotDefinition ) + { + m_plotDefinition->detachAllCurves(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGridPlotWindow* RiuGridPlotWindow::ownerPlotDefinition() +{ + return m_plotDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimViewWindow* RiuGridPlotWindow::ownerViewWindow() const +{ + return m_plotDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::addPlot( RiuQwtPlotWidget* plotWidget ) +{ + // Insert the plot to the left of the scroll bar + insertPlot( plotWidget, m_plotWidgets.size() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) +{ + m_plotWidgets.insert( static_cast( index ), plotWidget ); + + RiuQwtPlotLegend* legend = new RiuQwtPlotLegend( this ); + int legendColumns = 1; + if ( m_plotDefinition->legendsHorizontal() ) + { + legendColumns = 0; // unlimited + } + legend->setMaxColumns( legendColumns ); + legend->horizontalScrollBar()->setVisible( false ); + legend->verticalScrollBar()->setVisible( false ); + + legend->connect( plotWidget, + SIGNAL( legendDataChanged( const QVariant&, const QList& ) ), + SLOT( updateLegend( const QVariant&, const QList& ) ) ); + + legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter ); + plotWidget->updateLegend(); + m_legends.insert( static_cast( index ), legend ); + m_legendColumns.insert( static_cast( index ), -1 ); + scheduleUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::removePlot( RiuQwtPlotWidget* plotWidget ) +{ + if ( !plotWidget ) return; + + int plotWidgetIdx = m_plotWidgets.indexOf( plotWidget ); + CVF_ASSERT( plotWidgetIdx >= 0 ); + + m_plotWidgets.removeAt( plotWidgetIdx ); + plotWidget->setParent( nullptr ); + + RiuQwtPlotLegend* legend = m_legends[plotWidgetIdx]; + m_legends.removeAt( plotWidgetIdx ); + m_legendColumns.removeAt( plotWidgetIdx ); + delete legend; + + scheduleUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::setPlotTitle( const QString& plotTitle ) +{ + m_plotTitle->setText( plotTitle ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuGridPlotWindow::preferredWidth() const +{ + int titleWidth = 0; + if ( m_plotTitle && m_plotTitle->isVisible() ) + { + titleWidth = m_plotTitle->width(); + } + + QList> visiblePlotWidgets = this->visiblePlotWidgets(); + auto rowAndColumnCount = this->rowAndColumnCount( visiblePlotWidgets.size() ); + + int sumColumnWidths = 0; + for ( int visibleIndex = 0; visibleIndex < rowAndColumnCount.second; ++visibleIndex ) + { + sumColumnWidths += visiblePlotWidgets[visibleIndex]->width(); + } + return std::max( titleWidth, sumColumnWidths ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::setTitleVisible( bool visible ) +{ + m_plotTitle->setVisible( visible ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::setScrollbarVisible( bool visible ) +{ + m_scrollBar->setVisible( visible ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::setSelectionsVisible( bool visible ) +{ + for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets ) + { + if ( !visible ) + { + plotWidget->setDefaultStyleSheet( false ); + } + else + { + plotWidget->setSelected( caf::SelectionManager::instance()->isSelected( plotWidget->plotOwner(), 0 ) ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::setFontSize( int fontSize ) +{ + QFont font = m_plotTitle->font(); + + font.setPointSize( fontSize + 1 ); + font.setBold( true ); + m_plotTitle->setFont( font ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuGridPlotWindow::fontSize() const +{ + return m_plotTitle->font().pointSize() - 1; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuGridPlotWindow::indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) +{ + return m_plotWidgets.indexOf( plotWidget ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::scheduleUpdate() +{ + RiaPlotWindowRedrawScheduler::instance()->schedulePlotWindowUpdate( this ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::scheduleReplotOfAllPlots() +{ + for ( RiuQwtPlotWidget* plotWidget : visiblePlotWidgets() ) + { + plotWidget->scheduleReplot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::contextMenuEvent( QContextMenuEvent* event ) +{ + QMenu menu; + caf::CmdFeatureMenuBuilder menuBuilder; + + caf::SelectionManager::instance()->setSelectedItem( ownerPlotDefinition() ); + + menuBuilder << "RicShowPlotDataFeature"; + menuBuilder << "RicShowContributingWellsFromPlotFeature"; + + menuBuilder.appendToMenu( &menu ); + + if ( menu.actions().size() > 0 ) + { + menu.exec( event->globalPos() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::keyPressEvent( QKeyEvent* keyEvent ) +{ + m_plotDefinition->handleKeyPressEvent( keyEvent ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QLabel* RiuGridPlotWindow::createTitleLabel() const +{ + QLabel* plotTitle = new QLabel( "PLOT TITLE HERE", nullptr ); + plotTitle->setVisible( m_plotDefinition->isPlotTitleVisible() ); + plotTitle->setAlignment( Qt::AlignHCenter ); + plotTitle->setWordWrap( true ); + plotTitle->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + return plotTitle; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::resizeEvent( QResizeEvent* event ) +{ + QWidget::resizeEvent( event ); + bool needsUpdate = false; + for ( int i = 0; i < m_legends.size(); ++i ) + { + if ( m_legends[i]->isVisible() ) + { + int columnCount = m_legends[i]->columnCount(); + if ( columnCount != m_legendColumns[i] ) + { + int oldColumnCount = m_legendColumns[i]; + m_legendColumns[i] = columnCount; + if ( oldColumnCount != -1 ) + { + needsUpdate = true; + } + } + } + } + if ( needsUpdate ) + { + performUpdate(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::showEvent( QShowEvent* event ) +{ + QWidget::showEvent( event ); + performUpdate(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::dragEnterEvent( QDragEnterEvent* event ) +{ + if ( this->geometry().contains( event->pos() ) ) + { + event->acceptProposedAction(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::dragMoveEvent( QDragMoveEvent* event ) +{ + if ( this->geometry().contains( event->pos() ) ) + { + RiuQwtPlotWidget* source = dynamic_cast( event->source() ); + if ( source ) + { + QRect originalGeometry = source->geometry(); + QPoint offset = source->dragStartPosition(); + QRect newRect( event->pos() - offset, originalGeometry.size() ); + + QList> visiblePlotWidgets = this->visiblePlotWidgets(); + + int insertBeforeIndex = visiblePlotWidgets.size(); + for ( int visibleIndex = 0; visibleIndex < visiblePlotWidgets.size(); ++visibleIndex ) + { + visiblePlotWidgets[visibleIndex]->setDefaultStyleSheet(); + + if ( visiblePlotWidgets[visibleIndex]->frameIsInFrontOfThis( newRect ) ) + { + insertBeforeIndex = std::min( insertBeforeIndex, visibleIndex ); + } + } + if ( insertBeforeIndex >= 0 && insertBeforeIndex < visiblePlotWidgets.size() ) + { + visiblePlotWidgets[insertBeforeIndex]->setStyleSheetForThisObject( + "border-left: 2px solid red; border-top: none; border-bottom: none; border-right: none;" ); + } + + if ( insertBeforeIndex > 0 ) + { + int insertAfterIndex = insertBeforeIndex - 1; + visiblePlotWidgets[insertAfterIndex]->setStyleSheetForThisObject( + "border-left: none; border-top: none; border-bottom: none; border-right: 2px solid red;" ); + } + event->acceptProposedAction(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::dragLeaveEvent( QDragLeaveEvent* event ) +{ + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + m_plotWidgets[tIdx]->setDefaultStyleSheet(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::dropEvent( QDropEvent* event ) +{ + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + m_plotWidgets[tIdx]->setDefaultStyleSheet(); + } + + if ( this->geometry().contains( event->pos() ) ) + { + RiuQwtPlotWidget* source = dynamic_cast( event->source() ); + + if ( source ) + { + event->acceptProposedAction(); + + QRect originalGeometry = source->geometry(); + QPoint offset = source->dragStartPosition(); + QRect newRect( event->pos() - offset, originalGeometry.size() ); + + int beforeIndex = m_plotWidgets.size(); + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + if ( m_plotWidgets[tIdx]->isVisible() ) + { + if ( m_plotWidgets[tIdx]->frameIsInFrontOfThis( newRect ) ) + { + beforeIndex = tIdx; + break; + } + } + } + RimPlotInterface* insertAfter = nullptr; + if ( beforeIndex > 0 ) + { + insertAfter = m_plotWidgets[beforeIndex - 1]->plotDefinition(); + } + + RimPlotInterface* plotWidget = source->plotDefinition(); + + if ( insertAfter != plotWidget ) + { + RicWellLogPlotTrackFeatureImpl::movePlotsToGridPlotWindow( m_plotDefinition, { plotWidget }, insertAfter ); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RiuGridPlotWindow::rowAndColumnCount( int plotWidgetCount ) const +{ + int columnCount = std::max( 1, std::min( m_plotDefinition->columnCount(), plotWidgetCount ) ); + int rowCount = static_cast( std::ceil( plotWidgetCount / static_cast( columnCount ) ) ); + return std::make_pair( rowCount, columnCount ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) +{ + for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets ) + { + bool isSelected = false; + for ( int changedLevel : changedSelectionLevels ) + { + isSelected = isSelected || + caf::SelectionManager::instance()->isSelected( plotWidget->plotOwner(), changedLevel ); + } + plotWidget->setSelected( isSelected ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::performUpdate() +{ + reinsertPlotWidgetsAndScrollbar(); + alignCanvasTopsAndScrollbar(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::alignCanvasTopsAndScrollbar() +{ + CVF_ASSERT( m_legends.size() == m_plotWidgets.size() ); + + QList> plotWidgets = visiblePlotWidgets(); + if ( plotWidgets.empty() ) return; + + auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); + + std::vector maxExtents( rowAndColumnCount.first, 0.0 ); + + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) + { + int row = visibleIndex / rowAndColumnCount.second; + + QFont font = m_plotWidgets[visibleIndex]->axisFont( QwtPlot::xTop ); + maxExtents[row] = std::max( maxExtents[row], + plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->extent( font ) ); + } + + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) + { + int row = visibleIndex / rowAndColumnCount.second; + plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( maxExtents[row] ); + } + m_scrollBarLayout->setContentsMargins( 0, maxExtents[0], 0, 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::reinsertPlotWidgetsAndScrollbar() +{ + clearGridLayout(); + + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + m_plotWidgets[tIdx]->hide(); + m_legends[tIdx]->hide(); + } + + QList> plotWidgets = this->visiblePlotWidgets(); + QList> legends = this->visibleLegends(); + + auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() ); + + for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex ) + { + int row = visibleIndex / rowAndColumnCount.second; + int column = visibleIndex % rowAndColumnCount.second; + + m_gridLayout->addWidget( legends[visibleIndex], 2 * row, column ); + m_gridLayout->addWidget( plotWidgets[visibleIndex], 2 * row + 1, column ); + + if ( m_plotDefinition->legendsVisible() ) + { + int legendColumns = 1; + if ( m_plotDefinition->legendsHorizontal() ) + { + legendColumns = 0; // unlimited + } + legends[visibleIndex]->setMaxColumns( legendColumns ); + int minimumHeight = legends[visibleIndex]->heightForWidth( plotWidgets[visibleIndex]->width() ); + legends[visibleIndex]->setMinimumHeight( minimumHeight ); + QFont legendFont = legends[visibleIndex]->font(); + legendFont.setPointSize( fontSize() - 1 ); + legends[visibleIndex]->setFont( legendFont ); + legends[visibleIndex]->show(); + } + else + { + legends[visibleIndex]->hide(); + } + + plotWidgets[visibleIndex]->setYAxisLabelsAndTicksEnabled( column == 0 ); + plotWidgets[visibleIndex]->setYTitleEnabled( column == 0 ); + + plotWidgets[visibleIndex]->show(); + + int widthScaleFactor = plotWidgets[visibleIndex]->widthScaleFactor(); + if ( column == 0 ) + { + widthScaleFactor += 1; // Give it a bit extra room due to axis + } + m_gridLayout->setColumnStretch( column, + std::max( m_gridLayout->columnStretch( column ), + plotWidgets[visibleIndex]->widthScaleFactor() ) ); + m_gridLayout->setRowStretch( 2 * row + 1, 1 ); + } + m_gridLayout->addLayout( m_scrollBarLayout, 1, rowAndColumnCount.second, rowAndColumnCount.first * 2 - 1, 1 ); + m_gridLayout->setColumnStretch( rowAndColumnCount.second, 0 ); + m_scrollBar->setVisible( plotWidgets.size() > 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuGridPlotWindow::clearGridLayout() +{ + if ( m_gridLayout ) + { + for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx ) + { + m_gridLayout->removeWidget( m_legends[tIdx] ); + m_gridLayout->removeWidget( m_plotWidgets[tIdx] ); + } + + QLayoutItem* item; + while ( ( item = m_gridLayout->takeAt( 0 ) ) != 0 ) + { + } + QWidget().setLayout( m_gridLayout ); + delete m_gridLayout; + m_gridLayout = new QGridLayout( m_plotWidgetFrame ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList> RiuGridPlotWindow::visiblePlotWidgets() const +{ + QList> plotWidgets; + for ( QPointer plotWidget : m_plotWidgets ) + { + if ( plotWidget->isChecked() ) + { + plotWidgets.push_back( plotWidget ); + } + } + return plotWidgets; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList> RiuGridPlotWindow::visibleLegends() const +{ + QList> legends; + for ( int i = 0; i < m_plotWidgets.size(); ++i ) + { + if ( m_plotWidgets[i]->isChecked() ) + { + legends.push_back( m_legends[i] ); + } + } + return legends; +} diff --git a/ApplicationCode/UserInterface/RiuGridPlotWindow.h b/ApplicationCode/UserInterface/RiuGridPlotWindow.h new file mode 100644 index 0000000000..657e9aa393 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuGridPlotWindow.h @@ -0,0 +1,124 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RiuInterfaceToViewWindow.h" + +#include "cafPdmPointer.h" +#include "cafSelectionChangedReceiver.h" + +#include +#include +#include +#include +#include +#include + +#include + +class RiaPlotWindowRedrawScheduler; +class RimGridPlotWindow; +class RiuQwtPlotLegend; +class RiuQwtPlotWidget; + +class QFocusEvent; +class QLabel; +class QScrollBar; + +//================================================================================================== +// +// RiuGridPlotWindow +// +//================================================================================================== +class RiuGridPlotWindow : public QWidget, public RiuInterfaceToViewWindow, public caf::SelectionChangedReceiver +{ + Q_OBJECT + +public: + RiuGridPlotWindow( RimGridPlotWindow* plotDefinition, QWidget* parent = nullptr ); + + ~RiuGridPlotWindow() override; + + RimGridPlotWindow* ownerPlotDefinition(); + RimViewWindow* ownerViewWindow() const override; + + void addPlot( RiuQwtPlotWidget* plotWidget ); + void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ); + void removePlot( RiuQwtPlotWidget* plotWidget ); + + void setPlotTitle( const QString& plotTitle ); + int preferredWidth() const; + + void setTitleVisible( bool visible ); + void setScrollbarVisible( bool visible ); + void setSelectionsVisible( bool visible ); + + void setFontSize( int fontSize ); + int fontSize() const; + + int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ); + + void scheduleUpdate(); + void scheduleReplotOfAllPlots(); + virtual void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) {} + +protected: + void contextMenuEvent( QContextMenuEvent* ) override; + void keyPressEvent( QKeyEvent* keyEvent ) override; + QLabel* createTitleLabel() const; + + void resizeEvent( QResizeEvent* event ) override; + void showEvent( QShowEvent* event ) override; + void dragEnterEvent( QDragEnterEvent* event ) override; + void dragMoveEvent( QDragMoveEvent* event ) override; + void dragLeaveEvent( QDragLeaveEvent* event ) override; + void dropEvent( QDropEvent* event ) override; + + std::pair rowAndColumnCount( int plotWidgetCount ) const; + + virtual void onSelectionManagerSelectionChanged( const std::set& changedSelectionLevels ) override; + +private slots: + void performUpdate(); + +private: + void alignCanvasTopsAndScrollbar(); + void reinsertPlotWidgetsAndScrollbar(); + void clearGridLayout(); + + QList> visiblePlotWidgets() const; + QList> visibleLegends() const; + +protected: + QPointer m_layout; + QPointer m_plotLayout; + QPointer m_plotWidgetFrame; + QPointer m_gridLayout; + QPointer m_plotTitle; + QPointer m_scrollBarLayout; + QScrollBar* m_scrollBar; + QList> m_legends; + QList m_legendColumns; + QList> m_plotWidgets; + caf::PdmPointer m_plotDefinition; + +private: + friend class RiaPlotWindowRedrawScheduler; +}; diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp index 6436f40a26..eb3e6ba3a2 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.cpp @@ -206,6 +206,35 @@ void RiuMainWindowBase::selectAsCurrentItem( const caf::PdmObject* object, bool m_allowActiveViewChangeFromSelection = true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::toggleItemInSelection( const caf::PdmObject* object, bool allowActiveViewChange ) +{ + m_allowActiveViewChangeFromSelection = allowActiveViewChange; + std::vector currentSelection; + m_projectTreeView->selectedUiItems( currentSelection ); + std::vector updatedSelection; + bool alreadySelected = false; + for ( caf::PdmUiItem* uiItem : currentSelection ) + { + if ( object == uiItem ) + { + alreadySelected = true; + } + else + { + updatedSelection.push_back( uiItem ); + } + } + if ( !alreadySelected ) + { + updatedSelection.push_back( object ); + } + m_projectTreeView->selectItems( updatedSelection ); + m_allowActiveViewChangeFromSelection = true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindowBase.h b/ApplicationCode/UserInterface/RiuMainWindowBase.h index 895bf24d73..679c24269a 100644 --- a/ApplicationCode/UserInterface/RiuMainWindowBase.h +++ b/ApplicationCode/UserInterface/RiuMainWindowBase.h @@ -67,6 +67,7 @@ public: void setExpanded( const caf::PdmUiItem* uiItem, bool expanded = true ); void selectAsCurrentItem( const caf::PdmObject* object, bool allowActiveViewChange = true ); + void toggleItemInSelection( const caf::PdmObject* object, bool allowActiveViewChange = true ); void enableShowFirstVisibleMdiWindowMaximized( bool enable ); diff --git a/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp b/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp index bbaec43e7e..058a480b4b 100644 --- a/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMdiSubWindow.cpp @@ -27,7 +27,6 @@ #include "RiuMainWindow.h" #include "RiuPlotMainWindow.h" #include "RiuViewer.h" -#include "RiuWellLogPlot.h" #include diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp index 6a9744c539..0b1487903a 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindow.cpp @@ -37,11 +37,11 @@ #include "RiuDockWidgetTools.h" #include "RiuDragDrop.h" +#include "RiuGridPlotWindow.h" #include "RiuMdiSubWindow.h" #include "RiuToolTipMenu.h" #include "RiuTreeViewEventFilter.h" #include "RiuWellAllocationPlot.h" -#include "RiuWellLogPlot.h" #include "cafCmdFeatureManager.h" #include "cafPdmObjectHandle.h" @@ -606,7 +606,7 @@ void RiuPlotMainWindow::addViewer( QWidget* viewer, const RimMdiWindowGeometry& } else { - RiuWellLogPlot* wellLogPlot = dynamic_cast( viewer ); + RiuGridPlotWindow* wellLogPlot = dynamic_cast( viewer ); if ( wellLogPlot ) { subWindowSize = QSize( wellLogPlot->preferredWidth(), m_mdiArea->height() ); diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp index c2963eb335..d0f0bbd838 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp +++ b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.cpp @@ -70,6 +70,19 @@ void RiuPlotMainWindowTools::selectAsCurrentItem( const caf::PdmObject* object, } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuPlotMainWindowTools::toggleItemInSelection( const caf::PdmObject* object, bool allowActiveViewChange /*= true*/ ) +{ + if ( RiaGuiApplication::isRunning() ) + { + RiuPlotMainWindow* mpw = RiaGuiApplication::instance()->mainPlotWindow(); + + if ( mpw ) mpw->toggleItemInSelection( object, allowActiveViewChange ); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.h b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.h index 5b8bb22389..0cd9aa5f4c 100644 --- a/ApplicationCode/UserInterface/RiuPlotMainWindowTools.h +++ b/ApplicationCode/UserInterface/RiuPlotMainWindowTools.h @@ -33,5 +33,6 @@ public: static void setActiveViewer( QWidget* subWindow ); static void setExpanded( const caf::PdmUiItem* uiItem, bool expanded = true ); static void selectAsCurrentItem( const caf::PdmObject* object, bool allowActiveViewChange = true ); + static void toggleItemInSelection( const caf::PdmObject* object, bool allowActiveViewChange = true ); static void refreshToolbars(); }; diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.cpp b/ApplicationCode/UserInterface/RiuQwtPlot.cpp deleted file mode 100644 index 17843fc9e4..0000000000 --- a/ApplicationCode/UserInterface/RiuQwtPlot.cpp +++ /dev/null @@ -1,350 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2016- Statoil ASA -// -// ResInsight is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#include "RiuQwtPlot.h" - -#include "RiaColorTools.h" - -#include "RimProject.h" - -#include "RiuPlotMainWindowTools.h" -#include "RiuQwtCurvePointTracker.h" -#include "RiuQwtPlotTools.h" -#include "RiuQwtPlotWheelZoomer.h" -#include "RiuQwtPlotZoomer.h" -#include "RiuQwtScalePicker.h" - -#include "qwt_date_scale_draw.h" -#include "qwt_date_scale_engine.h" -#include "qwt_legend.h" -#include "qwt_plot_curve.h" -#include "qwt_plot_grid.h" -#include "qwt_plot_layout.h" -#include "qwt_plot_magnifier.h" -#include "qwt_plot_marker.h" -#include "qwt_plot_panner.h" -#include "qwt_plot_zoomer.h" -#include "qwt_scale_engine.h" -#include "qwt_symbol.h" - -#include -#include -#include - -#include - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuQwtPlot::RiuQwtPlot( RimViewWindow* viewWindow, QWidget* parent ) - : QwtPlot( parent ) -{ - Q_ASSERT( viewWindow ); - m_ownerViewWindow = viewWindow; - - // LeftButton for the zooming - m_zoomerLeft = new RiuQwtPlotZoomer( canvas() ); - m_zoomerLeft->setRubberBandPen( QColor( Qt::black ) ); - m_zoomerLeft->setTrackerMode( QwtPicker::AlwaysOff ); - m_zoomerLeft->setTrackerPen( QColor( Qt::black ) ); - m_zoomerLeft->initMousePattern( 1 ); - - // Attach a zoomer for the right axis - m_zoomerRight = new RiuQwtPlotZoomer( canvas() ); - m_zoomerRight->setAxis( xTop, yRight ); - m_zoomerRight->setTrackerMode( QwtPicker::AlwaysOff ); - m_zoomerRight->initMousePattern( 1 ); - - // MidButton for the panning - QwtPlotPanner* panner = new QwtPlotPanner( canvas() ); - panner->setMouseButton( Qt::MidButton ); - - auto wheelZoomer = new RiuQwtPlotWheelZoomer( this ); - - connect( wheelZoomer, SIGNAL( zoomUpdated() ), SLOT( onZoomedSlot() ) ); - connect( m_zoomerLeft, SIGNAL( zoomed( const QRectF& ) ), SLOT( onZoomedSlot() ) ); - connect( panner, SIGNAL( panned( int, int ) ), SLOT( onZoomedSlot() ) ); - - RiuQwtScalePicker* scalePicker = new RiuQwtScalePicker( this ); - connect( scalePicker, SIGNAL( clicked( int, double ) ), this, SLOT( onAxisClicked( int, double ) ) ); - - RiuQwtPlotTools::setCommonPlotBehaviour( this ); - RiuQwtPlotTools::setDefaultAxes( this ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuQwtPlot::~RiuQwtPlot() -{ - if ( ownerPlotDefinition() ) - { - ownerPlotDefinition()->detachAllCurves(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimRiuQwtPlotOwnerInterface* RiuQwtPlot::ownerPlotDefinition() const -{ - RimRiuQwtPlotOwnerInterface* plotDefinition = dynamic_cast( ownerViewWindow() ); - return plotDefinition; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimViewWindow* RiuQwtPlot::ownerViewWindow() const -{ - return m_ownerViewWindow; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuQwtPlot::minimumSizeHint() const -{ - return QSize( 0, 100 ); -} - -//-------------------------------------------------------------------------------------------------- -/// Empty default implementation -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::selectSample( QwtPlotCurve* curve, int sampleNumber ) {} - -//-------------------------------------------------------------------------------------------------- -/// Empty default implementation -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::clearSampleSelection() {} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::hideEvent( QHideEvent* event ) -{ - resetCurveHighlighting(); - QwtPlot::hideEvent( event ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuQwtPlot::sizeHint() const -{ - return QSize( 0, 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QwtInterval RiuQwtPlot::currentAxisRange( QwtPlot::Axis axis ) -{ - return axisScaleDiv( axis ).interval(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuQwtPlot::eventFilter( QObject* watched, QEvent* event ) -{ - if ( watched == canvas() ) - { - QMouseEvent* mouseEvent = dynamic_cast( event ); - if ( mouseEvent ) - { - if ( mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease ) - { - bool anyZoomingActive = false; - - if ( m_zoomerLeft && m_zoomerLeft->isActiveAndValid() ) - { - anyZoomingActive = true; - } - - if ( m_zoomerRight && m_zoomerRight->isActiveAndValid() ) - { - anyZoomingActive = true; - } - - if ( !anyZoomingActive ) - { - selectClosestCurve( mouseEvent->pos() ); - } - } - } - } - - return QwtPlot::eventFilter( watched, event ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::selectClosestCurve( const QPoint& pos ) -{ - QwtPlotCurve* closestCurve = nullptr; - double distMin = DBL_MAX; - int closestCurvePoint = -1; - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++ ) - { - if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) - { - QwtPlotCurve* candidateCurve = static_cast( *it ); - double dist = DBL_MAX; - int curvePoint = candidateCurve->closestPoint( pos, &dist ); - if ( dist < distMin ) - { - closestCurve = candidateCurve; - distMin = dist; - closestCurvePoint = curvePoint; - } - } - } - - resetCurveHighlighting(); - if ( closestCurve && distMin < 20 ) - { - CVF_ASSERT( closestCurvePoint >= 0 ); - caf::PdmObject* selectedPlotObject = ownerPlotDefinition()->findRimPlotObjectFromQwtCurve( closestCurve ); - - if ( selectedPlotObject ) - { - RimProject* proj = nullptr; - selectedPlotObject->firstAncestorOrThisOfType( proj ); - - if ( proj ) - { - RiuPlotMainWindowTools::showPlotMainWindow(); - RiuPlotMainWindowTools::selectAsCurrentItem( selectedPlotObject ); - highlightCurve( closestCurve ); - } - } - } - - if ( closestCurve && distMin < 10 ) - { - selectSample( closestCurve, closestCurvePoint ); - } - else - { - clearSampleSelection(); - } - - replot(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::highlightCurve( const QwtPlotCurve* closestCurve ) -{ - // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list - // plotCurve->setZ() causes the ordering of items in the list to change - auto plotItemList = this->itemList(); - for ( QwtPlotItem* plotItem : plotItemList ) - { - QwtPlotCurve* plotCurve = dynamic_cast( plotItem ); - if ( plotCurve ) - { - QPen existingPen = plotCurve->pen(); - QColor bgColor = this->canvasBackground().color(); - - QColor curveColor = existingPen.color(); - QColor symbolColor; - QColor symbolLineColor; - - QwtSymbol* symbol = const_cast( plotCurve->symbol() ); - if ( symbol ) - { - symbolColor = symbol->brush().color(); - symbolLineColor = symbol->pen().color(); - } - - double zValue = plotCurve->z(); - if ( plotCurve == closestCurve ) - { - plotCurve->setZ( zValue + 100.0 ); - } - else - { - QColor blendedColor = RiaColorTools::blendQColors( bgColor, curveColor, 3, 1 ); - QColor blendedSymbolColor = RiaColorTools::blendQColors( bgColor, symbolColor, 3, 1 ); - QColor blendedSymbolLineColor = RiaColorTools::blendQColors( bgColor, symbolLineColor, 3, 1 ); - - plotCurve->setPen( blendedColor, existingPen.width(), existingPen.style() ); - if ( symbol ) - { - symbol->setColor( blendedSymbolColor ); - symbol->setPen( blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style() ); - } - } - CurveColors curveColors = {curveColor, symbolColor, symbolLineColor}; - m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) ); - m_originalZValues.insert( std::make_pair( plotCurve, zValue ) ); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::resetCurveHighlighting() -{ - // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list - // plotCurve->setZ() causes the ordering of items in the list to change - auto plotItemList = this->itemList(); - for ( QwtPlotItem* plotItem : plotItemList ) - { - QwtPlotCurve* plotCurve = dynamic_cast( plotItem ); - if ( plotCurve && m_originalCurveColors.count( plotCurve ) ) - { - const QPen& existingPen = plotCurve->pen(); - auto colors = m_originalCurveColors[plotCurve]; - double zValue = m_originalZValues[plotCurve]; - - plotCurve->setPen( colors.lineColor, existingPen.width(), existingPen.style() ); - plotCurve->setZ( zValue ); - QwtSymbol* symbol = const_cast( plotCurve->symbol() ); - if ( symbol ) - { - symbol->setColor( colors.symbolColor ); - symbol->setPen( colors.symbolLineColor, symbol->pen().width(), symbol->pen().style() ); - } - } - } - m_originalCurveColors.clear(); - m_originalZValues.clear(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::onZoomedSlot() -{ - ownerPlotDefinition()->updateZoomWindowFromQwt(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuQwtPlot::onAxisClicked( int axis, double value ) -{ - ownerPlotDefinition()->selectAxisInPropertyEditor( axis ); -} diff --git a/ApplicationCode/UserInterface/RiuQwtPlot.h b/ApplicationCode/UserInterface/RiuQwtPlot.h deleted file mode 100644 index 3d3faa32fd..0000000000 --- a/ApplicationCode/UserInterface/RiuQwtPlot.h +++ /dev/null @@ -1,92 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2016- Statoil ASA -// -// ResInsight is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "RiuInterfaceToViewWindow.h" - -#include "RimRiuQwtPlotOwnerInterface.h" - -#include "cafPdmPointer.h" - -#include "qwt_plot.h" - -#include - -class RiuQwtPlotZoomer; - -class QwtPlotCurve; -class QwtPlotGrid; -class QwtInterval; -class QwtPicker; -class QwtPlotMarker; -class QwtScaleWidget; - -//================================================================================================== -// -// -// -//================================================================================================== -class RiuQwtPlot : public QwtPlot, public RiuInterfaceToViewWindow -{ - Q_OBJECT; - -public: - RiuQwtPlot( RimViewWindow* viewWindow, QWidget* parent = nullptr ); - ~RiuQwtPlot() override; - - RimRiuQwtPlotOwnerInterface* ownerPlotDefinition() const; - RimViewWindow* ownerViewWindow() const override; - - QwtInterval currentAxisRange( QwtPlot::Axis axis ); - -protected: - bool eventFilter( QObject* watched, QEvent* event ) override; - - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - - virtual void selectSample( QwtPlotCurve* curve, int sampleNumber ); - virtual void clearSampleSelection(); - - virtual void hideEvent( QHideEvent* event ) override; - -private: - void selectClosestCurve( const QPoint& pos ); - - void highlightCurve( const QwtPlotCurve* closestCurve ); - void resetCurveHighlighting(); -private slots: - void onZoomedSlot(); - void onAxisClicked( int axis, double value ); - -private: - struct CurveColors - { - QColor lineColor; - QColor symbolColor; - QColor symbolLineColor; - }; - caf::PdmPointer m_ownerViewWindow; - - QPointer m_zoomerLeft; - QPointer m_zoomerRight; - - std::map m_originalCurveColors; - std::map m_originalZValues; -}; diff --git a/ApplicationCode/ProjectDataModel/RimPlot.cpp b/ApplicationCode/UserInterface/RiuQwtPlotLegend.cpp similarity index 57% rename from ApplicationCode/ProjectDataModel/RimPlot.cpp rename to ApplicationCode/UserInterface/RiuQwtPlotLegend.cpp index 8f0ecb5467..1a008193c7 100644 --- a/ApplicationCode/ProjectDataModel/RimPlot.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlotLegend.cpp @@ -15,22 +15,41 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// -#include "RimPlot.h" +#include "RiuQwtPlotLegend.h" -CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimPlot, "RimPlot" ); // Do not use. Abstract class +#include "qwt_dyngrid_layout.h" + +#include + +#include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimPlot::RimPlot() +RiuQwtPlotLegend::RiuQwtPlotLegend( QWidget* parent /*= nullptr */ ) + : QwtLegend( parent ) + , m_columnCount( -1 ) { - CAF_PDM_InitObject( "Plot", "", "", "" ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QWidget* RimPlot::createPlotWidget() +void RiuQwtPlotLegend::resizeEvent( QResizeEvent* event ) { - return createViewWidget( nullptr ); + QWidget::resizeEvent( event ); + QSize size = event->size(); + const QwtDynGridLayout* legendLayout = qobject_cast( contentsWidget()->layout() ); + if ( legendLayout ) + { + m_columnCount = legendLayout->columnsForWidth( size.width() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuQwtPlotLegend::columnCount() const +{ + return m_columnCount; } diff --git a/ApplicationCode/ProjectDataModel/RimPlot.h b/ApplicationCode/UserInterface/RiuQwtPlotLegend.h similarity index 76% rename from ApplicationCode/ProjectDataModel/RimPlot.h rename to ApplicationCode/UserInterface/RiuQwtPlotLegend.h index 65f8113b68..b8f9836d9a 100644 --- a/ApplicationCode/ProjectDataModel/RimPlot.h +++ b/ApplicationCode/UserInterface/RiuQwtPlotLegend.h @@ -17,15 +17,16 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once -#include "RimNameConfig.h" -#include "RimViewWindow.h" +#include "qwt_legend.h" -class RimPlot : public RimViewWindow +class RiuQwtPlotLegend : public QwtLegend { - CAF_PDM_HEADER_INIT; - + Q_OBJECT public: - RimPlot(); + RiuQwtPlotLegend( QWidget* parent = nullptr ); + void resizeEvent( QResizeEvent* event ); + int columnCount() const; - QWidget* createPlotWidget(); +private: + mutable int m_columnCount; }; diff --git a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp index 830d47f473..af095b8546 100644 --- a/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp +++ b/ApplicationCode/UserInterface/RiuQwtPlotTools.cpp @@ -25,7 +25,9 @@ #include "qwt_plot.h" #include "qwt_plot_grid.h" #include "qwt_plot_layout.h" +#include "qwt_scale_widget.h" +#include #include #include @@ -43,11 +45,15 @@ void RiuQwtPlotTools::setCommonPlotBehaviour( QwtPlot* plot ) plot->setAutoFillBackground( true ); plot->setCanvasBackground( Qt::white ); + plot->canvas()->setContentsMargins( 1, 1, 1, 1 ); QFrame* canvasFrame = dynamic_cast( plot->canvas() ); - if ( canvasFrame ) - { - canvasFrame->setFrameShape( QFrame::NoFrame ); - } + canvasFrame->setFrameShape( QFrame::Box ); + + QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect( plot->canvas() ); + dropShadowEffect->setOffset( 1.0, 1.0 ); + dropShadowEffect->setBlurRadius( 3.0 ); + dropShadowEffect->setColor( QColor( 60, 60, 60, 60 ) ); + plot->canvas()->setGraphicsEffect( dropShadowEffect ); // Grid @@ -57,9 +63,11 @@ void RiuQwtPlotTools::setCommonPlotBehaviour( QwtPlot* plot ) gridPen.setColor( Qt::lightGray ); grid->setPen( gridPen ); + int fontSize = RiaFontCache::pointSizeFromFontSizeEnum( + RiaApplication::instance()->preferences()->defaultPlotFontSize() ); // Axis number font QFont axisFont = plot->axisFont( QwtPlot::xBottom ); - axisFont.setPointSize( 10 ); + axisFont.setPointSize( fontSize ); plot->setAxisFont( QwtPlot::xBottom, axisFont ); plot->setAxisFont( QwtPlot::xTop, axisFont ); @@ -67,13 +75,13 @@ void RiuQwtPlotTools::setCommonPlotBehaviour( QwtPlot* plot ) plot->setAxisFont( QwtPlot::yRight, axisFont ); // Axis title font - std::vector axes = {QwtPlot::xBottom, QwtPlot::xTop, QwtPlot::yLeft, QwtPlot::yRight}; + std::vector axes = { QwtPlot::xBottom, QwtPlot::xTop, QwtPlot::yLeft, QwtPlot::yRight }; for ( QwtPlot::Axis axis : axes ) { QwtText axisTitle = plot->axisTitle( axis ); QFont axisTitleFont = axisTitle.font(); - axisTitleFont.setPointSize( 10 ); + axisTitleFont.setPointSize( fontSize ); axisTitleFont.setBold( false ); axisTitle.setFont( axisTitleFont ); axisTitle.setRenderFlags( Qt::AlignRight ); @@ -89,10 +97,16 @@ void RiuQwtPlotTools::setCommonPlotBehaviour( QwtPlot* plot ) // Enable mousetracking and event filter plot->canvas()->setMouseTracking( true ); - plot->canvas()->installEventFilter( plot ); plot->plotLayout()->setAlignCanvasToScales( true ); - plot->setContentsMargins( 4, 4, 4, 4 ); + plot->setContentsMargins( 2, 2, 2, 2 ); + + // Store the pointer address as an object name. This way each plot can be identified uniquely for CSS-stylesheets + QString objectName = QString( "%1" ).arg( reinterpret_cast( plot ) ); + plot->setObjectName( objectName ); + + QString canvasName = QString( "%1" ).arg( reinterpret_cast( plot->canvas() ) ); + plot->canvas()->setObjectName( canvasName ); } //-------------------------------------------------------------------------------------------------- @@ -105,6 +119,11 @@ void RiuQwtPlotTools::setDefaultAxes( QwtPlot* plot ) plot->enableAxis( QwtPlot::xTop, false ); plot->enableAxis( QwtPlot::yRight, false ); + plot->axisScaleDraw( QwtPlot::xBottom )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); + plot->axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); + plot->axisWidget( QwtPlot::xBottom )->setMargin( 0 ); + plot->axisWidget( QwtPlot::yLeft )->setMargin( 0 ); + plot->setAxisMaxMinor( QwtPlot::xBottom, 2 ); plot->setAxisMaxMinor( QwtPlot::yLeft, 3 ); } @@ -120,14 +139,14 @@ void RiuQwtPlotTools::enableDateBasedBottomXAxis( QwtPlot* { QwtDateScaleDraw* scaleDraw = new QwtDateScaleDraw( Qt::UTC ); - std::set intervals = {QwtDate::Year, - QwtDate::Month, - QwtDate::Week, - QwtDate::Day, - QwtDate::Hour, - QwtDate::Minute, - QwtDate::Second, - QwtDate::Millisecond}; + std::set intervals = { QwtDate::Year, + QwtDate::Month, + QwtDate::Week, + QwtDate::Day, + QwtDate::Hour, + QwtDate::Minute, + QwtDate::Second, + QwtDate::Millisecond }; for ( QwtDate::IntervalType interval : intervals ) { diff --git a/ApplicationCode/UserInterface/RiuQwtPlotWidget.cpp b/ApplicationCode/UserInterface/RiuQwtPlotWidget.cpp new file mode 100644 index 0000000000..f2a4f832b2 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuQwtPlotWidget.cpp @@ -0,0 +1,830 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RiuQwtPlotWidget.h" + +#include "RiaApplication.h" +#include "RiaColorTools.h" +#include "RiaPlotWindowRedrawScheduler.h" + +#include "RimPlotCurve.h" +#include "RimPlotInterface.h" + +#include "RiuPlotMainWindowTools.h" +#include "RiuQwtCurvePointTracker.h" +#include "RiuQwtPlotTools.h" + +#include "RiuQwtLinearScaleEngine.h" +#include "RiuQwtScalePicker.h" + +#include "cafAssert.h" + +#include "qwt_legend.h" +#include "qwt_plot_curve.h" +#include "qwt_plot_grid.h" +#include "qwt_plot_layout.h" +#include "qwt_plot_marker.h" +#include "qwt_plot_picker.h" +#include "qwt_scale_draw.h" +#include "qwt_scale_widget.h" +#include "qwt_symbol.h" +#include "qwt_text.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuQwtPlotWidget::RiuQwtPlotWidget( RimPlotInterface* plotTrackDefinition, QWidget* parent ) + : QwtPlot( parent ) +{ + m_plotOwner = dynamic_cast( plotTrackDefinition ); + CAF_ASSERT( m_plotOwner ); + + setDefaults(); + + this->installEventFilter( this ); + this->canvas()->installEventFilter( this ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuQwtPlotWidget::~RiuQwtPlotWidget() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuQwtPlotWidget::isChecked() const +{ + if ( plotDefinition() ) + { + return plotDefinition()->isChecked(); + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuQwtPlotWidget::fontSize() const +{ + for ( int axisId = 0; axisId < QwtPlot::axisCnt; ++axisId ) + { + if ( this->axisEnabled( axisId ) ) + { + return this->axisFont( axisId ).pointSize(); + } + } + return -1; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setFontSize( int fontSize ) +{ + // Axis number font + QFont axisFont = this->axisFont( QwtPlot::xBottom ); + axisFont.setPointSize( fontSize ); + + setAxisFont( QwtPlot::xBottom, axisFont ); + setAxisFont( QwtPlot::xTop, axisFont ); + setAxisFont( QwtPlot::yLeft, axisFont ); + setAxisFont( QwtPlot::yRight, axisFont ); + + // Axis title font + std::vector axes = { QwtPlot::xBottom, QwtPlot::xTop, QwtPlot::yLeft, QwtPlot::yRight }; + + for ( QwtPlot::Axis axis : axes ) + { + QwtText axisTitle = this->axisTitle( axis ); + QFont axisTitleFont = axisTitle.font(); + axisTitleFont.setPointSize( fontSize ); + axisTitleFont.setBold( false ); + axisTitle.setFont( axisTitleFont ); + axisTitle.setRenderFlags( Qt::AlignRight ); + + setAxisTitle( axis, axisTitle ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotInterface* RiuQwtPlotWidget::plotDefinition() const +{ + return dynamic_cast( m_plotOwner.p() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RiuQwtPlotWidget::plotOwner() const +{ + return m_plotOwner.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setEnabledAxes( const std::set enabledAxes ) +{ + for ( int axisId = 0; axisId < QwtPlot::axisCnt; ++axisId ) + { + QwtPlot::Axis axis = static_cast( axisId ); + if ( enabledAxes.count( axis ) ) + { + enableAxis( axis, true ); + // Align the canvas with the actual min and max values of the curves + axisScaleEngine( axis )->setAttribute( QwtScaleEngine::Floating, true ); + setAxisScale( axis, 0.0, 100.0 ); + axisScaleDraw( axis )->setMinimumExtent( axisExtent( axis ) ); + setMinimumWidth( defaultMinimumWidth() ); + + axisScaleDraw( axis )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); + axisWidget( axis )->setMargin( 0 ); + } + else + { + enableAxis( axis, false ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setXTitle( const QString& title ) +{ + QwtText axisTitleX = axisTitle( QwtPlot::xTop ); + if ( title != axisTitleX.text() ) + { + axisTitleX.setText( title ); + setAxisTitle( QwtPlot::xTop, axisTitleX ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setYTitle( const QString& title ) +{ + m_yAxisTitle = title; + applyYTitleToQwt(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setYTitleEnabled( bool enable ) +{ + m_yAxisTitleEnabled = enable; + applyYTitleToQwt(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QwtInterval RiuQwtPlotWidget::axisRange( QwtPlot::Axis axis ) +{ + return axisScaleDiv( axis ).interval(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setXRange( double min, double max, QwtPlot::Axis axis ) +{ + setAxisScale( axis, min, max ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setYRange( double min, double max ) +{ + // Note: Y-axis may be inverted + if ( axisScaleEngine( QwtPlot::yLeft )->testAttribute( QwtScaleEngine::Inverted ) ) + { + setAxisScale( QwtPlot::yLeft, max, min ); + } + else + { + setAxisScale( QwtPlot::yLeft, min, max ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setAxisInverted( QwtPlot::Axis axis ) +{ + axisScaleEngine( axis )->setAttribute( QwtScaleEngine::Inverted, true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setYAxisLabelsAndTicksEnabled( bool enable ) +{ + this->axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Ticks, enable ); + this->axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Labels, enable ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::enableXGridLines( bool majorGridLines, bool minorGridLines ) +{ + QwtPlotItemList plotItems = this->itemList( QwtPlotItem::Rtti_PlotGrid ); + for ( QwtPlotItem* plotItem : plotItems ) + { + QwtPlotGrid* grid = static_cast( plotItem ); + grid->setXAxis( QwtPlot::xTop ); + grid->enableX( majorGridLines ); + grid->enableXMin( minorGridLines ); + grid->setMajorPen( Qt::lightGray, 1.0, Qt::SolidLine ); + grid->setMinorPen( Qt::lightGray, 1.0, Qt::DashLine ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::enableYGridLines( bool majorGridLines, bool minorGridLines ) +{ + QwtPlotItemList plotItems = this->itemList( QwtPlotItem::Rtti_PlotGrid ); + for ( QwtPlotItem* plotItem : plotItems ) + { + QwtPlotGrid* grid = static_cast( plotItem ); + grid->setYAxis( QwtPlot::yLeft ); + grid->enableY( majorGridLines ); + grid->enableYMin( minorGridLines ); + grid->setMajorPen( Qt::lightGray, 1.0, Qt::SolidLine ); + grid->setMinorPen( Qt::lightGray, 1.0, Qt::DashLine ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setMajorAndMinorTickIntervals( double majorTickInterval, + double minorTickInterval, + double minValue, + double maxValue, + QwtPlot::Axis axis /*= QwtPlot::xTop */ ) +{ + RiuQwtLinearScaleEngine* scaleEngine = dynamic_cast( this->axisScaleEngine( axis ) ); + if ( scaleEngine ) + { + QwtScaleDiv scaleDiv = scaleEngine->divideScaleWithExplicitIntervals( minValue, + maxValue, + majorTickInterval, + minorTickInterval ); + + this->setAxisScaleDiv( axis, scaleDiv ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setAutoTickIntervalCounts( int maxMajorTickIntervalCount, + int maxMinorTickIntervalCount, + QwtPlot::Axis axis ) +{ + this->setAxisMaxMajor( axis, maxMajorTickIntervalCount ); + this->setAxisMaxMinor( axis, maxMinorTickIntervalCount ); + // Reapply axis limits to force Qwt to use the tick settings. + QwtInterval currentRange = this->axisInterval( axis ); + setAxisScale( currentRange.minValue(), currentRange.maxValue(), axis ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiuQwtPlotWidget::getCurrentMajorTickInterval() const +{ + QwtScaleDiv scaleDiv = this->axisScaleDiv( QwtPlot::xTop ); + QList majorTicks = scaleDiv.ticks( QwtScaleDiv::MajorTick ); + if ( majorTicks.size() < 2 ) return 0.0; + + return majorTicks.at( 1 ) - majorTicks.at( 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiuQwtPlotWidget::getCurrentMinorTickInterval() const +{ + QwtScaleDiv scaleDiv = this->axisScaleDiv( QwtPlot::xTop ); + QList minorTicks = scaleDiv.ticks( QwtScaleDiv::MinorTick ); + if ( minorTicks.size() < 2 ) return 0.0; + + return minorTicks.at( 1 ) - minorTicks.at( 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuQwtPlotWidget::axisExtent( QwtPlot::Axis axis ) const +{ + QFont tickLabelFont = axisFont( axis ); + int lineExtent = static_cast( std::ceil( axisScaleDraw( axis )->extent( tickLabelFont ) ) ); + if ( !axisTitle( axis ).text().isEmpty() ) + { + QFont titleFont = axisTitle( axis ).font(); + lineExtent += QFontMetrics( titleFont ).height(); + } + return lineExtent; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuQwtPlotWidget::frameIsInFrontOfThis( const QRect& frameGeometry ) +{ + QRect ownGeometry = this->canvas()->geometry(); + ownGeometry.translate( this->geometry().topLeft() ); + + if ( frameGeometry.bottom() < ownGeometry.center().y() ) + { + return true; + } + else if ( frameGeometry.left() < ownGeometry.left() && frameGeometry.top() < ownGeometry.center().y() ) + { + return true; + } + else + { + QRect intersection = ownGeometry.intersected( frameGeometry ); + + double ownArea = double( ownGeometry.height() ) * double( ownGeometry.width() ); + double frameArea = double( frameGeometry.height() ) * double( frameGeometry.width() ); + double intersectionArea = double( intersection.height() ) * double( intersection.width() ); + if ( intersectionArea > 0.8 * std::min( ownArea, frameArea ) ) + { + return true; + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QPoint RiuQwtPlotWidget::dragStartPosition() const +{ + return m_clickPosition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setDefaultStyleSheet( bool includeHoverFrame ) +{ + setStyleSheetForThisObject( "background-color: white; border: 1px solid transparent;" ); + if ( includeHoverFrame ) + { + QString styleSheet = createHoverStyleSheet( "dotted" ); + appendStyleSheetForThisObject( styleSheet, "hover" ); + } + this->canvas()->setStyleSheet( QString( "QwtPlotCanvas#%1 { background-color: white; border: 1px solid black; }" ) + .arg( this->canvas()->objectName() ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setStyleSheetForThisObject( const QString& content, const QString& state /*= "" */ ) +{ + QString stateTag = !state.isEmpty() ? QString( ":%1" ).arg( state ) : ""; + QString stylesheet = QString( "QwtPlot#%1%2 { %3 }\n" ).arg( this->objectName() ).arg( stateTag ).arg( content ); + setStyleSheet( stylesheet ); + this->canvas()->setStyleSheet( QString( "QwtPlotCanvas#%1 { background-color: white; border: 1px solid black; }" ) + .arg( this->canvas()->objectName() ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::appendStyleSheetForThisObject( const QString& content, const QString& state /*= ""*/ ) +{ + QString stateTag = !state.isEmpty() ? QString( ":%1" ).arg( state ) : ""; + QString stylesheet = QString( "QwtPlot#%1%2 { %3 }\n" ).arg( this->objectName() ).arg( stateTag ).arg( content ); + QString completeStyleSheet = this->styleSheet() + stylesheet; + setStyleSheet( completeStyleSheet ); + this->canvas()->setStyleSheet( QString( "QwtPlotCanvas#%1 { background-color: white; border: 1px solid black; }" ) + .arg( this->canvas()->objectName() ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuQwtPlotWidget::widthScaleFactor() const +{ + if ( plotOwner() ) + { + return plotDefinition()->widthScaleFactor(); + } + return 1; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::scheduleReplot() +{ + RiaPlotWindowRedrawScheduler::instance()->schedulePlotWidgetReplot( this ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setSelected( bool selected ) +{ + if ( selected ) + { + QColor defaultHighlightColor = this->palette().highlight().color(); + QString styleSheet = createHoverStyleSheet( "solid" ); + setStyleSheetForThisObject( styleSheet, "hover" ); + appendStyleSheetForThisObject( QString( "border: 1px solid %1;" ).arg( defaultHighlightColor.name() ) ); + } + else + { + setDefaultStyleSheet(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuQwtPlotWidget::sizeHint() const +{ + return QSize( 0, 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuQwtPlotWidget::minimumSizeHint() const +{ + return QSize( 0, 0 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuQwtPlotWidget::eventFilter( QObject* watched, QEvent* event ) +{ + QMouseEvent* mouseEvent = dynamic_cast( event ); + if ( mouseEvent ) + { + // Shift is the zoom modifier and is reserved for QwtZoomPickers + bool zoomModifierApplied = ( mouseEvent->modifiers() & Qt::ShiftModifier ) != 0; + if ( zoomModifierApplied ) return false; + + bool toggleItemInSelection = ( mouseEvent->modifiers() & Qt::ControlModifier ) != 0; + + if ( mouseEvent->type() == QMouseEvent::MouseButtonPress && mouseEvent->button() == Qt::LeftButton ) + { + m_clickPosition = mouseEvent->pos(); + } + + if ( watched == this && !this->canvas()->geometry().contains( mouseEvent->pos() ) ) + { + if ( mouseEvent->type() == QMouseEvent::MouseMove && ( mouseEvent->buttons() & Qt::LeftButton ) && + !m_clickPosition.isNull() ) + { + int dragLength = ( mouseEvent->pos() - m_clickPosition ).manhattanLength(); + if ( dragLength >= QApplication::startDragDistance() ) + { + QPoint dragPositionOffset = this->geometry().topLeft() - mouseEvent->pos(); + QPixmap pixmap = this->grab(); + QDrag* drag = new QDrag( this ); + QMimeData* mimeData = new QMimeData; + mimeData->setImageData( pixmap ); + drag->setMimeData( mimeData ); + drag->setPixmap( pixmap ); + drag->setHotSpot( mouseEvent->pos() ); + drag->exec( Qt::MoveAction ); + return true; + } + } + else if ( mouseEvent->type() == QMouseEvent::MouseButtonRelease && + ( mouseEvent->button() == Qt::LeftButton ) && !m_clickPosition.isNull() ) + { + QWidget* childClicked = this->childAt( m_clickPosition ); + + if ( childClicked ) + { + QwtScaleWidget* scaleWidget = qobject_cast( childClicked ); + if ( scaleWidget ) + { + onAxisSelected( scaleWidget, toggleItemInSelection ); + return true; + } + } + else + { + selectPlotOwner( toggleItemInSelection ); + return true; + } + } + } + else if ( watched == canvas() ) + { + if ( mouseEvent->type() == QMouseEvent::MouseButtonRelease && mouseEvent->button() == Qt::LeftButton && + !m_clickPosition.isNull() ) + { + selectClosestCurve( mouseEvent->pos(), toggleItemInSelection ); + return true; + } + } + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::hideEvent( QHideEvent* event ) +{ + resetCurveHighlighting(); + QwtPlot::hideEvent( event ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::applyYTitleToQwt() +{ + QString titleToApply = m_yAxisTitleEnabled ? m_yAxisTitle : QString( "" ); + QwtText axisTitleY = axisTitle( QwtPlot::yLeft ); + if ( titleToApply != axisTitleY.text() ) + { + axisTitleY.setText( titleToApply ); + setAxisTitle( QwtPlot::yLeft, axisTitleY ); + setMinimumWidth( defaultMinimumWidth() + axisExtent( QwtPlot::yLeft ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// Empty default implementation +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::selectPoint( QwtPlotCurve* curve, int pointNumber ) {} + +//-------------------------------------------------------------------------------------------------- +/// Empty default implementation +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::clearPointSelection() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuQwtPlotWidget::createHoverStyleSheet( const QString& borderType ) +{ + QColor highlightColor = this->palette().highlight().color(); + QColor backgroundColor = this->palette().background().color(); + QColor blendedHighlightColor = RiaColorTools::blendQColors( highlightColor, backgroundColor, 2, 1 ); + QColor nearlyBackgroundColor = RiaColorTools::blendQColors( highlightColor, backgroundColor, 1, 20 ); + + QString styleSheet = QString( "border: 1px %1 %2; background: qlineargradient(x1: 1, y1: 0, x2: 1, y2: 1, " + "stop: 0 %3, stop: 0.04 %4, stop:1 %5 );" ) + .arg( borderType ) + .arg( highlightColor.name() ) + .arg( blendedHighlightColor.name() ) + .arg( nearlyBackgroundColor.name() ) + .arg( backgroundColor.name() ); + return styleSheet; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::onAxisSelected( QwtScaleWidget* scale, bool toggleItemInSelection ) +{ + int axisId = -1; + for ( int i = 0; i < QwtPlot::axisCnt; ++i ) + { + if ( scale == this->axisWidget( i ) ) + { + axisId = i; + } + } + plotDefinition()->onAxisSelected( axisId, toggleItemInSelection ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::setDefaults() +{ + setEnabledAxes( { QwtPlot::xTop, QwtPlot::yLeft } ); + RiuQwtPlotTools::setCommonPlotBehaviour( this ); + setDefaultStyleSheet(); +} + +void RiuQwtPlotWidget::selectPlotOwner( bool toggleItemInSelection ) +{ + if ( toggleItemInSelection ) + { + RiuPlotMainWindowTools::toggleItemInSelection( plotOwner() ); + } + else + { + RiuPlotMainWindowTools::selectAsCurrentItem( plotOwner() ); + } + scheduleReplot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::selectClosestCurve( const QPoint& pos, bool toggleItemInSelection /*= false*/ ) +{ + QwtPlotCurve* closestCurve = nullptr; + double distMin = DBL_MAX; + int closestCurvePoint = -1; + + const QwtPlotItemList& itmList = itemList(); + for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++ ) + { + if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) + { + QwtPlotCurve* candidateCurve = static_cast( *it ); + double dist = DBL_MAX; + int curvePoint = candidateCurve->closestPoint( pos, &dist ); + if ( dist < distMin ) + { + closestCurve = candidateCurve; + distMin = dist; + closestCurvePoint = curvePoint; + } + } + } + + RiuPlotMainWindowTools::showPlotMainWindow(); + resetCurveHighlighting(); + if ( closestCurve && distMin < 20 ) + { + if ( plotDefinition() ) + { + RimPlotCurve* selectedCurve = dynamic_cast( + plotDefinition()->findPdmObjectFromQwtCurve( closestCurve ) ); + if ( selectedCurve ) + { + if ( toggleItemInSelection ) + { + RiuPlotMainWindowTools::toggleItemInSelection( selectedCurve ); + } + else + { + RiuPlotMainWindowTools::selectAsCurrentItem( selectedCurve ); + } + // TODO: highlight all selected curves + highlightCurve( closestCurve ); + } + } + if ( distMin < 10 ) + { + selectPoint( closestCurve, closestCurvePoint ); + } + else + { + clearPointSelection(); + } + scheduleReplot(); + } + else + { + selectPlotOwner( toggleItemInSelection ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiuQwtPlotWidget::defaultMinimumWidth() +{ + return 80; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::replot() +{ + QwtPlot::replot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::highlightCurve( const QwtPlotCurve* closestCurve ) +{ + // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list + // plotCurve->setZ() causes the ordering of items in the list to change + auto plotItemList = this->itemList(); + for ( QwtPlotItem* plotItem : plotItemList ) + { + QwtPlotCurve* plotCurve = dynamic_cast( plotItem ); + if ( plotCurve ) + { + QPen existingPen = plotCurve->pen(); + QColor bgColor = this->canvasBackground().color(); + + QColor curveColor = existingPen.color(); + QColor symbolColor; + QColor symbolLineColor; + + QwtSymbol* symbol = const_cast( plotCurve->symbol() ); + if ( symbol ) + { + symbolColor = symbol->brush().color(); + symbolLineColor = symbol->pen().color(); + } + + double zValue = plotCurve->z(); + if ( plotCurve == closestCurve ) + { + plotCurve->setZ( zValue + 100.0 ); + } + else + { + QColor blendedColor = RiaColorTools::blendQColors( bgColor, curveColor, 3, 1 ); + QColor blendedSymbolColor = RiaColorTools::blendQColors( bgColor, symbolColor, 3, 1 ); + QColor blendedSymbolLineColor = RiaColorTools::blendQColors( bgColor, symbolLineColor, 3, 1 ); + + plotCurve->setPen( blendedColor, existingPen.width(), existingPen.style() ); + if ( symbol ) + { + symbol->setColor( blendedSymbolColor ); + symbol->setPen( blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style() ); + } + } + CurveColors curveColors = { curveColor, symbolColor, symbolLineColor }; + m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) ); + m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) ); + m_originalZValues.insert( std::make_pair( plotCurve, zValue ) ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotWidget::resetCurveHighlighting() +{ + // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list + // plotCurve->setZ() causes the ordering of items in the list to change + auto plotItemList = this->itemList(); + for ( QwtPlotItem* plotItem : plotItemList ) + { + QwtPlotCurve* plotCurve = dynamic_cast( plotItem ); + if ( plotCurve && m_originalCurveColors.count( plotCurve ) ) + { + const QPen& existingPen = plotCurve->pen(); + auto colors = m_originalCurveColors[plotCurve]; + double zValue = m_originalZValues[plotCurve]; + + plotCurve->setPen( colors.lineColor, existingPen.width(), existingPen.style() ); + plotCurve->setZ( zValue ); + QwtSymbol* symbol = const_cast( plotCurve->symbol() ); + if ( symbol ) + { + symbol->setColor( colors.symbolColor ); + symbol->setPen( colors.symbolLineColor, symbol->pen().width(), symbol->pen().style() ); + } + } + } + m_originalCurveColors.clear(); + m_originalZValues.clear(); +} diff --git a/ApplicationCode/UserInterface/RiuQwtPlotWidget.h b/ApplicationCode/UserInterface/RiuQwtPlotWidget.h new file mode 100644 index 0000000000..1340649a4d --- /dev/null +++ b/ApplicationCode/UserInterface/RiuQwtPlotWidget.h @@ -0,0 +1,146 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "qwt_plot.h" + +#include "cafPdmObject.h" +#include "cafPdmPointer.h" + +#include + +#include + +class RiaPlotWindowRedrawScheduler; +class RimPlotInterface; + +class QwtLegend; +class QwtPicker; +class QwtPlotCurve; +class QwtPlotGrid; +class QwtPlotMarker; +class QwtPlotPicker; + +class QEvent; + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuQwtPlotWidget : public QwtPlot +{ + Q_OBJECT + +public: + RiuQwtPlotWidget( RimPlotInterface* plotTrackDefinition, QWidget* parent = nullptr ); + ~RiuQwtPlotWidget() override; + + RimPlotInterface* plotDefinition() const; + caf::PdmObject* plotOwner() const; + + bool isChecked() const; + + int fontSize() const; + void setFontSize( int fontSize ); + + void setEnabledAxes( const std::set enabledAxes ); + + void setXTitle( const QString& title ); + void setYTitle( const QString& title ); + void setYTitleEnabled( bool enable ); + + QwtInterval axisRange( QwtPlot::Axis axis ); + void setXRange( double min, double max, QwtPlot::Axis axis = QwtPlot::xTop ); + void setYRange( double min, double max ); + + void setAxisInverted( QwtPlot::Axis axis ); + + void setYAxisLabelsAndTicksEnabled( bool enable ); + + void enableXGridLines( bool majorGridLines, bool minorGridLines ); + void enableYGridLines( bool majorGridLines, bool minorGridLines ); + + void setMajorAndMinorTickIntervals( double majorTickInterval, + double minorTickInterval, + double minValue, + double maxValue, + QwtPlot::Axis axis = QwtPlot::xTop ); + void setAutoTickIntervalCounts( int maxMajorTickIntervalCount, + int maxMinorTickIntervalCount, + QwtPlot::Axis axis = QwtPlot::xTop ); + double getCurrentMajorTickInterval() const; + double getCurrentMinorTickInterval() const; + + int axisExtent( QwtPlot::Axis axis ) const; + + bool frameIsInFrontOfThis( const QRect& frameGeometry ); + QPoint dragStartPosition() const; + void setDefaultStyleSheet( bool includeHoverFrame = true ); + void setStyleSheetForThisObject( const QString& content, const QString& state = "" ); + void appendStyleSheetForThisObject( const QString& content, const QString& state = "" ); + int widthScaleFactor() const; + + void scheduleReplot(); + void setSelected( bool selected ); + +protected: + QSize sizeHint() const override; + QSize minimumSizeHint() const override; + bool eventFilter( QObject* watched, QEvent* event ) override; + void hideEvent( QHideEvent* event ) override; + + void applyYTitleToQwt(); + + virtual void selectPoint( QwtPlotCurve* curve, int pointNumber ); + virtual void clearPointSelection(); + + QString createHoverStyleSheet( const QString& borderType = "solid" ); + +private: + void setDefaults(); + void selectPlotOwner( bool toggleItemInSelection = false ); + void selectClosestCurve( const QPoint& pos, bool toggleItemInSelection = false ); + static int defaultMinimumWidth(); + void replot() override; + + void highlightCurve( const QwtPlotCurve* closestCurve ); + void resetCurveHighlighting(); + void onAxisSelected( QwtScaleWidget* scale, bool toggleItemInSelection ); + +private: + caf::PdmPointer m_plotOwner; + QPoint m_clickPosition; + QString m_yAxisTitle; + bool m_yAxisTitleEnabled; + QPointer m_plotPicker; + + struct CurveColors + { + QColor lineColor; + QColor symbolColor; + QColor symbolLineColor; + }; + + std::map m_originalCurveColors; + std::map m_originalZValues; + + friend class RiaPlotWindowRedrawScheduler; +}; diff --git a/ApplicationCode/UserInterface/RiuQwtScalePicker.cpp b/ApplicationCode/UserInterface/RiuQwtScalePicker.cpp index 4f4617257b..41b5051694 100644 --- a/ApplicationCode/UserInterface/RiuQwtScalePicker.cpp +++ b/ApplicationCode/UserInterface/RiuQwtScalePicker.cpp @@ -1,6 +1,7 @@ // Based on the example scalepicker from the Qwt/examples/event_filter #include "RiuQwtScalePicker.h" +#include "RiuQwtPlotWidget.h" #include @@ -31,7 +32,7 @@ bool RiuQwtScalePicker::eventFilter( QObject* object, QEvent* event ) if ( scaleWidget ) { QMouseEvent* mouseEvent = static_cast( event ); - mouseClicked( scaleWidget, mouseEvent->pos() ); + Q_EMIT( mouseClicked( scaleWidget, mouseEvent->pos() ) ); return true; } @@ -43,7 +44,7 @@ bool RiuQwtScalePicker::eventFilter( QObject* object, QEvent* event ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuQwtScalePicker::mouseClicked( const QwtScaleWidget* scale, const QPoint& pos ) +double RiuQwtScalePicker::axisValueAtPosition( const QwtScaleWidget* scale, const QPoint& pos ) { QRect rect = scale->rect(); @@ -85,6 +86,7 @@ void RiuQwtScalePicker::mouseClicked( const QwtScaleWidget* scale, const QPoint& break; } } - Q_EMIT clicked( axis, value ); + return value; } + return std::numeric_limits::infinity(); } diff --git a/ApplicationCode/UserInterface/RiuQwtScalePicker.h b/ApplicationCode/UserInterface/RiuQwtScalePicker.h index afbb389a26..2416e3e985 100644 --- a/ApplicationCode/UserInterface/RiuQwtScalePicker.h +++ b/ApplicationCode/UserInterface/RiuQwtScalePicker.h @@ -16,9 +16,8 @@ public: bool eventFilter( QObject*, QEvent* ) override; -Q_SIGNALS: - void clicked( int axis, double value ); + static double axisValueAtPosition( const QwtScaleWidget*, const QPoint& ); -private: - void mouseClicked( const QwtScaleWidget*, const QPoint& ); +Q_SIGNALS: + void mouseClicked( QwtScaleWidget*, const QPoint& ); }; diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp index 3b66965919..00714bf26b 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp @@ -23,6 +23,7 @@ #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" #include "RimMainPlotCollection.h" +#include "RimPlotInterface.h" #include "RimRegularLegendConfig.h" #include "RimSummaryCase.h" #include "RimSummaryCurve.h" @@ -32,6 +33,7 @@ #include "RiuCvfOverlayItemWidget.h" #include "RiuQwtCurvePointTracker.h" +#include "RiuQwtPlotWheelZoomer.h" #include "RiuRimQwtPlotCurve.h" #include "RiuWidgetDragger.h" @@ -89,11 +91,43 @@ static EnsembleCurveInfoTextProvider ensembleCurveInfoTextProvider; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuSummaryQwtPlot::RiuSummaryQwtPlot( RimViewWindow* viewWindow, QWidget* parent /*= nullptr*/ ) - : RiuQwtPlot( viewWindow, parent ) +RiuSummaryQwtPlot::RiuSummaryQwtPlot( RimPlotInterface* plotDefinition, QWidget* parent /*= nullptr*/ ) + : RiuQwtPlotWidget( plotDefinition, parent ) { + // LeftButton for the zooming + m_zoomerLeft = new RiuQwtPlotZoomer( canvas() ); + m_zoomerLeft->setRubberBandPen( QColor( Qt::black ) ); + m_zoomerLeft->setTrackerMode( QwtPicker::AlwaysOff ); + m_zoomerLeft->setTrackerPen( QColor( Qt::black ) ); + m_zoomerLeft->initMousePattern( 1 ); + m_zoomerLeft->setMousePattern( QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier ); + + // Attach a zoomer for the right axis + m_zoomerRight = new RiuQwtPlotZoomer( canvas() ); + m_zoomerRight->setAxis( xTop, yRight ); + m_zoomerRight->setTrackerMode( QwtPicker::AlwaysOff ); + m_zoomerRight->initMousePattern( 1 ); + m_zoomerRight->setMousePattern( QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier ); + + // MidButton for the panning + QwtPlotPanner* panner = new QwtPlotPanner( canvas() ); + panner->setMouseButton( Qt::MidButton ); + + auto wheelZoomer = new RiuQwtPlotWheelZoomer( this ); + + connect( wheelZoomer, SIGNAL( zoomUpdated() ), SLOT( onZoomedSlot() ) ); + connect( m_zoomerLeft, SIGNAL( zoomed( const QRectF& ) ), SLOT( onZoomedSlot() ) ); + connect( m_zoomerRight, SIGNAL( zoomed( const QRectF& ) ), SLOT( onZoomedSlot() ) ); + connect( panner, SIGNAL( panned( int, int ) ), SLOT( onZoomedSlot() ) ); + setDefaults(); new RiuQwtCurvePointTracker( this, true, &ensembleCurveInfoTextProvider ); + + RiuQwtPlotTools::setCommonPlotBehaviour( this ); + RiuQwtPlotTools::setDefaultAxes( this ); + + this->installEventFilter( this ); + this->canvas()->installEventFilter( this ); } //-------------------------------------------------------------------------------------------------- @@ -162,12 +196,20 @@ void RiuSummaryQwtPlot::removeEnsembleCurveSetLegend( RimEnsembleCurveSet* curve this->updateLegendLayout(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimViewWindow* RiuSummaryQwtPlot::ownerViewWindow() const +{ + return dynamic_cast( plotDefinition() ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuSummaryQwtPlot::keyPressEvent( QKeyEvent* keyEvent ) { - RimSummaryPlot* summaryPlot = dynamic_cast( ownerPlotDefinition() ); + RimSummaryPlot* summaryPlot = dynamic_cast( plotDefinition() ); if ( summaryPlot ) { @@ -183,7 +225,7 @@ void RiuSummaryQwtPlot::contextMenuEvent( QContextMenuEvent* event ) QMenu menu; caf::CmdFeatureMenuBuilder menuBuilder; - caf::SelectionManager::instance()->setSelectedItem( ownerViewWindow() ); + caf::SelectionManager::instance()->setSelectedItem( plotOwner() ); menuBuilder << "RicShowPlotDataFeature"; menuBuilder << "RicSavePlotTemplateFeature"; @@ -221,6 +263,14 @@ void RiuSummaryQwtPlot::updateLayout() updateLegendLayout(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::onZoomedSlot() +{ + plotDefinition()->updateZoomFromQwt(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -234,7 +284,7 @@ void RiuSummaryQwtPlot::updateLegendLayout() int ypos = startMarginY; int maxColumnWidth = 0; - RimSummaryPlot* summaryPlot = dynamic_cast( ownerPlotDefinition() ); + RimSummaryPlot* summaryPlot = dynamic_cast( plotDefinition() ); if ( !summaryPlot || !summaryPlot->ensembleCurveSetCollection() ) return; diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h index 473c03dc23..22c233f00b 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h @@ -20,7 +20,7 @@ #include "RiaQDateTimeTools.h" #include "RiuInterfaceToViewWindow.h" -#include "RiuQwtPlot.h" +#include "RiuQwtPlotWidget.h" #include "cafPdmPointer.h" @@ -28,18 +28,19 @@ class RimEnsembleCurveSet; class RiuCvfOverlayItemWidget; +class RiuQwtPlotZoomer; //================================================================================================== // // // //================================================================================================== -class RiuSummaryQwtPlot : public RiuQwtPlot +class RiuSummaryQwtPlot : public RiuQwtPlotWidget, public RiuInterfaceToViewWindow { Q_OBJECT; public: - RiuSummaryQwtPlot( RimViewWindow* ownerViewWindow, QWidget* parent = nullptr ); + RiuSummaryQwtPlot( RimPlotInterface* plotDefinition, QWidget* parent = nullptr ); void useDateBasedTimeAxis( const QString& dateFormat, @@ -52,13 +53,22 @@ public: void addOrUpdateEnsembleCurveSetLegend( RimEnsembleCurveSet* curveSetToShowLegendFor ); void removeEnsembleCurveSetLegend( RimEnsembleCurveSet* curveSetToShowLegendFor ); + RimViewWindow* ownerViewWindow() const override; + protected: void keyPressEvent( QKeyEvent* ) override; void contextMenuEvent( QContextMenuEvent* ) override; void setDefaults(); void updateLayout() override; +private slots: + void onZoomedSlot(); + private: - void updateLegendLayout(); + void updateLegendLayout(); + std::map, QPointer> m_ensembleLegendWidgets; + + QPointer m_zoomerLeft; + QPointer m_zoomerRight; }; diff --git a/ApplicationCode/UserInterface/RiuWellLogPlot.cpp b/ApplicationCode/UserInterface/RiuWellLogPlot.cpp index 1ec180b76b..0dc003bfb5 100644 --- a/ApplicationCode/UserInterface/RiuWellLogPlot.cpp +++ b/ApplicationCode/UserInterface/RiuWellLogPlot.cpp @@ -1,632 +1,51 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS -// -// 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 "RiuWellLogPlot.h" -#include "RiaApplication.h" -#include "RiaPreferences.h" - -#include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h" - -#include "RimContextCommandBuilder.h" +#include "RimPlotWindow.h" #include "RimWellLogPlot.h" -#include "RimWellLogTrack.h" -#include "RiuMainWindow.h" -#include "RiuPlotMainWindow.h" -#include "RiuPlotObjectPicker.h" -#include "RiuWellLogTrack.h" +#include "cafAssert.h" +#include "cafPdmPointer.h" -#include "cafCmdFeatureMenuBuilder.h" -#include "cafSelectionManager.h" - -#include "cvfAssert.h" - -#include "qwt_legend.h" -#include "qwt_plot_layout.h" -#include "qwt_scale_draw.h" - -#include -#include -#include -#include -#include #include -#include - -#include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuWellLogPlot::RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent ) - : QWidget( parent ) + : RiuGridPlotWindow( plotDefinition, parent ) { - Q_ASSERT( plotDefinition ); - m_plotDefinition = plotDefinition; - - m_layout = new QVBoxLayout( this ); - m_layout->setMargin( 0 ); - m_layout->setSpacing( 2 ); - - m_plotTitle = createTitleLabel(); - m_layout->addWidget( m_plotTitle ); - - m_plotLayout = new QHBoxLayout; - m_layout->addLayout( m_plotLayout ); - - m_trackFrame = new QFrame; - m_trackFrame->setVisible( true ); - m_plotLayout->addWidget( m_trackFrame, 1 ); - - m_trackLayout = new QGridLayout( m_trackFrame ); - m_trackLayout->setMargin( 0 ); - m_trackLayout->setSpacing( 2 ); - - QPalette newPalette( palette() ); - newPalette.setColor( QPalette::Background, Qt::white ); - setPalette( newPalette ); - - setAutoFillBackground( true ); - - m_scrollBar = new QScrollBar( nullptr ); - m_scrollBar->setOrientation( Qt::Vertical ); - m_scrollBar->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ); - - m_scrollBarLayout = new QVBoxLayout; - m_scrollBarLayout->addWidget( m_scrollBar, 0 ); - - new RiuPlotObjectPicker( m_plotTitle, m_plotDefinition ); - - this->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); - - setFocusPolicy( Qt::StrongFocus ); connect( m_scrollBar, SIGNAL( valueChanged( int ) ), this, SLOT( slotSetMinDepth( int ) ) ); - - setAcceptDrops( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuWellLogPlot::~RiuWellLogPlot() +RimWellLogPlot* RiuWellLogPlot::wellLogPlotDefinition() { - if ( m_plotDefinition ) - { - m_plotDefinition->detachAllCurves(); - } + RimWellLogPlot* wellLogPlot = dynamic_cast( m_plotDefinition.p() ); + CAF_ASSERT( wellLogPlot ); + return wellLogPlot; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::addTrackPlot( RiuWellLogTrack* trackPlot ) +void RiuWellLogPlot::updateVerticalScrollBar( double minVisible, double maxVisible, double minAvailable, double maxAvailable ) { - // Insert the plot to the left of the scroll bar - insertTrackPlot( trackPlot, m_trackPlots.size() ); -} + maxAvailable += 0.01 * ( maxAvailable - minAvailable ); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::insertTrackPlot( RiuWellLogTrack* trackPlot, size_t index, bool updateLayoutAfter ) -{ - m_trackPlots.insert( static_cast( index ), trackPlot ); - - QwtLegend* legend = new QwtLegend( nullptr ); - int legendColumns = 1; - if ( m_plotDefinition->areTrackLegendsHorizontal() ) - { - legendColumns = 0; // unlimited - } - legend->setMaxColumns( legendColumns ); - legend->horizontalScrollBar()->setVisible( false ); - legend->verticalScrollBar()->setVisible( false ); - - legend->connect( trackPlot, - SIGNAL( legendDataChanged( const QVariant&, const QList& ) ), - SLOT( updateLegend( const QVariant&, const QList& ) ) ); - legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter ); - trackPlot->updateLegend(); - m_legends.insert( static_cast( index ), legend ); - - if ( updateLayoutAfter ) - { - updateChildrenLayout(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::removeTrackPlot( RiuWellLogTrack* trackPlot, bool updateLayoutAfter ) -{ - if ( !trackPlot ) return; - - int trackIdx = m_trackPlots.indexOf( trackPlot ); - CVF_ASSERT( trackIdx >= 0 ); - - m_trackPlots.removeAt( trackIdx ); - trackPlot->setParent( nullptr ); - - QwtLegend* legend = m_legends[trackIdx]; - m_legends.removeAt( trackIdx ); - delete legend; - - if ( updateLayoutAfter ) - { - updateChildrenLayout(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::setDepthZoomAndReplot( double minDepth, double maxDepth ) -{ - for ( int tpIdx = 0; tpIdx < m_trackPlots.count(); tpIdx++ ) - { - m_trackPlots[tpIdx]->setDepthZoom( minDepth, maxDepth ); - m_trackPlots[tpIdx]->replot(); - } - - updateScrollBar( minDepth, maxDepth ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::setPlotTitle( const QString& plotTitle ) -{ - m_plotTitle->setText( plotTitle ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiuWellLogPlot::preferredWidth() const -{ - int titleWidth = 0; - if ( m_plotTitle && m_plotTitle->isVisible() ) - { - titleWidth = m_plotTitle->width(); - } - - int sumTrackWidth = 0; - for ( QPointer track : m_trackPlots ) - { - if ( track->isVisible() ) - { - sumTrackWidth += track->width(); - } - } - return std::max( titleWidth, sumTrackWidth ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::setTitleVisible( bool visible ) -{ - m_plotTitle->setVisible( visible ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::setScrollbarVisible( bool visible ) -{ - m_scrollBar->setVisible( visible ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiuWellLogPlot::indexOfTrackPlot( RiuWellLogTrack* track ) -{ - return m_trackPlots.indexOf( track ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::updateChildrenLayout() -{ - reinsertTracksAndScrollbar(); - alignCanvasTopsAndScrollbar(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::contextMenuEvent( QContextMenuEvent* event ) -{ - QMenu menu; - caf::CmdFeatureMenuBuilder menuBuilder; - - caf::SelectionManager::instance()->setSelectedItem( ownerPlotDefinition() ); - - menuBuilder << "RicShowPlotDataFeature"; - menuBuilder << "RicShowContributingWellsFromPlotFeature"; - - menuBuilder.appendToMenu( &menu ); - - if ( menu.actions().size() > 0 ) - { - menu.exec( event->globalPos() ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::keyPressEvent( QKeyEvent* keyEvent ) -{ - m_plotDefinition->handleKeyPressEvent( keyEvent ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QLabel* RiuWellLogPlot::createTitleLabel() const -{ - QLabel* plotTitle = new QLabel( "PLOT TITLE HERE", nullptr ); - - RiaApplication* app = RiaApplication::instance(); - - QFont font = plotTitle->font(); - int defaultFontSize = RiaFontCache::pointSizeFromFontSizeEnum( app->preferences()->defaultPlotFontSize() ); - - font.setPointSize( defaultFontSize + 1 ); - font.setBold( true ); - plotTitle->setFont( font ); - plotTitle->setVisible( m_plotDefinition->isPlotTitleVisible() ); - plotTitle->setAlignment( Qt::AlignHCenter ); - plotTitle->setWordWrap( true ); - plotTitle->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); - return plotTitle; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::resizeEvent( QResizeEvent* event ) -{ - QWidget::resizeEvent( event ); - updateChildrenLayout(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::showEvent( QShowEvent* event ) -{ - QWidget::showEvent( event ); - updateChildrenLayout(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::changeEvent( QEvent* event ) -{ - QWidget::changeEvent( event ); - if ( event->type() == QEvent::WindowStateChange ) - { - updateChildrenLayout(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::dragEnterEvent( QDragEnterEvent* event ) -{ - if ( this->geometry().contains( event->pos() ) ) - { - event->acceptProposedAction(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::dragMoveEvent( QDragMoveEvent* event ) -{ - if ( this->geometry().contains( event->pos() ) ) - { - RiuWellLogTrack* source = dynamic_cast( event->source() ); - if ( source ) - { - QRect originalGeometry = source->geometry(); - QPoint offset = source->dragStartPosition(); - QRect newRect( event->pos() - offset, originalGeometry.size() ); - - QList> visibleTracks = this->visibleTracks(); - - int insertBeforeIndex = visibleTracks.size(); - for ( int visibleIndex = 0; visibleIndex < visibleTracks.size(); ++visibleIndex ) - { - visibleTracks[visibleIndex]->setDefaultStyleSheet(); - - if ( visibleTracks[visibleIndex]->frameIsInFrontOfThis( newRect ) ) - { - insertBeforeIndex = std::min( insertBeforeIndex, visibleIndex ); - } - } - if ( insertBeforeIndex >= 0 && insertBeforeIndex < visibleTracks.size() ) - { - visibleTracks[insertBeforeIndex]->setStyleSheetForThisObject( - "border-left: 2px solid red; border-top: none; border-bottom: none; border-right: none;" ); - } - - if ( insertBeforeIndex > 0 ) - { - int insertAfterIndex = insertBeforeIndex - 1; - visibleTracks[insertAfterIndex]->setStyleSheetForThisObject( - "border-left: none; border-top: none; border-bottom: none; border-right: 2px solid red;" ); - } - event->acceptProposedAction(); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::dragLeaveEvent( QDragLeaveEvent* event ) -{ - for ( int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx ) - { - m_trackPlots[tIdx]->setDefaultStyleSheet(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::dropEvent( QDropEvent* event ) -{ - for ( int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx ) - { - m_trackPlots[tIdx]->setDefaultStyleSheet(); - } - - if ( this->geometry().contains( event->pos() ) ) - { - RiuWellLogTrack* source = dynamic_cast( event->source() ); - - if ( source ) - { - event->acceptProposedAction(); - - QRect originalGeometry = source->geometry(); - QPoint offset = source->dragStartPosition(); - QRect newRect( event->pos() - offset, originalGeometry.size() ); - - int beforeIndex = m_trackPlots.size(); - for ( int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx ) - { - if ( m_trackPlots[tIdx]->isVisible() ) - { - if ( m_trackPlots[tIdx]->frameIsInFrontOfThis( newRect ) ) - { - beforeIndex = tIdx; - break; - } - } - } - RimWellLogTrack* insertAfter = nullptr; - if ( beforeIndex > 0 ) - { - insertAfter = m_trackPlots[beforeIndex - 1]->plotDefinition(); - } - - RimWellLogTrack* rimTrack = source->plotDefinition(); - - if ( insertAfter != rimTrack ) - { - RicWellLogPlotTrackFeatureImpl::moveTracksToWellLogPlot( m_plotDefinition, {rimTrack}, insertAfter ); - } - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::pair RiuWellLogPlot::rowAndColumnCount( int trackCount ) const -{ - int columnCount = std::max( 1, std::min( m_plotDefinition->columnCount(), trackCount ) ); - int rowCount = static_cast( std::ceil( trackCount / static_cast( columnCount ) ) ); - return std::make_pair( rowCount, columnCount ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::updateScrollBar( double minDepth, double maxDepth ) -{ - double availableMinDepth; - double availableMaxDepth; - m_plotDefinition->availableDepthRange( &availableMinDepth, &availableMaxDepth ); - availableMaxDepth += 0.01 * ( availableMaxDepth - availableMinDepth ); - - double visibleDepth = maxDepth - minDepth; + double visibleRange = maxVisible - minVisible; m_scrollBar->blockSignals( true ); { - m_scrollBar->setRange( (int)availableMinDepth, (int)( ( availableMaxDepth - visibleDepth ) ) ); - m_scrollBar->setPageStep( (int)visibleDepth ); - m_scrollBar->setValue( (int)minDepth ); + m_scrollBar->setRange( (int)minAvailable, (int)( ( maxAvailable - visibleRange ) ) ); + m_scrollBar->setPageStep( (int)visibleRange ); + m_scrollBar->setValue( (int)minVisible ); m_scrollBar->setVisible( true ); } m_scrollBar->blockSignals( false ); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::alignCanvasTopsAndScrollbar() -{ - CVF_ASSERT( m_legends.size() == m_trackPlots.size() ); - - QList> tracks = visibleTracks(); - - auto rowAndColumnCount = this->rowAndColumnCount( tracks.size() ); - - std::vector maxExtents( rowAndColumnCount.first, 0.0 ); - - for ( int visibleIndex = 0; visibleIndex < tracks.size(); ++visibleIndex ) - { - int row = visibleIndex / rowAndColumnCount.second; - - QFont font = m_trackPlots[visibleIndex]->axisFont( QwtPlot::xTop ); - maxExtents[row] = std::max( maxExtents[row], - tracks[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->extent( font ) ); - } - - for ( int visibleIndex = 0; visibleIndex < tracks.size(); ++visibleIndex ) - { - int row = visibleIndex / rowAndColumnCount.second; - tracks[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( maxExtents[row] ); - } - m_scrollBarLayout->setContentsMargins( 0, maxExtents[0], 0, 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::reinsertTracksAndScrollbar() -{ - clearTrackLayout(); - - for ( int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx ) - { - m_trackPlots[tIdx]->hide(); - } - - QList> tracks = this->visibleTracks(); - QList> legends = this->visibleLegends(); - - auto rowAndColumnCount = this->rowAndColumnCount( tracks.size() ); - - for ( int visibleIndex = 0; visibleIndex < tracks.size(); ++visibleIndex ) - { - int row = visibleIndex / rowAndColumnCount.second; - int column = visibleIndex % rowAndColumnCount.second; - - m_trackLayout->addWidget( legends[visibleIndex], 2 * row, column ); - m_trackLayout->addWidget( tracks[visibleIndex], 2 * row + 1, column ); - - if ( m_plotDefinition->areTrackLegendsVisible() ) - { - int legendColumns = 1; - if ( m_plotDefinition->areTrackLegendsHorizontal() ) - { - legendColumns = 0; // unlimited - } - legends[visibleIndex]->setMaxColumns( legendColumns ); - int minimumHeight = legends[visibleIndex]->heightForWidth( tracks[visibleIndex]->width() ); - legends[visibleIndex]->setMinimumHeight( minimumHeight ); - - legends[visibleIndex]->show(); - } - else - { - legends[visibleIndex]->hide(); - } - - tracks[visibleIndex]->setDepthTitle( column == 0 ? m_plotDefinition->depthPlotTitle() : "" ); - tracks[visibleIndex]->enableDepthAxisLabelsAndTicks( column == 0 ); - tracks[visibleIndex]->show(); - - int widthScaleFactor = tracks[visibleIndex]->widthScaleFactor(); - if ( column == 0 ) - { - widthScaleFactor += 1; // Give it a bit extra room due to depth axis - } - m_trackLayout->setColumnStretch( column, - std::max( m_trackLayout->columnStretch( column ), - tracks[visibleIndex]->widthScaleFactor() ) ); - m_trackLayout->setRowStretch( 2 * row + 1, 1 ); - } - m_trackLayout->addLayout( m_scrollBarLayout, 1, rowAndColumnCount.second, rowAndColumnCount.first * 2 - 1, 1 ); - m_trackLayout->setColumnStretch( rowAndColumnCount.second, 0 ); - m_scrollBar->setVisible( tracks.size() > 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogPlot::clearTrackLayout() -{ - if ( m_trackLayout ) - { - for ( int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx ) - { - m_trackLayout->removeWidget( m_legends[tIdx] ); - m_trackLayout->removeWidget( m_trackPlots[tIdx] ); - } - - QLayoutItem* item; - while ( ( item = m_trackLayout->takeAt( 0 ) ) != 0 ) - { - } - QWidget().setLayout( m_trackLayout ); - delete m_trackLayout; - m_trackLayout = new QGridLayout( m_trackFrame ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QList> RiuWellLogPlot::visibleTracks() const -{ - QList> tracks; - for ( QPointer track : m_trackPlots ) - { - if ( track->isRimTrackVisible() ) - { - tracks.push_back( track ); - } - } - return tracks; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QList> RiuWellLogPlot::visibleLegends() const -{ - QList> legends; - for ( int i = 0; i < m_trackPlots.size(); ++i ) - { - if ( m_trackPlots[i]->isRimTrackVisible() ) - { - legends.push_back( m_legends[i] ); - } - } - return legends; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -634,25 +53,9 @@ void RiuWellLogPlot::slotSetMinDepth( int value ) { double minimumDepth; double maximumDepth; - m_plotDefinition->depthZoomMinMax( &minimumDepth, &maximumDepth ); + wellLogPlotDefinition()->availableDepthRange( &minimumDepth, &maximumDepth ); double delta = value - minimumDepth; - m_plotDefinition->setDepthZoomMinMax( minimumDepth + delta, maximumDepth + delta ); - m_plotDefinition->setDepthAutoZoom( false ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellLogPlot* RiuWellLogPlot::ownerPlotDefinition() -{ - return m_plotDefinition; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimViewWindow* RiuWellLogPlot::ownerViewWindow() const -{ - return m_plotDefinition; + wellLogPlotDefinition()->setDepthAxisRange( minimumDepth + delta, maximumDepth + delta ); + wellLogPlotDefinition()->setAutoScaleYEnabled( false ); } diff --git a/ApplicationCode/UserInterface/RiuWellLogPlot.h b/ApplicationCode/UserInterface/RiuWellLogPlot.h index 2458cdaf22..f18ecacab5 100644 --- a/ApplicationCode/UserInterface/RiuWellLogPlot.h +++ b/ApplicationCode/UserInterface/RiuWellLogPlot.h @@ -1,7 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS +// Copyright (C) 2019- 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,99 +15,22 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// - #pragma once -#include "RiuInterfaceToViewWindow.h" - -#include "cafPdmPointer.h" - -#include -#include -#include -#include -#include -#include - -#include +#include "RiuGridPlotWindow.h" class RimWellLogPlot; -class RiuWellLogTrack; -class QFocusEvent; -class QLabel; -class QScrollBar; -class QwtLegend; - -//================================================================================================== -// -// RiuWellLogPlot -// -//================================================================================================== -class RiuWellLogPlot : public QWidget, public RiuInterfaceToViewWindow +class RiuWellLogPlot : public RiuGridPlotWindow { Q_OBJECT - public: - RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent = nullptr ); - - ~RiuWellLogPlot() override; - - RimWellLogPlot* ownerPlotDefinition(); - RimViewWindow* ownerViewWindow() const override; - - void addTrackPlot( RiuWellLogTrack* trackPlot ); - void insertTrackPlot( RiuWellLogTrack* trackPlot, size_t index, bool updateLayoutAfter = true ); - void removeTrackPlot( RiuWellLogTrack* trackPlot, bool updateLayoutAfter = true ); - - void setDepthZoomAndReplot( double minDepth, double maxDepth ); - void setPlotTitle( const QString& plotTitle ); - int preferredWidth() const; - - void setTitleVisible( bool visible ); - void setScrollbarVisible( bool visible ); - - int indexOfTrackPlot( RiuWellLogTrack* track ); - -public slots: - void updateChildrenLayout(); - -protected: - void contextMenuEvent( QContextMenuEvent* ) override; - void keyPressEvent( QKeyEvent* keyEvent ) override; - QLabel* createTitleLabel() const; - - void resizeEvent( QResizeEvent* event ) override; - void showEvent( QShowEvent* event ) override; - void changeEvent( QEvent* ) override; - void dragEnterEvent( QDragEnterEvent* event ) override; - void dragMoveEvent( QDragMoveEvent* event ) override; - void dragLeaveEvent( QDragLeaveEvent* event ) override; - void dropEvent( QDropEvent* event ) override; - - std::pair rowAndColumnCount( int trackCount ) const; + RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent ); + void updateVerticalScrollBar( double minVisible, double maxVisible, double minAvailable, double maxAvailable ); private: - void updateScrollBar( double minDepth, double maxDepth ); - void alignCanvasTopsAndScrollbar(); - void reinsertTracksAndScrollbar(); - void clearTrackLayout(); - - QList> visibleTracks() const; - QList> visibleLegends() const; + RimWellLogPlot* wellLogPlotDefinition(); private slots: void slotSetMinDepth( int value ); - -protected: - QPointer m_layout; - QPointer m_plotLayout; - QPointer m_trackFrame; - QPointer m_trackLayout; - QPointer m_plotTitle; - QPointer m_scrollBarLayout; - QScrollBar* m_scrollBar; - QList> m_legends; - QList> m_trackPlots; - caf::PdmPointer m_plotDefinition; }; diff --git a/ApplicationCode/UserInterface/RiuWellLogTrack.cpp b/ApplicationCode/UserInterface/RiuWellLogTrack.cpp index 9a29fab086..fc7e074b42 100644 --- a/ApplicationCode/UserInterface/RiuWellLogTrack.cpp +++ b/ApplicationCode/UserInterface/RiuWellLogTrack.cpp @@ -1,521 +1,83 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS -// -// 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 "RiuWellLogTrack.h" - -#include "RiaApplication.h" - -#include "RimWellLogCurve.h" -#include "RimWellLogPlot.h" -#include "RimWellLogTrack.h" - -#include "RiuPlotMainWindowTools.h" -#include "RiuQwtCurvePointTracker.h" -#include "RiuQwtPlotTools.h" - -#include "RiuQwtLinearScaleEngine.h" - -#include "qwt_legend.h" -#include "qwt_plot_curve.h" -#include "qwt_plot_grid.h" -#include "qwt_plot_layout.h" -#include "qwt_plot_marker.h" -#include "qwt_plot_picker.h" -#include "qwt_scale_draw.h" -#include "qwt_scale_widget.h" -#include "qwt_symbol.h" -#include "qwt_text.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define RIU_SCROLLWHEEL_ZOOMFACTOR 1.1 -#define RIU_SCROLLWHEEL_PANFACTOR 0.1 - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuWellLogTrack::RiuWellLogTrack( RimWellLogTrack* plotTrackDefinition, QWidget* parent ) - : QwtPlot( parent ) -{ - Q_ASSERT( plotTrackDefinition ); - m_plotTrackDefinition = plotTrackDefinition; - - setDefaults(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuWellLogTrack::~RiuWellLogTrack() {} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDepthZoom( double minDepth, double maxDepth ) -{ - // Note: Y-axis is inverted - setAxisScale( QwtPlot::yLeft, maxDepth, minDepth ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setXRange( double min, double max, QwtPlot::Axis axis ) -{ - setAxisScale( axis, min, max ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDepthTitle( const QString& title ) -{ - QwtText axisTitleY = axisTitle( QwtPlot::yLeft ); - if ( title != axisTitleY.text() ) - { - axisTitleY.setText( title ); - setAxisTitle( QwtPlot::yLeft, axisTitleY ); - setMinimumWidth( defaultMinimumWidth() + axisExtent( QwtPlot::yLeft ) ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setXTitle( const QString& title ) -{ - QwtText axisTitleX = axisTitle( QwtPlot::xTop ); - if ( title != axisTitleX.text() ) - { - axisTitleX.setText( title ); - setAxisTitle( QwtPlot::xTop, axisTitleX ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuWellLogTrack::isRimTrackVisible() -{ - if ( m_plotTrackDefinition ) - { - return m_plotTrackDefinition->isVisible(); - } - - return false; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::enableDepthAxisLabelsAndTicks( bool enable ) -{ - this->axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Ticks, enable ); - this->axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Labels, enable ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiuWellLogTrack::widthScaleFactor() const -{ - if ( m_plotTrackDefinition ) - { - return m_plotTrackDefinition->widthScaleFactor(); - } - return 1; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::enableXGridLines( bool majorGridLines, bool minorGridLines ) -{ - QwtPlotItemList plotItems = this->itemList( QwtPlotItem::Rtti_PlotGrid ); - for ( QwtPlotItem* plotItem : plotItems ) - { - QwtPlotGrid* grid = static_cast( plotItem ); - grid->setXAxis( QwtPlot::xTop ); - grid->enableX( majorGridLines ); - grid->enableXMin( minorGridLines ); - grid->setMajorPen( Qt::lightGray, 1.0, Qt::SolidLine ); - grid->setMinorPen( Qt::lightGray, 1.0, Qt::DashLine ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::enableDepthGridLines( bool majorGridLines, bool minorGridLines ) -{ - QwtPlotItemList plotItems = this->itemList( QwtPlotItem::Rtti_PlotGrid ); - for ( QwtPlotItem* plotItem : plotItems ) - { - QwtPlotGrid* grid = static_cast( plotItem ); - grid->setYAxis( QwtPlot::yLeft ); - grid->enableY( majorGridLines ); - grid->enableYMin( minorGridLines ); - grid->setMajorPen( Qt::lightGray, 1.0, Qt::SolidLine ); - grid->setMinorPen( Qt::lightGray, 1.0, Qt::DashLine ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setMajorAndMinorTickIntervals( double majorTickInterval, double minorTickInterval ) -{ - RiuQwtLinearScaleEngine* scaleEngine = dynamic_cast( - this->axisScaleEngine( QwtPlot::xTop ) ); - if ( scaleEngine ) - { - QwtInterval currentRange = this->axisInterval( QwtPlot::xTop ); - QwtScaleDiv scaleDiv = scaleEngine->divideScaleWithExplicitIntervals( currentRange.minValue(), - currentRange.maxValue(), - majorTickInterval, - minorTickInterval ); - - this->setAxisScaleDiv( QwtPlot::xTop, scaleDiv ); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setAutoTickIntervalCounts( int maxMajorTickIntervalCount, int maxMinorTickIntervalCount ) -{ - this->setAxisMaxMajor( QwtPlot::xTop, maxMajorTickIntervalCount ); - this->setAxisMaxMinor( QwtPlot::xTop, maxMinorTickIntervalCount ); - // Reapply axis limits to force Qwt to use the tick settings. - QwtInterval currentRange = this->axisInterval( QwtPlot::xTop ); - this->setXRange( currentRange.minValue(), currentRange.maxValue() ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RiuWellLogTrack::getCurrentMajorTickInterval() const -{ - QwtScaleDiv scaleDiv = this->axisScaleDiv( QwtPlot::xTop ); - QList majorTicks = scaleDiv.ticks( QwtScaleDiv::MajorTick ); - if ( majorTicks.size() < 2 ) return 0.0; - - return majorTicks.at( 1 ) - majorTicks.at( 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RiuWellLogTrack::getCurrentMinorTickInterval() const -{ - QwtScaleDiv scaleDiv = this->axisScaleDiv( QwtPlot::xTop ); - QList minorTicks = scaleDiv.ticks( QwtScaleDiv::MinorTick ); - if ( minorTicks.size() < 2 ) return 0.0; - - return minorTicks.at( 1 ) - minorTicks.at( 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiuWellLogTrack::axisExtent( QwtPlot::Axis axis ) const -{ - QFont tickLabelFont = axisFont( axis ); - int lineExtent = static_cast( std::ceil( axisScaleDraw( axis )->extent( tickLabelFont ) ) ); - if ( !axisTitle( axis ).text().isEmpty() ) - { - QFont titleFont = axisTitle( axis ).font(); - lineExtent += QFontMetrics( titleFont ).height(); - } - return lineExtent; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuWellLogTrack::frameIsInFrontOfThis( const QRect& frameGeometry ) -{ - QRect ownGeometry = this->canvas()->geometry(); - ownGeometry.translate( this->geometry().topLeft() ); - - if ( frameGeometry.bottom() < ownGeometry.center().y() ) - { - return true; - } - else if ( frameGeometry.left() < ownGeometry.left() && frameGeometry.top() < ownGeometry.center().y() ) - { - return true; - } - else - { - QRect intersection = ownGeometry.intersected( frameGeometry ); - - double ownArea = double( ownGeometry.height() ) * double( ownGeometry.width() ); - double frameArea = double( frameGeometry.height() ) * double( frameGeometry.width() ); - double intersectionArea = double( intersection.height() ) * double( intersection.width() ); - if ( intersectionArea > 0.8 * std::min( ownArea, frameArea ) ) - { - return true; - } - } - - return false; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QPoint RiuWellLogTrack::dragStartPosition() const -{ - return m_dragStartPosition; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDefaultStyleSheet() -{ - this->setStyleSheetForThisObject( "border: 1px dashed blue;", "hover" ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setStyleSheetForThisObject( const QString& content, const QString& state /*= "" */ ) -{ - QString stateTag = !state.isEmpty() ? QString( ":%1" ).arg( state ) : ""; - QString stylesheet = QString( "QwtPlot#%1%2 { %3 }" ).arg( this->objectName() ).arg( stateTag ).arg( content ); - this->setStyleSheet( stylesheet ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimWellLogTrack* RiuWellLogTrack::plotDefinition() const -{ - return m_plotTrackDefinition; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuWellLogTrack::eventFilter( QObject* watched, QEvent* event ) -{ - if ( watched == canvas() ) - { - QWheelEvent* wheelEvent = dynamic_cast( event ); - if ( wheelEvent ) - { - if ( !m_plotTrackDefinition ) - { - return QwtPlot::eventFilter( watched, event ); - } - - RimWellLogPlot* plotDefinition; - m_plotTrackDefinition->firstAncestorOrThisOfType( plotDefinition ); - if ( !plotDefinition ) - { - return QwtPlot::eventFilter( watched, event ); - } - - if ( wheelEvent->modifiers() & Qt::ControlModifier ) - { - QwtScaleMap scaleMap = canvasMap( QwtPlot::yLeft ); - double zoomCenter = scaleMap.invTransform( wheelEvent->pos().y() ); - - if ( wheelEvent->delta() > 0 ) - { - plotDefinition->setDepthZoomByFactorAndCenter( RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter ); - } - else - { - plotDefinition->setDepthZoomByFactorAndCenter( 1.0 / RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter ); - } - } - else - { - plotDefinition->panDepth( wheelEvent->delta() < 0 ? RIU_SCROLLWHEEL_PANFACTOR - : -RIU_SCROLLWHEEL_PANFACTOR ); - } - - event->accept(); - return true; - } - else - { - QMouseEvent* mouseEvent = dynamic_cast( event ); - if ( mouseEvent ) - { - if ( mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease ) - { - selectClosestCurve( mouseEvent->pos() ); - } - } - } - } - - return QwtPlot::eventFilter( watched, event ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuWellLogTrack::sizeHint() const -{ - return QSize( 0, 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuWellLogTrack::minimumSizeHint() const -{ - return QSize( 0, 0 ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::mousePressEvent( QMouseEvent* event ) -{ - if ( event->button() == Qt::LeftButton && this->underMouse() ) - { - m_dragStartPosition = event->pos(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::mouseMoveEvent( QMouseEvent* event ) -{ - if ( !( event->buttons() & Qt::LeftButton ) ) return; - if ( ( event->pos() - m_dragStartPosition ).manhattanLength() < QApplication::startDragDistance() ) return; - - QPoint dragPositionOffset = this->canvas()->geometry().topLeft() - m_dragStartPosition; - QPixmap pixmap = this->canvas()->grab(); - QDrag* drag = new QDrag( this ); - QMimeData* mimeData = new QMimeData; - mimeData->setImageData( pixmap ); - drag->setMimeData( mimeData ); - drag->setPixmap( pixmap ); - drag->setHotSpot( m_dragStartPosition ); - drag->exec( Qt::MoveAction ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::setDefaults() -{ - RiuQwtPlotTools::setCommonPlotBehaviour( this ); - - enableAxis( QwtPlot::xTop, true ); - enableAxis( QwtPlot::yLeft, true ); - enableAxis( QwtPlot::xBottom, false ); - enableAxis( QwtPlot::yRight, false ); - - axisScaleEngine( QwtPlot::yLeft )->setAttribute( QwtScaleEngine::Inverted, true ); - - // Align the canvas with the actual min and max values of the curves - axisScaleEngine( QwtPlot::xTop )->setAttribute( QwtScaleEngine::Floating, true ); - axisScaleEngine( QwtPlot::yLeft )->setAttribute( QwtScaleEngine::Floating, true ); - setAxisScale( QwtPlot::yLeft, 1000, 0 ); - setXRange( 0, 100 ); - axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( axisExtent( QwtPlot::xTop ) ); - setMinimumWidth( defaultMinimumWidth() ); - - canvas()->setContentsMargins( 0, 0, 0, 0 ); - QFrame* canvasFrame = dynamic_cast( canvas() ); - canvasFrame->setFrameShape( QFrame::Box ); - canvasFrame->setStyleSheet( "border: 1px solid black" ); - - QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect( canvas() ); - dropShadowEffect->setOffset( 1.0, 1.0 ); - dropShadowEffect->setBlurRadius( 3.0 ); - dropShadowEffect->setColor( QColor( 60, 60, 60, 60 ) ); - canvas()->setGraphicsEffect( dropShadowEffect ); - - axisScaleDraw( QwtPlot::xTop )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); - axisScaleDraw( QwtPlot::yLeft )->enableComponent( QwtAbstractScaleDraw::Backbone, false ); - axisWidget( QwtPlot::xTop )->setMargin( 0 ); - axisWidget( QwtPlot::yLeft )->setMargin( 0 ); - - // Store the pointer address as an object name. This way each track can be identified uniquely for CSS-stylesheets - QString objectName = QString( "%1" ).arg( reinterpret_cast( this ) ); - setObjectName( objectName ); - - setDefaultStyleSheet(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuWellLogTrack::selectClosestCurve( const QPoint& pos ) -{ - QwtPlotCurve* closestCurve = nullptr; - double distMin = DBL_MAX; - - const QwtPlotItemList& itmList = itemList(); - for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++ ) - { - if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) - { - QwtPlotCurve* candidateCurve = static_cast( *it ); - double dist = DBL_MAX; - candidateCurve->closestPoint( pos, &dist ); - if ( dist < distMin ) - { - closestCurve = candidateCurve; - distMin = dist; - } - } - } - - if ( closestCurve && distMin < 20 ) - { - RimWellLogCurve* selectedCurve = m_plotTrackDefinition->curveDefinitionFromCurve( closestCurve ); - if ( selectedCurve ) - { - RiuPlotMainWindowTools::showPlotMainWindow(); - RiuPlotMainWindowTools::selectAsCurrentItem( selectedCurve ); - - return; - } - } - - RiuPlotMainWindowTools::showPlotMainWindow(); - RiuPlotMainWindowTools::selectAsCurrentItem( m_plotTrackDefinition ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -int RiuWellLogTrack::defaultMinimumWidth() -{ - return 80; -} +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RiuWellLogTrack.h" + +#include "RimWellLogTrack.h" + +#include + +#define RIU_SCROLLWHEEL_ZOOMFACTOR 1.1 +#define RIU_SCROLLWHEEL_PANFACTOR 0.1 + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellLogTrack::RiuWellLogTrack( RimWellLogTrack* plotTrackDefinition, QWidget* parent /*= nullptr */ ) + : RiuQwtPlotWidget( plotTrackDefinition, parent ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellLogTrack::~RiuWellLogTrack() {} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuWellLogTrack::eventFilter( QObject* watched, QEvent* event ) +{ + QWheelEvent* wheelEvent = dynamic_cast( event ); + if ( wheelEvent && watched == canvas() ) + { + RimWellLogTrack* track = dynamic_cast( plotDefinition() ); + CAF_ASSERT( track ); + + RimWellLogPlot* wellLogPlot = nullptr; + track->firstAncestorOrThisOfType( wellLogPlot ); + + if ( wellLogPlot ) + { + if ( wheelEvent->modifiers() & Qt::ControlModifier ) + { + QwtScaleMap scaleMap = canvasMap( QwtPlot::yLeft ); + double zoomCenter = scaleMap.invTransform( wheelEvent->pos().y() ); + + if ( wheelEvent->delta() > 0 ) + { + wellLogPlot->setDepthAxisRangeByFactorAndCenter( RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter ); + } + else + { + wellLogPlot->setDepthAxisRangeByFactorAndCenter( 1.0 / RIU_SCROLLWHEEL_ZOOMFACTOR, zoomCenter ); + } + } + else + { + wellLogPlot->setDepthAxisRangeByPanDepth( wheelEvent->delta() < 0 ? RIU_SCROLLWHEEL_PANFACTOR + : -RIU_SCROLLWHEEL_PANFACTOR ); + } + + event->accept(); + return true; + } + } + return RiuQwtPlotWidget::eventFilter( watched, event ); +} diff --git a/ApplicationCode/UserInterface/RiuWellLogTrack.h b/ApplicationCode/UserInterface/RiuWellLogTrack.h index f569995eb7..7915ae2632 100644 --- a/ApplicationCode/UserInterface/RiuWellLogTrack.h +++ b/ApplicationCode/UserInterface/RiuWellLogTrack.h @@ -1,86 +1,40 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2015- Statoil ASA -// Copyright (C) 2015- Ceetron Solutions AS -// -// 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 "qwt_plot.h" - -#include "cafPdmPointer.h" - -class RimWellLogTrack; - -class QwtLegend; -class QwtPicker; -class QwtPlotGrid; -class QwtPlotMarker; - -class QEvent; - -//================================================================================================== -// -// -// -//================================================================================================== -class RiuWellLogTrack : public QwtPlot -{ - Q_OBJECT - -public: - RiuWellLogTrack( RimWellLogTrack* plotTrackDefinition, QWidget* parent = nullptr ); - ~RiuWellLogTrack() override; - - void setDepthZoom( double minDepth, double maxDepth ); - void setDepthTitle( const QString& title ); - void setXTitle( const QString& title ); - - void setXRange( double min, double max, QwtPlot::Axis axis = QwtPlot::xTop ); - - bool isRimTrackVisible(); - void enableDepthAxisLabelsAndTicks( bool enable ); - int widthScaleFactor() const; - void enableXGridLines( bool majorGridLines, bool minorGridLines ); - void enableDepthGridLines( bool majorGridLines, bool minorGridLines ); - void setMajorAndMinorTickIntervals( double majorTickInterval, double minorTickInterval ); - void setAutoTickIntervalCounts( int maxMajorTickIntervalCount, int maxMinorTickIntervalCount ); - double getCurrentMajorTickInterval() const; - double getCurrentMinorTickInterval() const; - int axisExtent( QwtPlot::Axis axis ) const; - bool frameIsInFrontOfThis( const QRect& frameGeometry ); - QPoint dragStartPosition() const; - void setDefaultStyleSheet(); - void setStyleSheetForThisObject( const QString& content, const QString& state = "" ); - - RimWellLogTrack* plotDefinition() const; - -protected: - bool eventFilter( QObject* watched, QEvent* event ) override; - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - void mousePressEvent( QMouseEvent* event ) override; - void mouseMoveEvent( QMouseEvent* event ) override; - -private: - void setDefaults(); - void selectClosestCurve( const QPoint& pos ); - static int defaultMinimumWidth(); - -private: - caf::PdmPointer m_plotTrackDefinition; - QPoint m_dragStartPosition; -}; +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015- Statoil ASA +// Copyright (C) 2015- Ceetron Solutions AS +// +// 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 "RiuQwtPlotWidget.h" + +class RimWellLogTrack; + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuWellLogTrack : public RiuQwtPlotWidget +{ + Q_OBJECT + +public: + RiuWellLogTrack( RimWellLogTrack* plotTrackDefinition, QWidget* parent = nullptr ); + ~RiuWellLogTrack() override; + +protected: + bool eventFilter( QObject* watched, QEvent* event ) override; +}; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp index a0b0e7c16e..53e42213c2 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.cpp @@ -171,6 +171,14 @@ void PdmUiTreeView::selectAsCurrentItem(const PdmUiItem* uiItem) m_treeViewEditor->selectAsCurrentItem(uiItem); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiTreeView::selectItems(const std::vector& uiItems) +{ + m_treeViewEditor->selectItems(uiItems); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h index d3d254082e..8c29f16f08 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeView.h @@ -76,6 +76,7 @@ public: void selectedUiItems(std::vector& objects); // TODO: rename void selectAsCurrentItem(const PdmUiItem* uiItem); + void selectItems(const std::vector& uiItems); void setExpanded(const PdmUiItem* uiItem, bool doExpand) const ; // QModelIndex access diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp index 92158274a2..b3d6f44e2d 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp @@ -316,9 +316,36 @@ PdmChildArrayFieldHandle* PdmUiTreeViewEditor::currentChildArrayFieldHandle() void PdmUiTreeViewEditor::selectAsCurrentItem(const PdmUiItem* uiItem) { QModelIndex index = m_treeViewModel->findModelIndex(uiItem); + QModelIndex currentIndex = m_treeView->currentIndex(); + + m_treeView->clearSelection(); + m_treeView->setCurrentIndex(index); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiTreeViewEditor::selectItems(std::vector uiItems) +{ + m_treeView->clearSelection(); + + if (uiItems.empty()) + { + return; + } + + QModelIndex index = findModelIndex(uiItems.back()); + m_treeView->setCurrentIndex(index); + + for (const PdmUiItem* uiItem : uiItems) + { + QModelIndex itemIndex = findModelIndex(uiItem); + m_treeView->selectionModel()->select(itemIndex, QItemSelectionModel::Select); + } + m_treeView->setFocus(Qt::MouseFocusReason); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -391,7 +418,6 @@ void PdmUiTreeViewEditor::updateSelectionManager() { std::vector items; this->selectedUiItems(items); - SelectionManager::instance()->setSelectedItems(items); } } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h index c73c5e964e..47de8a8126 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h @@ -102,6 +102,7 @@ public: bool isTreeItemEditWidgetActive() const; void selectAsCurrentItem(const PdmUiItem* uiItem); + void selectItems(std::vector uiItems); void selectedUiItems(std::vector& objects); void setExpanded(const PdmUiItem* uiItem, bool doExpand) const;