diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 9a0060af49..c697293d18 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -48,6 +48,7 @@ #include "RimFlowPlotCollection.h" #include "RimFormationNamesCollection.h" #include "RimRftPlotCollection.h" +#include "RimPltPlotCollection.h" #include "RimEclipseCase.h" #include "RimGeoMechCase.h" @@ -61,7 +62,6 @@ #include "RimOilField.h" #include "RimProject.h" #include "RimReservoirCellResultsStorage.h" -#include "RimRftPlotCollection.h" #include "RimScriptCollection.h" #include "RimSummaryCase.h" #include "RimSummaryCaseMainCollection.h" @@ -77,6 +77,7 @@ #include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RimWellRftPlot.h" +#include "RimWellPltPlot.h" #include "RiuMainPlotWindow.h" #include "RiuMainWindow.h" @@ -622,6 +623,7 @@ void RiaApplication::loadAndUpdatePlotData() RimSummaryPlotCollection* spColl = nullptr; RimFlowPlotCollection* flowColl = nullptr; RimRftPlotCollection* rftColl = nullptr; + RimPltPlotCollection* pltColl = nullptr; if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->wellLogPlotCollection()) { @@ -639,12 +641,17 @@ void RiaApplication::loadAndUpdatePlotData() { rftColl = m_project->mainPlotCollection()->rftPlotCollection(); } + if (m_project->mainPlotCollection() && m_project->mainPlotCollection()->pltPlotCollection()) + { + pltColl = m_project->mainPlotCollection()->pltPlotCollection(); + } size_t plotCount = 0; plotCount += wlpColl ? wlpColl->wellLogPlots().size() : 0; plotCount += spColl ? spColl->summaryPlots().size() : 0; plotCount += flowColl ? flowColl->plotCount() : 0; plotCount += rftColl ? rftColl->rftPlots().size() : 0; + plotCount += pltColl ? pltColl->pltPlots().size() : 0; caf::ProgressInfo plotProgress(plotCount, "Loading Plot Data"); if (wlpColl) @@ -680,6 +687,15 @@ void RiaApplication::loadAndUpdatePlotData() plotProgress.incrementProgress(); } } + + if (pltColl) + { + for (const auto& pltPlot : pltColl->pltPlots()) + { + pltPlot->loadDataAndUpdate(); + plotProgress.incrementProgress(); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake index 9cd2ca9d6b..89da6b44b7 100644 --- a/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/WellLogCommands/CMakeLists_files.cmake @@ -10,6 +10,8 @@ ${CEE_CURRENT_LIST_DIR}RicNewWellLogCurveExtractionFeature.h ${CEE_CURRENT_LIST_DIR}RicNewWellLogRftCurveFeature.h ${CEE_CURRENT_LIST_DIR}RicNewRftPlotFeature.h ${CEE_CURRENT_LIST_DIR}RicDeleteRftPlotFeature.h +${CEE_CURRENT_LIST_DIR}RicNewPltPlotFeature.h +${CEE_CURRENT_LIST_DIR}RicDeletePltPlotFeature.h ${CEE_CURRENT_LIST_DIR}RicNewWellLogFileCurveFeature.h ${CEE_CURRENT_LIST_DIR}RicNewWellLogPlotFeature.h ${CEE_CURRENT_LIST_DIR}RicNewWellLogPlotFeatureImpl.h @@ -33,6 +35,8 @@ ${CEE_CURRENT_LIST_DIR}RicNewWellLogCurveExtractionFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewWellLogRftCurveFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewRftPlotFeature.cpp ${CEE_CURRENT_LIST_DIR}RicDeleteRftPlotFeature.cpp +${CEE_CURRENT_LIST_DIR}RicNewPltPlotFeature.cpp +${CEE_CURRENT_LIST_DIR}RicDeletePltPlotFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewWellLogFileCurveFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewWellLogPlotFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewWellLogPlotFeatureImpl.cpp diff --git a/ApplicationCode/Commands/WellLogCommands/RicDeletePltPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicDeletePltPlotFeature.cpp new file mode 100644 index 0000000000..b50eda24b8 --- /dev/null +++ b/ApplicationCode/Commands/WellLogCommands/RicDeletePltPlotFeature.cpp @@ -0,0 +1,78 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicDeletePltPlotFeature.h" + +#include "RimPltPlotCollection.h" +#include "RimWellPltPlot.h" +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT(RicDeletePltPlotFeature, "RicDeletePltPlotFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicDeletePltPlotFeature::isCommandEnabled() +{ + std::vector objects; + caf::SelectionManager::instance()->objectsByType(&objects); + + if (objects.size() > 0) + { + return true; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicDeletePltPlotFeature::onActionTriggered(bool isChecked) +{ + std::vector selectedPlots; + caf::SelectionManager::instance()->objectsByType(&selectedPlots); + + if (selectedPlots.size() == 0) return; + + RimWellPltPlot* firstPlot = selectedPlots[0]; + + RimPltPlotCollection* pltPlotCollection = nullptr; + firstPlot->firstAncestorOrThisOfType(pltPlotCollection); + if (!pltPlotCollection) return; + + for (RimWellPltPlot* plot : selectedPlots) + { + pltPlotCollection->removePlot(plot); + delete plot; + } + + pltPlotCollection->uiCapability()->updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicDeletePltPlotFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Delete PLT Plot"); + actionToSetup->setIcon(QIcon(":/Erase.png")); +} diff --git a/ApplicationCode/Commands/WellLogCommands/RicDeletePltPlotFeature.h b/ApplicationCode/Commands/WellLogCommands/RicDeletePltPlotFeature.h new file mode 100644 index 0000000000..77f5078983 --- /dev/null +++ b/ApplicationCode/Commands/WellLogCommands/RicDeletePltPlotFeature.h @@ -0,0 +1,36 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicDeletePltPlotFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; +protected: + + // Overrides + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp b/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp new file mode 100644 index 0000000000..234c5f168c --- /dev/null +++ b/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.cpp @@ -0,0 +1,184 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicNewPltPlotFeature.h" + +#include "RicWellLogPlotCurveFeatureImpl.h" +#include "RicNewWellLogPlotFeatureImpl.h" + +#include "RiaApplication.h" + +#include "RigWellLogCurveData.h" + +#include "RimProject.h" +#include "RimSimWellInView.h" +#include "RimView.h" +#include "RimWellLogExtractionCurve.h" +#include "RimWellPltPlot.h" +#include "RimWellLogPlot.h" +#include "RimWellLogTrack.h" +#include "RimWellPath.h" +#include "RimPltPlotCollection.h" +#include "RimMainPlotCollection.h" +#include "RimEclipseResultCase.h" + +#include "RiuMainPlotWindow.h" +#include "RiuSelectionManager.h" + +#include "cafSelectionManagerTools.h" + +#include + +#include + + +CAF_CMD_SOURCE_INIT(RicNewPltPlotFeature, "RicNewPltPlotFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewPltPlotFeature::isCommandEnabled() +{ + if (RicWellLogPlotCurveFeatureImpl::parentWellAllocationPlot()) return false; + + RimSimWellInView* simWell = caf::firstAncestorOfTypeFromSelectedObject(); + RimWellPath* rimWellPath = simWell == nullptr ? caf::firstAncestorOfTypeFromSelectedObject() : nullptr; + + bool enable = true; + if (simWell != nullptr) + { + RimEclipseResultCase* eclCase = caf::firstAncestorOfTypeFromSelectedObject(); + if (simWell != nullptr) + { + enable &= RimWellPltPlot::hasPressureData(eclCase); + } + } + else if (rimWellPath) + { + enable &= RimWellPltPlot::hasPressureData(rimWellPath); + } + return enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPltPlotFeature::onActionTriggered(bool isChecked) +{ + RimProject* proj = RiaApplication::instance()->project(); + + RimPltPlotCollection* pltPlotColl = proj->mainPlotCollection()->pltPlotCollection(); + if (pltPlotColl) + { + QString wellName; + RimWellPath* wellPath = nullptr; + RimSimWellInView* eclipseWell = nullptr; + if ((wellPath = caf::firstAncestorOfTypeFromSelectedObject()) != nullptr) + { + wellName = wellPath->name(); + } + else if ((eclipseWell = caf::firstAncestorOfTypeFromSelectedObject()) != nullptr) + { + wellName = eclipseWell->name(); + } + + QString plotName = QString(RimWellPltPlot::plotNameFormatString()).arg(wellName); + + RimWellPltPlot* pltPlot = new RimWellPltPlot(); + pltPlot->setCurrentWellName(wellName); + + RimWellLogTrack* plotTrack = new RimWellLogTrack(); + pltPlot->wellLogPlot()->addTrack(plotTrack); + plotTrack->setDescription(QString("Track %1").arg(pltPlot->wellLogPlot()->trackCount())); + + pltPlotColl->addPlot(pltPlot); + pltPlot->setDescription(plotName); + + pltPlot->applyInitialSelections(); + pltPlot->loadDataAndUpdate(); + pltPlotColl->updateConnectedEditors(); + + RiuMainPlotWindow* mainPlotWindow = RiaApplication::instance()->getOrCreateAndShowMainPlotWindow(); + if (mainPlotWindow) + { + mainPlotWindow->setExpanded(plotTrack); + mainPlotWindow->selectAsCurrentItem(pltPlot); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewPltPlotFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("New PLT Plot"); + actionToSetup->setIcon(QIcon(":/SummaryPlot16x16.png")); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogTrack* RicNewPltPlotFeature::selectedWellLogPlotTrack() const +{ + auto selection = caf::selectedObjectsByType(); + return selection.size() > 0 ? selection[0] : nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath* RicNewPltPlotFeature::selectedWellPath() const +{ + auto selection = caf::selectedObjectsByType(); + return selection.size() > 0 ? selection[0] : nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimSimWellInView* RicNewPltPlotFeature::selectedSimulationWell(int * branchIndex) const +{ + RiuSelectionItem* selItem = RiuSelectionManager::instance()->selectedItem(RiuSelectionManager::RUI_TEMPORARY); + RiuSimWellSelectionItem* simWellSelItem = dynamic_cast(selItem); + if (simWellSelItem) + { + (*branchIndex) = static_cast(simWellSelItem->m_branchIndex); + return simWellSelItem->m_simWell; + } + else + { + std::vector selection; + caf::SelectionManager::instance()->objectsByType(&selection); + (*branchIndex) = 0; + return selection.size() > 0 ? selection[0] : nullptr; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewPltPlotFeature::caseAvailable() const +{ + std::vector cases; + RiaApplication::instance()->project()->allCases(cases); + + return cases.size() > 0; +} + diff --git a/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.h b/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.h new file mode 100644 index 0000000000..140e7d5b78 --- /dev/null +++ b/ApplicationCode/Commands/WellLogCommands/RicNewPltPlotFeature.h @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafCmdFeature.h" + +class RimSimWellInView; +class RimView; +class RimWellLogExtractionCurve; +class RimWellLogTrack; +class RimWellPath; +class RimPltPlotCollection; +class RimWellPltPlot; + + +//================================================================================================== +/// +//================================================================================================== +class RicNewPltPlotFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + // Overrides + virtual bool isCommandEnabled(); + virtual void onActionTriggered( bool isChecked ); + virtual void setupActionLook( QAction* actionToSetup ); + +private: + RimWellLogTrack* selectedWellLogPlotTrack() const; + RimWellPath* selectedWellPath() const; + RimSimWellInView* selectedSimulationWell(int * branchIndex) const; + bool caseAvailable() const; +}; + diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 5f69d87b31..b0207bc356 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -66,6 +66,7 @@ ${CEE_CURRENT_LIST_DIR}RimViewController.h ${CEE_CURRENT_LIST_DIR}RimMainPlotCollection.h ${CEE_CURRENT_LIST_DIR}RimWellLogPlotCollection.h ${CEE_CURRENT_LIST_DIR}RimRftPlotCollection.h +${CEE_CURRENT_LIST_DIR}RimPltPlotCollection.h ${CEE_CURRENT_LIST_DIR}RimWellLogPlot.h ${CEE_CURRENT_LIST_DIR}RimWellLogTrack.h ${CEE_CURRENT_LIST_DIR}RimWellLogCurve.h @@ -166,6 +167,7 @@ ${CEE_CURRENT_LIST_DIR}RimViewController.cpp ${CEE_CURRENT_LIST_DIR}RimMainPlotCollection.cpp ${CEE_CURRENT_LIST_DIR}RimWellLogPlotCollection.cpp ${CEE_CURRENT_LIST_DIR}RimRftPlotCollection.cpp +${CEE_CURRENT_LIST_DIR}RimPltPlotCollection.cpp ${CEE_CURRENT_LIST_DIR}RimWellLogPlot.cpp ${CEE_CURRENT_LIST_DIR}RimWellLogTrack.cpp ${CEE_CURRENT_LIST_DIR}RimWellLogCurve.cpp diff --git a/ApplicationCode/ProjectDataModel/Flow/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/Flow/CMakeLists_files.cmake index 09b9e98d8a..5c86380848 100644 --- a/ApplicationCode/ProjectDataModel/Flow/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/Flow/CMakeLists_files.cmake @@ -14,6 +14,7 @@ ${CEE_CURRENT_LIST_DIR}RimWellFlowRateCurve.h ${CEE_CURRENT_LIST_DIR}RimWellAllocationPlotLegend.h ${CEE_CURRENT_LIST_DIR}RimFlowCharacteristicsPlot.h ${CEE_CURRENT_LIST_DIR}RimWellRftPlot.h +${CEE_CURRENT_LIST_DIR}RimWellPltPlot.h ${CEE_CURRENT_LIST_DIR}RimWellRftAddress.h ) @@ -27,6 +28,7 @@ ${CEE_CURRENT_LIST_DIR}RimWellFlowRateCurve.cpp ${CEE_CURRENT_LIST_DIR}RimWellAllocationPlotLegend.cpp ${CEE_CURRENT_LIST_DIR}RimFlowCharacteristicsPlot.cpp ${CEE_CURRENT_LIST_DIR}RimWellRftPlot.cpp +${CEE_CURRENT_LIST_DIR}RimWellPltPlot.cpp ${CEE_CURRENT_LIST_DIR}RimWellRftAddress.cpp ) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp new file mode 100644 index 0000000000..7f77a34b2b --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.cpp @@ -0,0 +1,1331 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 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 "RimWellPltPlot.h" + +#include "RiaApplication.h" +#include "RiaColorTables.h" +#include "RiaDateStringParser.h" +#include "RifReaderEclipseRft.h" +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" +#include "RigSimWellData.h" +#include "RigWellPath.h" +#include "RimEclipseCase.h" +#include "RimEclipseCaseCollection.h" +#include "RimEclipseResultCase.h" +#include "RimEclipseResultDefinition.h" +#include "RimOilField.h" +#include "RimProject.h" +#include "RimTools.h" +#include "RimWellLogExtractionCurve.h" +#include "RimWellLogFile.h" +#include "RimWellLogFileChannel.h" +#include "RimWellLogFileCurve.h" +#include "RimWellLogPlot.h" +#include "RimWellLogRftCurve.h" +#include "RimWellLogTrack.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" +#include "RiuWellPltPlot.h" +#include "cafPdmUiTreeSelectionEditor.h" +#include +#include +#include + +CAF_PDM_SOURCE_INIT(RimWellPltPlot, "WellPltPlot"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const char RimWellPltPlot::PRESSURE_DATA_NAME[] = "PRESSURE"; +const char RimWellPltPlot::PLOT_NAME_QFORMAT_STRING[] = "RFT: %1"; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPltPlot::RimWellPltPlot() +{ + CAF_PDM_InitObject("Well Allocation Plot", ":/WellAllocPlot16x16.png", "", ""); + + CAF_PDM_InitField(&m_userName, "PlotDescription", QString("RFT Plot"), "Name", "", "", ""); + m_userName.uiCapability()->setUiReadOnly(true); + + CAF_PDM_InitField(&m_showPlotTitle, "ShowPlotTitle", true, "Show Plot Title", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_wellLogPlot, "WellLog", "WellLog", "", "", ""); + m_wellLogPlot.uiCapability()->setUiHidden(true); + m_wellLogPlot = new RimWellLogPlot(); + m_wellLogPlot->setDepthType(RimWellLogPlot::TRUE_VERTICAL_DEPTH); + + CAF_PDM_InitFieldNoDefault(&m_wellName, "WellName", "WellName", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_branchIndex, "BranchIndex", "BranchIndex", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_selectedSources, "Sources", "Sources", "", "", ""); + m_selectedSources.uiCapability()->setUiEditorTypeName(caf::PdmUiTreeSelectionEditor::uiEditorTypeName()); + m_selectedSources.xmlCapability()->disableIO(); + m_selectedSources.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + m_selectedSources.uiCapability()->setAutoAddingOptionFromValue(false); + + CAF_PDM_InitFieldNoDefault(&m_selectedTimeSteps, "TimeSteps", "TimeSteps", "", "", ""); + m_selectedTimeSteps.uiCapability()->setUiEditorTypeName(caf::PdmUiTreeSelectionEditor::uiEditorTypeName()); + m_selectedTimeSteps.xmlCapability()->disableIO(); + m_selectedTimeSteps.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + m_selectedTimeSteps.uiCapability()->setAutoAddingOptionFromValue(false); + + this->setAsPlotMdiWindow(); + m_selectedSourcesOrTimeStepsFieldsChanged = false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPltPlot::~RimWellPltPlot() +{ + removeMdiWindowFromMdiArea(); + + deleteViewWidget(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::deleteViewWidget() +{ + if (m_wellLogPlotWidget) + { + m_wellLogPlotWidget->deleteLater(); + m_wellLogPlotWidget = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::applyCurveAppearance(RimWellLogCurve* newCurve) +{ + const std::pair& newCurveDef = curveDefFromCurve(newCurve); + + std::vector colorTable; + RiaColorTables::summaryCurveDefaultPaletteColors().color3fArray().toStdVector(&colorTable); + + std::vector symbolTable = + { + RimPlotCurve::SYMBOL_ELLIPSE, + RimPlotCurve::SYMBOL_RECT, + RimPlotCurve::SYMBOL_DIAMOND, + RimPlotCurve::SYMBOL_TRIANGLE, + RimPlotCurve::SYMBOL_CROSS, + RimPlotCurve::SYMBOL_XCROSS + }; + + // State variables + static size_t defaultColorTableIndex = 0; + static size_t defaultSymbolTableIndex = 0; + + cvf::Color3f currentColor; + RimPlotCurve::PointSymbolEnum currentSymbol = symbolTable.front(); + RimPlotCurve::LineStyleEnum currentLineStyle = RimPlotCurve::STYLE_SOLID; + bool isCurrentColorSet = false; + bool isCurrentSymbolSet = false; + + std::set assignedColors; + std::set assignedSymbols; + + // Used colors and symbols + for (RimWellLogCurve* const curve : m_wellLogPlot->trackByIndex(0)->curvesVector()) + { + if (curve == newCurve) continue; + + std::pair cDef = curveDefFromCurve(curve); + if (cDef.first == newCurveDef.first) + { + currentColor = curve->color(); + isCurrentColorSet = true; + } + if (cDef.second == newCurveDef.second) + { + currentSymbol = curve->symbol(); + isCurrentSymbolSet = true; + } + assignedColors.insert(curve->color()); + assignedSymbols.insert(curve->symbol()); + } + + // Assign color + if (!isCurrentColorSet) + { + for(const auto& color : colorTable) + { + if (assignedColors.count(color) == 0) + { + currentColor = color; + isCurrentColorSet = true; + break; + } + } + if (!isCurrentColorSet) + { + currentColor = colorTable[defaultColorTableIndex]; + if (++defaultColorTableIndex == colorTable.size()) + defaultColorTableIndex = 0; + + } + } + + // Assign symbol + if (!isCurrentSymbolSet) + { + for (const auto& symbol : symbolTable) + { + if (assignedSymbols.count(symbol) == 0) + { + currentSymbol = symbol; + isCurrentSymbolSet = true; + break; + } + } + if (!isCurrentSymbolSet) + { + currentSymbol = symbolTable[defaultSymbolTableIndex]; + if (++defaultSymbolTableIndex == symbolTable.size()) + defaultSymbolTableIndex = 0; + } + } + + // Observed data + currentLineStyle = newCurveDef.first.sourceType() == RftSourceType::OBSERVED + ? RimPlotCurve::STYLE_NONE : RimPlotCurve::STYLE_SOLID; + + newCurve->setColor(currentColor); + newCurve->setSymbol(currentSymbol); + newCurve->setLineStyle(currentLineStyle); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::updateSelectedTimeStepsFromSelectedSources() +{ + std::vector newTimeStepsSelections; + std::vector selectedSourcesVector = selectedSources(); + auto selectedSources = std::set(selectedSourcesVector.begin(), selectedSourcesVector.end()); + + for (const QDateTime& timeStep : m_selectedTimeSteps()) + { + if(m_timeStepsToAddresses.count(timeStep) > 0) + { + std::vector intersectVector; + const std::set& addresses = m_timeStepsToAddresses[timeStep]; + std::set_intersection(selectedSources.begin(), selectedSources.end(), + addresses.begin(), addresses.end(), std::inserter(intersectVector, intersectVector.end())); + if(intersectVector.size() > 0) + { + newTimeStepsSelections.push_back(timeStep); + } + } + } + m_selectedTimeSteps = newTimeStepsSelections; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::applyInitialSelections() +{ + std::vector> eclCaseTuples = eclipseCasesForWell(m_wellName); + + std::vector sourcesToSelect; + std::map> rftTimeStepsMap; + std::map> observedTimeStepsMap; + std::map> gridTimeStepsMap; + + for(RimEclipseResultCase* const rftCase : rftCasesFromEclipseCases(eclCaseTuples)) + { + sourcesToSelect.push_back(RimWellRftAddress(RftSourceType::RFT, rftCase)); + addTimeStepsToMap(rftTimeStepsMap, timeStepsFromRftCase(rftCase)); + } + + for (RimEclipseResultCase* const gridCase : gridCasesFromEclipseCases(eclCaseTuples)) + { + sourcesToSelect.push_back(RimWellRftAddress(RftSourceType::GRID, gridCase)); + addTimeStepsToMap(gridTimeStepsMap, timeStepsFromGridCase(gridCase)); + } + + std::vector wellLogFiles = wellLogFilesContainingPressure(m_wellName); + if(wellLogFiles.size() > 0) + { + sourcesToSelect.push_back(RimWellRftAddress(RftSourceType::OBSERVED)); + for (RimWellLogFile* const wellLogFile : wellLogFiles) + { + addTimeStepsToMap(observedTimeStepsMap, timeStepsFromWellLogFile(wellLogFile)); + } + } + + m_selectedSources = sourcesToSelect; + + std::set timeStepsToSelect; + for (const std::pair>& dateTimePair : rftTimeStepsMap) + { + timeStepsToSelect.insert(dateTimePair.first); + } + for (const std::pair>& dateTimePair : observedTimeStepsMap) + { + timeStepsToSelect.insert(dateTimePair.first); + } + if (gridTimeStepsMap.size() > 0) + timeStepsToSelect.insert((*gridTimeStepsMap.begin()).first); + + m_selectedTimeSteps = std::vector(timeStepsToSelect.begin(), timeStepsToSelect.end()); + + syncCurvesFromUiSelection(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::updateEditorsFromCurves() +{ + std::set selectedSources; + std::set selectedTimeSteps; + std::map> selectedTimeStepsMap; + + for (const std::pair& curveDef : curveDefsFromCurves()) + { + if (curveDef.first.sourceType() == RftSourceType::OBSERVED) + selectedSources.insert(RimWellRftAddress(RftSourceType::OBSERVED)); + else + selectedSources.insert(curveDef.first); + + auto newTimeStepMap = std::map> + { + { curveDef.second, std::set { curveDef.first} } + }; + addTimeStepsToMap(selectedTimeStepsMap, newTimeStepMap); + selectedTimeSteps.insert(curveDef.second); + } + + m_selectedSources = std::vector(selectedSources.begin(), selectedSources.end()); + m_selectedTimeSteps = std::vector(selectedTimeSteps.begin(), selectedTimeSteps.end()); + addTimeStepsToMap(m_timeStepsToAddresses, selectedTimeStepsMap); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::updateWidgetTitleWindowTitle() +{ + updateMdiWindowTitle(); + + if (m_wellLogPlotWidget) + { + if (m_showPlotTitle) + { + m_wellLogPlotWidget->showTitle(m_userName); + } + else + { + m_wellLogPlotWidget->hideTitle(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::syncCurvesFromUiSelection() +{ + RimWellLogTrack* plotTrack = m_wellLogPlot->trackByIndex(0); + const std::set>& allCurveDefs = selectedCurveDefs(); + const std::set>& curveDefsInPlot = curveDefsFromCurves(); + std::set curvesToDelete; + std::set> newCurveDefs; + + if (allCurveDefs.size() < curveDefsInPlot.size()) + { + // Determine which curves to delete from plot + std::set> deleteCurveDefs; + std::set_difference(curveDefsInPlot.begin(), curveDefsInPlot.end(), + allCurveDefs.begin(), allCurveDefs.end(), + std::inserter(deleteCurveDefs, deleteCurveDefs.end())); + + for (RimWellLogCurve* const curve : plotTrack->curvesVector()) + { + std::pair curveDef = curveDefFromCurve(curve); + if (deleteCurveDefs.count(curveDef) > 0) + curvesToDelete.insert(curve); + } + } + else + { + // Determine which curves are new since last time + std::set_difference(allCurveDefs.begin(), allCurveDefs.end(), + curveDefsInPlot.begin(), curveDefsInPlot.end(), + std::inserter(newCurveDefs, newCurveDefs.end())); + } + updateCurvesInPlot(allCurveDefs, newCurveDefs, curvesToDelete); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellPltPlot::wellLogFilesContainingPressure(const QString& wellName) const +{ + std::vector wellLogFiles; + const RimProject* const project = RiaApplication::instance()->project(); + + for (const auto& oilField : project->oilFields) + { + auto wellPathsVector = std::vector(oilField->wellPathCollection()->wellPaths.begin(), oilField->wellPathCollection()->wellPaths.end()); + + for (const auto& wellPath : wellPathsVector) + { + bool hasPressure = false; + const std::vector files = wellPath->wellLogFiles(); + + for (RimWellLogFile* const file : files) + { + size_t timeStepCount = timeStepsFromWellLogFile(file).size(); + + if (timeStepCount == 0) continue; + if (QString::compare(file->wellName(), wellName) != 0) continue; + + if (hasPressureData(file)) + { + wellLogFiles.push_back(file); + } + } + } + } + return wellLogFiles; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogFileChannel* RimWellPltPlot::getPressureChannelFromWellFile(const RimWellLogFile* wellLogFile) const +{ + if(wellLogFile != nullptr) + { + for (RimWellLogFileChannel* const channel : wellLogFile->wellLogChannels()) + { + if (isPressureChannel(channel)) + { + return channel; + } + } + } + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPath* RimWellPltPlot::wellPathFromWellLogFile(const RimWellLogFile* wellLogFile) const +{ + RimProject* const project = RiaApplication::instance()->project(); + for (const auto& oilField : project->oilFields) + { + auto wellPaths = std::vector(oilField->wellPathCollection()->wellPaths.begin(), oilField->wellPathCollection()->wellPaths.end()); + + for (const auto& wellPath : wellPaths) + { + for (RimWellLogFile* const file : wellPath->wellLogFiles()) + { + if (file == wellLogFile) + { + return wellPath; + } + } + } + } + + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> +RimWellPltPlot::eclipseCasesForWell(const QString& wellName) const +{ + std::vector> cases; + const RimProject* const project = RiaApplication::instance()->project(); + + for (const auto& oilField : project->oilFields) + { + const RimEclipseCaseCollection* const eclCaseColl = oilField->analysisModels(); + for (RimEclipseCase* eCase : eclCaseColl->cases()) + { + auto eclCase = dynamic_cast(eCase); + if (eclCase != nullptr) + { + RigEclipseCaseData* const eclipseCaseData = eclCase->eclipseCaseData(); + for (const cvf::ref& wellResult : eclipseCaseData->wellResults()) + { + if (QString::compare(wellResult->m_wellName, wellName) == 0) + { + bool hasPressure = hasPressureData(eclCase); + bool hasRftData = eclCase->rftReader() != nullptr; + cases.push_back(std::make_tuple(eclCase, hasPressure, hasRftData)); + break; + } + } + } + } + } + return cases; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector +RimWellPltPlot::gridCasesFromEclipseCases(const std::vector>& eclipseCasesTuple) const +{ + std::vector cases; + for (const std::tuple& eclCaseTuple : eclipseCasesTuple) + { + bool hasPressureData = std::get<1>(eclCaseTuple); + size_t timeStepCount = timeStepsFromGridCase(std::get<0>(eclCaseTuple)).size(); + if (hasPressureData && timeStepCount > 0) + { + cases.push_back(std::get<0>(eclCaseTuple)); + } + } + return cases; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector +RimWellPltPlot::rftCasesFromEclipseCases(const std::vector>& eclipseCasesTuple) const +{ + std::vector cases; + for (const std::tuple& eclCaseTuple : eclipseCasesTuple) + { + bool hasRftData = std::get<2>(eclCaseTuple); + size_t timeStepCount = timeStepsFromRftCase(std::get<0>(eclCaseTuple)).size(); + if (hasRftData && timeStepCount > 0) + { + cases.push_back(std::get<0>(eclCaseTuple)); + } + } + return cases; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map> RimWellPltPlot::timeStepsFromRftCase(RimEclipseResultCase* rftCase) const +{ + std::map> timeStepsMap; + RifReaderEclipseRft* const reader = rftCase->rftReader(); + if (reader != nullptr) + { + for (const QDateTime& timeStep : reader->availableTimeSteps(m_wellName, RifEclipseRftAddress::PRESSURE)) + { + if (timeStepsMap.count(timeStep) == 0) + { + timeStepsMap.insert(std::make_pair(timeStep, std::set())); + } + timeStepsMap[timeStep].insert(RimWellRftAddress(RftSourceType::RFT, rftCase)); + } + } + return timeStepsMap; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map> RimWellPltPlot::timeStepsFromGridCase(RimEclipseCase* gridCase) const +{ + const RigEclipseCaseData* const eclipseCaseData = gridCase->eclipseCaseData(); + size_t resultIndex = eclipseCaseData != nullptr ? + eclipseCaseData->results(RiaDefines::MATRIX_MODEL)->findScalarResultIndex(RiaDefines::DYNAMIC_NATIVE, PRESSURE_DATA_NAME) : + cvf::UNDEFINED_SIZE_T; + + std::map> timeStepsMap; + if (resultIndex != cvf::UNDEFINED_SIZE_T) + { + for (const QDateTime& timeStep : eclipseCaseData->results(RiaDefines::MATRIX_MODEL)->timeStepDates(resultIndex)) + { + if (timeStepsMap.count(timeStep) == 0) + { + timeStepsMap.insert(std::make_pair(timeStep, std::set())); + } + timeStepsMap[timeStep].insert(RimWellRftAddress(RftSourceType::GRID, gridCase)); + } + } + return timeStepsMap; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map > RimWellPltPlot::timeStepsFromWellLogFile(RimWellLogFile* wellLogFile) const +{ + std::map > timeStepsMap; + + QDateTime timeStep = RiaDateStringParser::parseDateString(wellLogFile->date()); + + if (timeStepsMap.count(timeStep) == 0) + { + timeStepsMap.insert(std::make_pair(timeStep, std::set())); + } + timeStepsMap[timeStep].insert(RimWellRftAddress(RftSourceType::OBSERVED, wellLogFile)); + + return timeStepsMap; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map> +RimWellPltPlot::adjacentTimeSteps(const std::vector>>& allTimeSteps, + const std::pair>& searchTimeStepPair) +{ + std::map> timeStepsMap; + + if (allTimeSteps.size() > 0) + { + auto itr = std::find_if(allTimeSteps.begin(), allTimeSteps.end(), + [searchTimeStepPair](const std::pair>& dt) + { + return dt.first > searchTimeStepPair.first; + }); + + auto itrEnd = itr != allTimeSteps.end() ? itr + 1 : itr; + + for (itr = itrEnd - 1; itr != allTimeSteps.begin() && (*itr).first >= searchTimeStepPair.first; itr--); + auto itrFirst = itr; + + timeStepsMap.insert(itrFirst, itrEnd); + } + + // Add searched time step in case it is not included + addTimeStepToMap(timeStepsMap, searchTimeStepPair); + + return timeStepsMap; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::mapContainsTimeStep(const std::map>& map, const QDateTime& timeStep) +{ + return std::find_if(map.begin(), map.end(), [timeStep](const std::pair>& pair) + { + return pair.first == timeStep; + }) != map.end(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set < std::pair> RimWellPltPlot::selectedCurveDefs() const +{ + std::set> curveDefs; + const std::vector>& eclipseCases = eclipseCasesForWell(m_wellName); + const std::vector rftCases = rftCasesFromEclipseCases(eclipseCases); + const std::vector gridCases = gridCasesFromEclipseCases(eclipseCases); + + for (const QDateTime& timeStep : m_selectedTimeSteps()) + { + for (const RimWellRftAddress& addr : selectedSources()) + { + if (addr.sourceType() == RftSourceType::RFT) + { + for (RimEclipseResultCase* const rftCase : rftCases) + { + const std::map>& timeStepsMap = timeStepsFromRftCase(rftCase); + if (mapContainsTimeStep(timeStepsMap , timeStep)) + { + curveDefs.insert(std::make_pair(addr, timeStep)); + } + } + } + else if (addr.sourceType() == RftSourceType::GRID) + { + for (RimEclipseResultCase* const gridCase : gridCases) + { + const std::map>& timeStepsMap = timeStepsFromGridCase(gridCase); + if (mapContainsTimeStep(timeStepsMap, timeStep)) + { + curveDefs.insert(std::make_pair(addr, timeStep)); + } + } + } + else if (addr.sourceType() == RftSourceType::OBSERVED) + { + if (addr.wellLogFile() != nullptr) + { + const std::map>& timeStepsMap = timeStepsFromWellLogFile(addr.wellLogFile()); + if (mapContainsTimeStep(timeStepsMap, timeStep)) + { + curveDefs.insert(std::make_pair(RimWellRftAddress(RftSourceType::OBSERVED, addr.wellLogFile()), timeStep)); + } + } + } + } + } + return curveDefs; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set> RimWellPltPlot::curveDefsFromCurves() const +{ + std::set> curveDefs; + + RimWellLogTrack* const plotTrack = m_wellLogPlot->trackByIndex(0); + for (RimWellLogCurve* const curve : plotTrack->curvesVector()) + { + curveDefs.insert(curveDefFromCurve(curve)); + } + return curveDefs; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RimWellPltPlot::curveDefFromCurve(const RimWellLogCurve* curve) const +{ + const RimWellLogRftCurve* rftCurve = dynamic_cast(curve); + const RimWellLogExtractionCurve* gridCurve = dynamic_cast(curve); + const RimWellLogFileCurve* wellLogFileCurve = dynamic_cast(curve); + + if (rftCurve != nullptr) + { + RimEclipseResultCase* rftCase = dynamic_cast(rftCurve->eclipseResultCase()); + if (rftCase != nullptr) + { + const RifEclipseRftAddress rftAddress = rftCurve->rftAddress(); + const QDateTime timeStep = rftAddress.timeStep(); + return std::make_pair(RimWellRftAddress(RftSourceType::RFT, rftCase), timeStep); + } + } + else if (gridCurve != nullptr) + { + RimEclipseResultCase* gridCase = dynamic_cast(gridCurve->rimCase()); + if (gridCase != nullptr) + { + size_t timeStepIndex = gridCurve->currentTimeStep(); + const std::map>& timeStepsMap = timeStepsFromGridCase(gridCase); + auto timeStepsVector = std::vector>>( + timeStepsMap.begin(), timeStepsMap.end()); + if (timeStepIndex < timeStepsMap.size()) + { + return std::make_pair(RimWellRftAddress(RftSourceType::GRID, gridCase), + timeStepsVector[timeStepIndex].first); + } + } + } + else if (wellLogFileCurve != nullptr) + { + const RimWellPath* const wellPath = wellLogFileCurve->wellPath(); + RimWellLogFile* const wellLogFile = wellLogFileCurve->wellLogFile(); + + if (wellLogFile != nullptr) + { + const QDateTime date = RiaDateStringParser::parseDateString(wellLogFile->date()); + + if (date.isValid()) + { + return std::make_pair(RimWellRftAddress(RftSourceType::OBSERVED, wellLogFile), date); + } + } + } + return std::make_pair(RimWellRftAddress(), QDateTime()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::updateCurvesInPlot(const std::set>& allCurveDefs, + const std::set>& curveDefsToAdd, + const std::set& curvesToDelete) +{ + RimWellLogTrack* const plotTrack = m_wellLogPlot->trackByIndex(0); + + // Delete curves + for (RimWellLogCurve* const curve : curvesToDelete) + { + plotTrack->removeCurve(curve); + } + + // Add new curves + for (const std::pair& curveDefToAdd : curveDefsToAdd) + { + if (curveDefToAdd.first.sourceType() == RftSourceType::RFT) + { + auto curve = new RimWellLogRftCurve(); + plotTrack->addCurve(curve); + + auto rftCase = curveDefToAdd.first.eclCase(); + curve->setEclipseResultCase(dynamic_cast(rftCase)); + + RifEclipseRftAddress address(m_wellName, curveDefToAdd.second, RifEclipseRftAddress::PRESSURE); + curve->setRftAddress(address); + curve->setZOrder(1); + + applyCurveAppearance(curve); + curve->loadDataAndUpdate(true); + } + else if (curveDefToAdd.first.sourceType() == RftSourceType::GRID) + { + auto curve = new RimWellLogExtractionCurve(); + plotTrack->addCurve(curve); + + cvf::Color3f curveColor = RiaColorTables::wellLogPlotPaletteColors().cycledColor3f(plotTrack->curveCount()); + curve->setColor(curveColor); + curve->setFromSimulationWellName(m_wellName, m_branchIndex); + + // Fetch cases and time steps + auto gridCase = curveDefToAdd.first.eclCase(); + if (gridCase != nullptr) + { + // Case + curve->setCase(gridCase); + + // Result definition + RimEclipseResultDefinition* resultDef = new RimEclipseResultDefinition(); + resultDef->setResultVariable(PRESSURE_DATA_NAME); + curve->setEclipseResultDefinition(resultDef); + + // Time step + const std::map>& timeSteps = timeStepsFromGridCase(gridCase); + auto currentTimeStepItr = std::find_if(timeSteps.begin(), timeSteps.end(), + [curveDefToAdd](std::pair> pair) {return pair.first == curveDefToAdd.second; }); + auto currentTimeStepIndex = std::distance(timeSteps.begin(), currentTimeStepItr); + curve->setCurrentTimeStep(currentTimeStepIndex); + curve->setZOrder(0); + + applyCurveAppearance(curve); + curve->loadDataAndUpdate(false); + } + } + else if (curveDefToAdd.first.sourceType() == RftSourceType::OBSERVED) + { + RimWellLogFile* const wellLogFile = curveDefToAdd.first.wellLogFile(); + RimWellPath* const wellPath = wellPathFromWellLogFile(wellLogFile); + if(wellLogFile!= nullptr) + { + RimWellLogFileChannel* pressureChannel = getPressureChannelFromWellFile(wellLogFile); + auto curve = new RimWellLogFileCurve(); + plotTrack->addCurve(curve); + curve->setWellPath(wellPath); + curve->setWellLogFile(wellLogFile); + curve->setWellLogChannelName(pressureChannel->name()); + curve->setZOrder(2); + + applyCurveAppearance(curve); + curve->loadDataAndUpdate(true); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::isOnlyGridSourcesSelected() const +{ + const std::vector& selSources = m_selectedSources(); + return std::find_if(selSources.begin(), selSources.end(), [](const RimWellRftAddress& addr) + { + return addr.sourceType() == RftSourceType::RFT || addr.sourceType() == RftSourceType::OBSERVED; + }) == selSources.end(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::isAnySourceAddressSelected(const std::set& addresses) const +{ + const std::vector& selectedSourcesVector = m_selectedSources(); + const auto selectedSources = std::set(selectedSourcesVector.begin(), selectedSourcesVector.end()); + std::vector intersectVector; + + std::set_intersection(selectedSources.begin(), selectedSources.end(), + addresses.begin(), addresses.end(), std::inserter(intersectVector, intersectVector.end())); + return intersectVector.size() > 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellPltPlot::selectedSources() const +{ + std::vector sources; + for (const RimWellRftAddress& addr : m_selectedSources()) + { + if (addr.sourceType() == RftSourceType::OBSERVED) + { + for (RimWellLogFile* const wellLogFile : wellLogFilesContainingPressure(m_wellName)) + { + sources.push_back(RimWellRftAddress(RftSourceType::OBSERVED, wellLogFile)); + } + } + else + sources.push_back(addr); + } + return sources; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* RimWellPltPlot::viewWidget() +{ + return m_wellLogPlotWidget; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::zoomAll() +{ + m_wellLogPlot()->zoomAll(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellLogPlot* RimWellPltPlot::wellLogPlot() const +{ + return m_wellLogPlot(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::setCurrentWellName(const QString& currWellName) +{ + m_wellName = currWellName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellPltPlot::currentWellName() const +{ + return m_wellName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::hasPressureData(const RimWellLogFile* wellLogFile) +{ + for (RimWellLogFileChannel* const wellLogChannel : wellLogFile->wellLogChannels()) + { + if (isPressureChannel(wellLogChannel)) return true; + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::hasPressureData(RimWellPath* wellPath) +{ + for (RimWellLogFile* const wellLogFile : wellPath->wellLogFiles()) + { + if (hasPressureData(wellLogFile)) + { + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::isPressureChannel(RimWellLogFileChannel* channel) +{ + // Todo: read pressure channel names from config/defines + return QString::compare(channel->name(), PRESSURE_DATA_NAME) == 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimWellPltPlot::hasPressureData(RimEclipseResultCase* gridCase) +{ + const RigEclipseCaseData* const eclipseCaseData = gridCase->eclipseCaseData(); + size_t resultIndex = eclipseCaseData->results(RiaDefines::MATRIX_MODEL)-> + findScalarResultIndex(RiaDefines::DYNAMIC_NATIVE, PRESSURE_DATA_NAME); + return resultIndex != cvf::UNDEFINED_SIZE_T; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const char* RimWellPltPlot::plotNameFormatString() +{ + return PLOT_NAME_QFORMAT_STRING; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimWellPltPlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +{ + QList options; + + if (fieldNeedingOptions == &m_wellName) + { + calculateValueOptionsForWells(options); + } + else if (fieldNeedingOptions == &m_selectedSources) + { + const std::vector>& eclipseCases = eclipseCasesForWell(m_wellName); + + const std::vector rftCases = rftCasesFromEclipseCases(eclipseCases); + if (rftCases.size() > 0) + { + options.push_back(caf::PdmOptionItemInfo::createHeader(RimWellRftAddress::sourceTypeUiText(RftSourceType::RFT), true)); + } + for (const auto& rftCase : rftCases) + { + auto addr = RimWellRftAddress(RftSourceType::RFT, rftCase); + auto item = caf::PdmOptionItemInfo(rftCase->caseUserDescription(), QVariant::fromValue(addr)); + item.setLevel(1); + options.push_back(item); + } + + const std::vector gridCases = gridCasesFromEclipseCases(eclipseCases); + if (gridCases.size() > 0) + { + options.push_back(caf::PdmOptionItemInfo::createHeader(RimWellRftAddress::sourceTypeUiText(RftSourceType::GRID), true)); + } + for (const auto& gridCase : gridCases) + { + auto addr = RimWellRftAddress(RftSourceType::GRID, gridCase); + auto item = caf::PdmOptionItemInfo(gridCase->caseUserDescription(), QVariant::fromValue(addr)); + item.setLevel(1); + options.push_back(item); + } + + if (wellLogFilesContainingPressure(m_wellName).size() > 0) + { + options.push_back(caf::PdmOptionItemInfo::createHeader(RimWellRftAddress::sourceTypeUiText(RftSourceType::OBSERVED), true)); + + auto addr = RimWellRftAddress(RftSourceType::OBSERVED); + auto item = caf::PdmOptionItemInfo("Observed Data", QVariant::fromValue(addr)); + item.setLevel(1); + options.push_back(item); + } + } + else if (fieldNeedingOptions == &m_selectedTimeSteps) + { + calculateValueOptionsForTimeSteps(m_wellName, options); + } + else if (fieldNeedingOptions == &m_branchIndex) + { + RimProject* proj = RiaApplication::instance()->project(); + + size_t branchCount = proj->simulationWellBranches(m_wellName).size(); + + for (int bIdx = 0; bIdx < static_cast(branchCount); ++bIdx) + { + options.push_back(caf::PdmOptionItemInfo("Branch " + QString::number(bIdx + 1), QVariant::fromValue(bIdx))); + } + + if (options.size() == 0) + { + options.push_front(caf::PdmOptionItemInfo("None", -1)); + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + RimViewWindow::fieldChangedByUi(changedField, oldValue, newValue); + + if (changedField == &m_wellName) + { + setDescription(QString(plotNameFormatString()).arg(m_wellName)); + } + + if (changedField == &m_wellName || changedField == &m_branchIndex) + { + RimWellLogTrack* const plotTrack = m_wellLogPlot->trackByIndex(0); + for (RimWellLogCurve* const curve : plotTrack->curvesVector()) + { + plotTrack->removeCurve(curve); + } + m_timeStepsToAddresses.clear(); + updateEditorsFromCurves(); + } + else if (changedField == &m_selectedSources) + { + // Update time steps selections based on source selections + updateSelectedTimeStepsFromSelectedSources(); + } + + if (changedField == &m_selectedSources || + changedField == &m_selectedTimeSteps) + { + syncCurvesFromUiSelection(); + m_selectedSourcesOrTimeStepsFieldsChanged = true; + } + else if (changedField == &m_showPlotTitle) + { + //m_wellLogPlot->setShowDescription(m_showPlotTitle); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QImage RimWellPltPlot::snapshotWindowContent() +{ + QImage image; + + if (m_wellLogPlotWidget) + { + QPixmap pix = QPixmap::grabWidget(m_wellLogPlotWidget); + image = pix.toImage(); + } + + return image; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + if (!m_selectedSourcesOrTimeStepsFieldsChanged) + { + updateEditorsFromCurves(); + } + m_selectedSourcesOrTimeStepsFieldsChanged = false; + + uiOrdering.add(&m_userName); + uiOrdering.add(&m_wellName); + + RimProject* proj = RiaApplication::instance()->project(); + if (proj->simulationWellBranches(m_wellName).size() > 1) + { + uiOrdering.add(&m_branchIndex); + } + + caf::PdmUiGroup* sourcesGroup = uiOrdering.addNewGroupWithKeyword("Sources", "Sources"); + sourcesGroup->add(&m_selectedSources); + + caf::PdmUiGroup* timeStepsGroup = uiOrdering.addNewGroupWithKeyword("Time Steps", "TimeSteps"); + timeStepsGroup->add(&m_selectedTimeSteps); + + //uiOrdering.add(&m_showPlotTitle); + + uiOrdering.skipRemainingFields(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::addTimeStepToMap(std::map>& destMap, + const std::pair>& timeStepToAdd) +{ + auto timeStepMapToAdd = std::map> { timeStepToAdd }; + addTimeStepsToMap(destMap, timeStepMapToAdd); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::addTimeStepsToMap(std::map>& destMap, + const std::map>& timeStepsToAdd) +{ + for (const auto& timeStepPair : timeStepsToAdd) + { + if (timeStepPair.first.isValid()) + { + if (destMap.count(timeStepPair.first) == 0) + { + destMap.insert(std::make_pair(timeStepPair.first, std::set())); + } + auto addresses = timeStepPair.second; + destMap[timeStepPair.first].insert(addresses.begin(), addresses.end()); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::calculateValueOptionsForWells(QList& options) +{ + RimProject * proj = RiaApplication::instance()->project(); + + if (proj != nullptr) + { + const std::vector simWellNames = proj->simulationWellNames(); + auto wellNames = std::set(simWellNames.begin(), simWellNames.end()); + + // Observed wells + for (const auto& oilField : proj->oilFields()) + { + auto wellPathColl = oilField->wellPathCollection(); + for (const auto& wellPath : wellPathColl->wellPaths) + { + wellNames.insert(wellPath->name()); + } + } + + for (const auto& wellName : wellNames) + { + options.push_back(caf::PdmOptionItemInfo(wellName, wellName)); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::calculateValueOptionsForTimeSteps(const QString& wellName, QList& options) +{ + std::map> displayTimeStepsMap, obsAndRftTimeStepsMap, gridTimeStepsMap; + const std::vector>& eclipseCases = eclipseCasesForWell(wellName); + const std::vector rftCases = rftCasesFromEclipseCases(eclipseCases); + const std::vector gridCases = gridCasesFromEclipseCases(eclipseCases); + + for (const RimWellRftAddress& selection : selectedSources()) + { + if (selection.sourceType() == RftSourceType::RFT) + { + for (RimEclipseResultCase* const rftCase : rftCases) + { + addTimeStepsToMap(obsAndRftTimeStepsMap, timeStepsFromRftCase(rftCase)); + } + } + else if (selection.sourceType() == RftSourceType::GRID) + { + for (RimEclipseResultCase* const gridCase : gridCases) + { + addTimeStepsToMap(gridTimeStepsMap, timeStepsFromGridCase(gridCase)); + } + } + else if (selection.sourceType() == RftSourceType::OBSERVED) + { + if (selection.wellLogFile() != nullptr) + { + addTimeStepsToMap(obsAndRftTimeStepsMap, timeStepsFromWellLogFile(selection.wellLogFile())); + } + } + } + + if (isOnlyGridSourcesSelected()) + { + displayTimeStepsMap = gridTimeStepsMap; + } + else + { + const auto gridTimeStepsVector = std::vector>>(gridTimeStepsMap.begin(), gridTimeStepsMap.end()); + + for (const std::pair>& timeStepPair : obsAndRftTimeStepsMap) + { + const std::map>& adjTimeSteps = adjacentTimeSteps(gridTimeStepsVector, timeStepPair); + addTimeStepsToMap(displayTimeStepsMap, adjTimeSteps); + } + + // Add the first grid time step (from the total grid time steps list) + if (gridTimeStepsVector.size() > 0) + { + addTimeStepToMap(displayTimeStepsMap, gridTimeStepsVector.front()); + } + + // Add already selected time steps + for (const QDateTime& timeStep : m_selectedTimeSteps()) + { + if (m_timeStepsToAddresses.count(timeStep) > 0) + { + const std::set sourceAddresses = m_timeStepsToAddresses[timeStep]; + if (isAnySourceAddressSelected(sourceAddresses)) + { + addTimeStepToMap(displayTimeStepsMap, std::make_pair(timeStep, m_timeStepsToAddresses[timeStep])); + } + } + } + } + + addTimeStepsToMap(m_timeStepsToAddresses, displayTimeStepsMap); + + // Create vector of all time steps + std::vector allTimeSteps; + for (const std::pair>& timeStepPair : m_timeStepsToAddresses) + { + allTimeSteps.push_back(timeStepPair.first); + } + + const QString dateFormatString = RimTools::createTimeFormatStringFromDates(allTimeSteps); + for (const std::pair>& timeStepPair : displayTimeStepsMap) + { + options.push_back(caf::PdmOptionItemInfo(timeStepPair.first.toString(dateFormatString), timeStepPair.first)); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::setDescription(const QString& description) +{ + m_userName = description; + + updateWidgetTitleWindowTitle(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimWellPltPlot::description() const +{ + return m_userName(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellPltPlot::loadDataAndUpdate() +{ + updateMdiWindowVisibility(); + m_wellLogPlot->loadDataAndUpdate(); + updateEditorsFromCurves(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QWidget* RimWellPltPlot::createViewWidget(QWidget* mainWindowParent) +{ + m_wellLogPlotWidget = new RiuWellPltPlot(this, mainWindowParent); + return m_wellLogPlotWidget; +} + diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.h new file mode 100644 index 0000000000..44f80aec98 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellPltPlot.h @@ -0,0 +1,165 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 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 "RimViewWindow.h" + +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPtrField.h" +#include "cvfCollection.h" +#include "RimWellRftAddress.h" +#include "RimPlotCurve.h" +#include +#include +#include +#include +#include + + +class RimEclipseCase; +class RimEclipseResultCase; +class RimWellLogCurve; +class RimWellLogFileChannel; +class RimWellLogPlot; +class RimWellPath; +class RiuWellPltPlot; + +namespace cvf { + class Color3f; +} + +namespace caf { + class PdmOptionItemInfo; +} + + +//================================================================================================== +/// +/// +//================================================================================================== +class RimWellPltPlot : public RimViewWindow +{ + CAF_PDM_HEADER_INIT; + + static const char PRESSURE_DATA_NAME[]; + static const char PLOT_NAME_QFORMAT_STRING[]; + +public: + RimWellPltPlot(); + virtual ~RimWellPltPlot(); + + void setDescription(const QString& description); + QString description() const; + + virtual void loadDataAndUpdate() override; + + virtual QWidget* viewWidget() override; + virtual void zoomAll() override; + + RimWellLogPlot* wellLogPlot() const; + + void setCurrentWellName(const QString& currWellName); + QString currentWellName() const; + + static bool hasPressureData(const RimWellLogFile* wellLogFile); + static bool isPressureChannel(RimWellLogFileChannel* channel); + static bool hasPressureData(RimEclipseResultCase* gridCase); + static bool hasPressureData(RimWellPath* wellPath); + static const char* plotNameFormatString(); + + void applyInitialSelections(); + +protected: + // Overridden PDM methods + virtual caf::PdmFieldHandle* userDescriptionField() { return &m_userName; } + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + + virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override; + + virtual QImage snapshotWindowContent() override; + + + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + +private: + void addTimeStepToMap(std::map>& destMap, + const std::pair>& timeStepToAdd); + void addTimeStepsToMap(std::map>& destMap, + const std::map>& timeStepsToAdd); + void calculateValueOptionsForWells(QList& options); + void calculateValueOptionsForTimeSteps(const QString& wellName, QList& options); + + void updateEditorsFromCurves(); + void updateWidgetTitleWindowTitle(); + + void syncCurvesFromUiSelection(); + + std::vector wellLogFilesContainingPressure(const QString& wellName) const; + RimWellLogFileChannel* getPressureChannelFromWellFile(const RimWellLogFile* wellLogFile) const; + + RimWellPath* wellPathFromWellLogFile(const RimWellLogFile* wellLogFile) const; + + std::vector> eclipseCasesForWell(const QString& wellName) const; + std::vector gridCasesFromEclipseCases(const std::vector>& eclipseCasesTuple) const; + std::vector rftCasesFromEclipseCases(const std::vector>& eclipseCasesTuple) const; + std::map> timeStepsFromRftCase(RimEclipseResultCase* gridCase) const; + std::map> timeStepsFromGridCase(RimEclipseCase* gridCase) const; + std::map> timeStepsFromWellLogFile(RimWellLogFile* wellLogFile) const; + std::map> adjacentTimeSteps(const std::vector>>& allTimeSteps, + const std::pair>& searchTimeStepPair); + static bool mapContainsTimeStep(const std::map>& map, const QDateTime& timeStep); + + std::set> selectedCurveDefs() const; + std::set> curveDefsFromCurves() const; + std::pair curveDefFromCurve(const RimWellLogCurve* curve) const; + void updateCurvesInPlot(const std::set>& allCurveDefs, + const std::set>& curveDefsToAdd, + const std::set& curvesToDelete); + bool isOnlyGridSourcesSelected() const; + bool isAnySourceAddressSelected(const std::set& addresses) const; + std::vector selectedSources() const; + + // RimViewWindow overrides + + virtual QWidget* createViewWidget(QWidget* mainWindowParent) override; + virtual void deleteViewWidget() override; + + void applyCurveAppearance(RimWellLogCurve* newCurve); + void updateSelectedTimeStepsFromSelectedSources(); + +private: + caf::PdmField m_showPlotTitle; + caf::PdmField m_userName; + + caf::PdmField m_wellName; + caf::PdmField m_branchIndex; + caf::PdmField> m_selectedSources; + + caf::PdmField> m_selectedTimeSteps; + + QPointer m_wellLogPlotWidget; + + caf::PdmChildField m_wellLogPlot; + + std::map> m_timeStepsToAddresses; + + bool m_selectedSourcesOrTimeStepsFieldsChanged; +}; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 25fb70566e..191fb584d5 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -67,6 +67,9 @@ #include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RimWellRftPlot.h" +#include "RimWellPltPlot.h" +#include "RimRftPlotCollection.h" +#include "RimPltPlotCollection.h" #ifdef USE_PROTOTYPE_FEATURE_FRACTURES #include "RimEllipseFractureTemplate.h" @@ -89,7 +92,6 @@ #include #include -#include "RimRftPlotCollection.h" //-------------------------------------------------------------------------------------------------- /// @@ -224,6 +226,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() else if (dynamic_cast(uiItem)) { commandIds << "RicNewRftPlotFeature"; + commandIds << "RicNewPltPlotFeature"; commandIds << "RicNewWellLogFileCurveFeature"; commandIds << "RicNewWellLogCurveExtractionFeature"; commandIds << "RicNewWellPathIntersectionFeature"; @@ -232,6 +235,10 @@ QStringList RimContextCommandBuilder::commandsFromSelection() { commandIds << "RicDeleteRftPlotFeature"; } + else if (dynamic_cast(uiItem)) + { + commandIds << "RicDeletePltPlotFeature"; + } else if (dynamic_cast(uiItem)) { commandIds << "RicEditScriptFeature"; @@ -269,6 +276,10 @@ QStringList RimContextCommandBuilder::commandsFromSelection() { commandIds << "RicNewRftPlotFeature"; } + else if (dynamic_cast(uiItem)) + { + commandIds << "RicNewPltPlotFeature"; + } else if (dynamic_cast(uiItem)) { commandIds << "RicPasteSummaryPlotFeature"; @@ -370,6 +381,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection() commandIds << "RicNewWellLogRftCurveFeature"; commandIds << "RicNewSimWellIntersectionFeature"; commandIds << "RicNewRftPlotFeature"; + commandIds << "RicNewPltPlotFeature"; commandIds << "RicShowWellAllocationPlotFeature"; } else if(dynamic_cast(uiItem)) diff --git a/ApplicationCode/ProjectDataModel/RimMainPlotCollection.cpp b/ApplicationCode/ProjectDataModel/RimMainPlotCollection.cpp index 4303f32281..f90c3c87f4 100644 --- a/ApplicationCode/ProjectDataModel/RimMainPlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimMainPlotCollection.cpp @@ -23,6 +23,7 @@ #include "RimProject.h" #include "RimSummaryPlotCollection.h" #include "RimRftPlotCollection.h" +#include "RimPltPlotCollection.h" #include "RimWellLogPlotCollection.h" #include "RiuMainWindow.h" @@ -47,6 +48,9 @@ RimMainPlotCollection::RimMainPlotCollection() CAF_PDM_InitFieldNoDefault(&m_rftPlotCollection, "RftPlotCollection", "", "", "", ""); m_rftPlotCollection.uiCapability()->setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&m_pltPlotCollection, "PltPlotCollection", "", "", "", ""); + m_pltPlotCollection.uiCapability()->setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&m_summaryPlotCollection, "SummaryPlotCollection", "Summary Plots", "", "", ""); m_summaryPlotCollection.uiCapability()->setUiHidden(true); @@ -55,6 +59,7 @@ RimMainPlotCollection::RimMainPlotCollection() m_wellLogPlotCollection = new RimWellLogPlotCollection(); m_rftPlotCollection = new RimRftPlotCollection(); + m_pltPlotCollection = new RimPltPlotCollection(); m_summaryPlotCollection = new RimSummaryPlotCollection(); m_flowPlotCollection = new RimFlowPlotCollection(); @@ -67,6 +72,7 @@ RimMainPlotCollection::~RimMainPlotCollection() { if (m_wellLogPlotCollection()) delete m_wellLogPlotCollection(); if (m_rftPlotCollection()) delete m_rftPlotCollection(); + if (m_pltPlotCollection()) delete m_pltPlotCollection(); if (m_summaryPlotCollection()) delete m_summaryPlotCollection(); if (m_flowPlotCollection()) delete m_flowPlotCollection(); @@ -104,6 +110,14 @@ RimRftPlotCollection* RimMainPlotCollection::rftPlotCollection() return m_rftPlotCollection(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPltPlotCollection* RimMainPlotCollection::pltPlotCollection() +{ + return m_pltPlotCollection(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -127,6 +141,7 @@ void RimMainPlotCollection::deleteAllContainedObjects() { m_wellLogPlotCollection()->wellLogPlots.deleteAllChildObjects(); m_rftPlotCollection()->deleteAllPlots(); + m_pltPlotCollection()->deleteAllPlots(); m_summaryPlotCollection()->summaryPlots.deleteAllChildObjects(); m_flowPlotCollection()->closeDefaultPlotWindowAndDeletePlots(); diff --git a/ApplicationCode/ProjectDataModel/RimMainPlotCollection.h b/ApplicationCode/ProjectDataModel/RimMainPlotCollection.h index b2ec543dfa..e6a3574e76 100644 --- a/ApplicationCode/ProjectDataModel/RimMainPlotCollection.h +++ b/ApplicationCode/ProjectDataModel/RimMainPlotCollection.h @@ -29,6 +29,7 @@ class RimWellLogPlotCollection; class RimRftPlotCollection; +class RimPltPlotCollection; class RimSummaryPlotCollection; class RimSummaryPlot; class RifReaderEclipseSummary; @@ -49,6 +50,7 @@ public: RimWellLogPlotCollection* wellLogPlotCollection(); RimRftPlotCollection* rftPlotCollection(); + RimPltPlotCollection* pltPlotCollection(); RimSummaryPlotCollection* summaryPlotCollection(); RimFlowPlotCollection* flowPlotCollection(); @@ -63,6 +65,7 @@ protected: caf::PdmChildField m_wellLogPlotCollection; caf::PdmChildField m_rftPlotCollection; + caf::PdmChildField m_pltPlotCollection; caf::PdmChildField m_summaryPlotCollection; caf::PdmChildField m_flowPlotCollection; diff --git a/ApplicationCode/ProjectDataModel/RimPltPlotCollection.cpp b/ApplicationCode/ProjectDataModel/RimPltPlotCollection.cpp new file mode 100644 index 0000000000..2f6f6a691e --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPltPlotCollection.cpp @@ -0,0 +1,225 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimPltPlotCollection.h" + +#include "RigEclipseWellLogExtractor.h" +#include "RigGeoMechCaseData.h" +#include "RigGeoMechWellLogExtractor.h" + +#include "RimEclipseCase.h" +#include "RimGeoMechCase.h" +#include "RimWellLogPlot.h" +#include "RimWellPltPlot.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +#include "cvfAssert.h" + +CAF_PDM_SOURCE_INIT(RimPltPlotCollection, "WellPltPlotCollection"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPltPlotCollection::RimPltPlotCollection() +{ + CAF_PDM_InitObject("PLT Plots", ":/WellLogPlots16x16.png", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_pltPlots, "PltPlots", "", "", "", ""); + m_pltPlots.uiCapability()->setUiHidden(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPltPlotCollection::~RimPltPlotCollection() +{ + m_pltPlots.deleteAllChildObjects(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigEclipseWellLogExtractor* RimPltPlotCollection::findOrCreateSimWellExtractor(const QString& simWellName, + const QString& caseUserDescription, + const RigWellPath* wellPathGeom, + const RigEclipseCaseData* eclCaseData) +{ + if (!(wellPathGeom && eclCaseData)) + { + return nullptr; + } + + for (size_t exIdx = 0; exIdx < m_extractors.size(); ++exIdx) + { + if (m_extractors[exIdx]->caseData() == eclCaseData && m_extractors[exIdx]->wellPathData() == wellPathGeom) + { + return m_extractors[exIdx].p(); + } + } + + std::string errorIdName = (simWellName + " " + caseUserDescription).toStdString(); + cvf::ref extractor = new RigEclipseWellLogExtractor(eclCaseData, wellPathGeom, errorIdName); + m_extractors.push_back(extractor.p()); + + return extractor.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigEclipseWellLogExtractor* RimPltPlotCollection::findOrCreateExtractor(RimWellPath* wellPath, RimEclipseCase* eclCase) +{ + if (!(wellPath && eclCase && wellPath->wellPathGeometry() && eclCase->eclipseCaseData())) + { + return NULL; + } + + RigEclipseCaseData* eclCaseData = eclCase->eclipseCaseData(); + RigWellPath* wellPathGeom = wellPath->wellPathGeometry(); + for (size_t exIdx = 0; exIdx < m_extractors.size(); ++exIdx) + { + if (m_extractors[exIdx]->caseData() == eclCaseData && m_extractors[exIdx]->wellPathData() == wellPathGeom) + { + return m_extractors[exIdx].p(); + } + } + + std::string errorIdName = (wellPath->name() + " " + eclCase->caseUserDescription()).toStdString(); + cvf::ref extractor = new RigEclipseWellLogExtractor(eclCaseData, wellPathGeom, errorIdName); + m_extractors.push_back(extractor.p()); + + return extractor.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigGeoMechWellLogExtractor* RimPltPlotCollection::findOrCreateExtractor(RimWellPath* wellPath, RimGeoMechCase* geomCase) +{ + if (!(wellPath && geomCase && wellPath->wellPathGeometry() && geomCase->geoMechData())) + { + return NULL; + } + + RigGeoMechCaseData* geomCaseData = geomCase->geoMechData(); + RigWellPath* wellPathGeom = wellPath->wellPathGeometry(); + for (size_t exIdx = 0; exIdx < m_geomExtractors.size(); ++exIdx) + { + if (m_geomExtractors[exIdx]->caseData() == geomCaseData && m_geomExtractors[exIdx]->wellPathData() == wellPathGeom) + { + return m_geomExtractors[exIdx].p(); + } + } + + std::string errorIdName = (wellPath->name() + " " + geomCase->caseUserDescription()).toStdString(); + cvf::ref extractor = new RigGeoMechWellLogExtractor(geomCaseData, wellPathGeom, errorIdName); + m_geomExtractors.push_back(extractor.p()); + + return extractor.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPltPlotCollection::removeExtractors(const RigWellPath* wellPath) +{ + for (int eIdx = (int) m_extractors.size() - 1; eIdx >= 0; eIdx--) + { + if (m_extractors[eIdx]->wellPathData() == wellPath) + { + m_extractors.eraseAt(eIdx); + } + } + + for (int eIdx = (int) m_geomExtractors.size() - 1; eIdx >= 0; eIdx--) + { + if (m_geomExtractors[eIdx]->wellPathData() == wellPath) + { + m_geomExtractors.eraseAt(eIdx); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPltPlotCollection::removeExtractors(const RigEclipseCaseData* caseData) +{ + for (int eIdx = (int) m_extractors.size() - 1; eIdx >= 0; eIdx--) + { + if (m_extractors[eIdx]->caseData() == caseData) + { + m_extractors.eraseAt(eIdx); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPltPlotCollection::removeExtractors(const RigGeoMechCaseData* caseData) +{ + for (int eIdx = (int) m_geomExtractors.size() - 1; eIdx >= 0; eIdx--) + { + if (m_geomExtractors[eIdx]->caseData() == caseData) + { + m_geomExtractors.eraseAt(eIdx); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector RimPltPlotCollection::pltPlots() const +{ + std::vector plots; + for (const auto& plot : m_pltPlots) + { + plots.push_back(plot); + } + return plots; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPltPlotCollection::addPlot(RimWellPltPlot* newPlot) +{ + m_pltPlots.push_back(newPlot); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPltPlotCollection::removePlot(RimWellPltPlot* plot) +{ + size_t index = m_pltPlots.index(plot); + if (index < m_pltPlots.size()) + m_pltPlots.erase(index); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPltPlotCollection::deleteAllPlots() +{ + m_pltPlots.deleteAllChildObjects(); +} diff --git a/ApplicationCode/ProjectDataModel/RimPltPlotCollection.h b/ApplicationCode/ProjectDataModel/RimPltPlotCollection.h new file mode 100644 index 0000000000..eefc9e4148 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimPltPlotCollection.h @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafPdmObject.h" +#include "cafPdmField.h" +#include "cafPdmChildArrayField.h" +#include "cvfCollection.h" + +class RimWellLogPlot; +class RigEclipseWellLogExtractor; +class RigGeoMechWellLogExtractor; +class RimGeoMechCase; +class RigEclipseCaseData; +class RigGeoMechCaseData; +class RigWellPath; +class RimWellPath; +class RimEclipseCase; +class RiuWellLogPlot; +class RimWellPltPlot; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimPltPlotCollection : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + RimPltPlotCollection(); + virtual ~RimPltPlotCollection(); + + RigEclipseWellLogExtractor* findOrCreateSimWellExtractor(const QString& simWellName, + const QString& caseUserDescription, + const RigWellPath* wellPathGeom, + const RigEclipseCaseData* eclCaseData); + + RigEclipseWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimEclipseCase* eclCase); + RigGeoMechWellLogExtractor* findOrCreateExtractor(RimWellPath* wellPath, RimGeoMechCase* eclCase); + + void removeExtractors(const RigWellPath* wellPath); + void removeExtractors(const RigEclipseCaseData* caseData); + void removeExtractors(const RigGeoMechCaseData* caseData); + + const std::vector pltPlots() const; + void addPlot(RimWellPltPlot* newPlot); + void removePlot(RimWellPltPlot* plot); + void deleteAllPlots(); + +private: + caf::PdmChildArrayField m_pltPlots; + cvf::Collection m_extractors; + cvf::Collection m_geomExtractors; +}; diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 9e3d9cb9b0..e5654d923a 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -61,6 +61,7 @@ #include "RimViewLinkerCollection.h" #include "RimWellLogPlotCollection.h" #include "RimRftPlotCollection.h" +#include "RimPltPlotCollection.h" #include "RimWellPathCollection.h" #include "RimWellPathImport.h" #include "RimWellPath.h" @@ -1047,6 +1048,11 @@ void RimProject::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QS uiTreeOrdering.add(mainPlotCollection->rftPlotCollection()); } + if (mainPlotCollection->pltPlotCollection()) + { + uiTreeOrdering.add(mainPlotCollection->pltPlotCollection()); + } + if (mainPlotCollection->flowPlotCollection()) { uiTreeOrdering.add(mainPlotCollection->flowPlotCollection()); diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index 93336b29b8..6b6398cbec 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -47,6 +47,7 @@ ${CEE_CURRENT_LIST_DIR}RiuEditPerforationCollectionWidget.h ${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h ${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h ${CEE_CURRENT_LIST_DIR}RiuWellRftPlot.h +${CEE_CURRENT_LIST_DIR}RiuWellPltPlot.h ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h ${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h ${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h @@ -101,6 +102,7 @@ ${CEE_CURRENT_LIST_DIR}RiuEditPerforationCollectionWidget.cpp ${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.cpp ${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.cpp ${CEE_CURRENT_LIST_DIR}RiuWellRftPlot.cpp +${CEE_CURRENT_LIST_DIR}RiuWellPltPlot.cpp ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.cpp ${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.cpp ${CEE_CURRENT_LIST_DIR}RiuMessagePanel.cpp @@ -141,6 +143,7 @@ ${CEE_CURRENT_LIST_DIR}RiuEditPerforationCollectionWidget.h ${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h ${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h ${CEE_CURRENT_LIST_DIR}RiuWellRftPlot.h +${CEE_CURRENT_LIST_DIR}RiuWellPltPlot.h ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h ${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h ${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index c9dc62f2ac..dd403ea8fc 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -327,6 +327,7 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) commandIds << "RicNewWellLogCurveExtractionFeature"; commandIds << "RicNewWellLogRftCurveFeature"; commandIds << "RicNewRftPlotFeature"; + commandIds << "RicNewPltPlotFeature"; commandIds << "RicShowWellAllocationPlotFeature"; commandIds << "RicPlotProductionRateFeature"; commandIds << "Separator"; diff --git a/ApplicationCode/UserInterface/RiuWellPltPlot.cpp b/ApplicationCode/UserInterface/RiuWellPltPlot.cpp new file mode 100644 index 0000000000..222c9ea62c --- /dev/null +++ b/ApplicationCode/UserInterface/RiuWellPltPlot.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 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 "RiuWellPltPlot.h" + +#include "RiaApplication.h" + +#include "RimContextCommandBuilder.h" +#include "RimTotalWellAllocationPlot.h" +#include "RimWellPltPlot.h" +#include "RimWellLogPlot.h" +#include "RimWellLogTrack.h" +#include "RimTofAccumulatedPhaseFractionsPlot.h" + +#include "RiuContextMenuLauncher.h" +#include "RiuNightchartsWidget.h" +#include "RiuPlotObjectPicker.h" + +#include "cvfColor3.h" + +#include +#include +#include +#include + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellPltPlot::RiuWellPltPlot(RimWellPltPlot* plotDefinition, QWidget* parent) + : m_plotDefinition(plotDefinition), + QFrame(parent) +{ + Q_ASSERT(m_plotDefinition); + + QVBoxLayout* mainLayout = new QVBoxLayout(); + this->setLayout(mainLayout); + this->layout()->setMargin(0); + this->layout()->setSpacing(2); + + m_titleLabel = new QLabel(this); + new RiuPlotObjectPicker(m_titleLabel, m_plotDefinition->wellLogPlot()); + + QFont font = m_titleLabel->font(); + font.setPointSize(14); + font.setBold(true); + m_titleLabel->setFont(font); + + // White background + QPalette pal = this->palette(); + pal.setColor(QPalette::Background, Qt::white); + this->setAutoFillBackground(true); + this->setPalette(pal); + + mainLayout->addWidget(m_titleLabel, 0, Qt::AlignCenter); + + auto plotWidgetsLayout = new QHBoxLayout(); + auto rightColumnLayout = new QVBoxLayout(); + + mainLayout->addLayout(plotWidgetsLayout); + plotWidgetsLayout->addLayout(rightColumnLayout); + + QWidget* wellFlowWidget = m_plotDefinition->wellLogPlot()->createViewWidget(this); + + plotWidgetsLayout->addWidget(wellFlowWidget); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuWellPltPlot::~RiuWellPltPlot() +{ + if (m_plotDefinition) + { + m_plotDefinition->handleMdiWindowClosed(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimWellPltPlot* RiuWellPltPlot::ownerPlotDefinition() +{ + return m_plotDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimViewWindow* RiuWellPltPlot::ownerViewWindow() const +{ + return m_plotDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellPltPlot::showTitle(const QString& title) +{ + m_titleLabel->show(); + + m_titleLabel->setText(title); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellPltPlot::hideTitle() +{ + m_titleLabel->hide(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuWellPltPlot::minimumSizeHint() const +{ + return QSize(0, 100); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellPltPlot::contextMenuEvent(QContextMenuEvent* event) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuWellPltPlot::sizeHint() const +{ + return QSize(0, 0); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellPltPlot::setDefaults() +{ +} diff --git a/ApplicationCode/UserInterface/RiuWellPltPlot.h b/ApplicationCode/UserInterface/RiuWellPltPlot.h new file mode 100644 index 0000000000..f1281953d8 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuWellPltPlot.h @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017 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 "qwt_plot.h" + +#include "cafPdmPointer.h" + +#include +#include + +#include "RiuInterfaceToViewWindow.h" + +class RimWellPltPlot; +class RiuNightchartsWidget; + +class QLabel; + +namespace cvf { + class Color3f; +} + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuWellPltPlot : public QFrame, public RiuInterfaceToViewWindow +{ + Q_OBJECT; +public: + RiuWellPltPlot(RimWellPltPlot* plotDefinition, QWidget* parent = NULL); + virtual ~RiuWellPltPlot(); + + RimWellPltPlot* ownerPlotDefinition(); + virtual RimViewWindow* ownerViewWindow() const override; + + void showTitle(const QString& title); + void hideTitle(); + +protected: + virtual QSize sizeHint() const override; + virtual QSize minimumSizeHint() const override; + + virtual void contextMenuEvent(QContextMenuEvent *) override; + +private: + void setDefaults(); + +private: + caf::PdmPointer m_plotDefinition; + QPointer m_titleLabel; +}; diff --git a/doc/well_log_classes.plantuml b/doc/well_log_classes.plantuml index 84351a114f..1ad8f88b00 100644 --- a/doc/well_log_classes.plantuml +++ b/doc/well_log_classes.plantuml @@ -10,8 +10,10 @@ PdmObject <|-- RimWellLogTrack RimViewWindow <|-- RimWellAllocationPlot RimViewWindow <|-- RimWellRftPlot +RimViewWindow <|-- RimWellPltPlot RimWellAllocationPlot *--> RimWellLogPlot RimWellRftPlot *--> RimWellLogPlot +RimWellPltPlot *--> RimWellLogPlot } package curve { @@ -57,6 +59,8 @@ class RiuWellAllocationPlot{ } class RiuWellRftPlot{ } +class RiuWellPltPlot{ +} } class RiuWellLogPlot { @@ -78,7 +82,9 @@ RimPlotCurve -r-> RiuLineSegmentQwtPlotCurve RimSummaryPlot -r-> RiuSummaryQwtPlot RimWellAllocationPlot *-> RiuWellAllocationPlot RimWellRftPlot *-> RiuWellRftPlot +RimWellPltPlot *-> RiuWellPltPlot RiuWellAllocationPlot ....> RiuWellLogPlot RiuWellRftPlot ....> RiuWellLogPlot +RiuWellPltPlot ....> RiuWellLogPlot @enduml