Merge remote-tracking branch 'origin/dev' into hdf-prototype

This commit is contained in:
Magne Sjaastad 2017-03-29 12:17:24 +02:00
commit 354e44b617
51 changed files with 2019 additions and 683 deletions

View File

@ -49,6 +49,7 @@
#include "RimEclipseWellCollection.h"
#include "RimFaultCollection.h"
#include "RimFormationNamesCollection.h"
#include "RimFlowCharacteristicsPlot.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechCellColors.h"
#include "RimGeoMechModels.h"
@ -83,6 +84,7 @@
#include "RiuViewer.h"
#include "RiuWellLogPlot.h"
#include "RiuWellAllocationPlot.h"
#include "RiuFlowCharacteristicsPlot.h"
#include "RicImportSummaryCaseFeature.h"
#include "RicSnapshotViewToClipboardFeature.h"
@ -1648,6 +1650,12 @@ RimViewWindow* RiaApplication::activeViewWindow()
{
viewWindow = wellAllocationPlot->ownerPlotDefinition();
}
RiuFlowCharacteristicsPlot* flowCharacteristicsPlot = dynamic_cast<RiuFlowCharacteristicsPlot*>(subwindows.back()->widget());
if (flowCharacteristicsPlot)
{
viewWindow = flowCharacteristicsPlot->ownerPlotDefinition();
}
}
}

View File

@ -402,3 +402,30 @@ const caf::ColorTable& RiaColorTables::selectionPaletteColors()
return colorTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const caf::ColorTable& RiaColorTables::timestepsPaletteColors()
{
static std::vector<cvf::Color3ub> colors{
cvf::Color3ub( 56, 56, 255), // Vivid Blue
cvf::Color3ub( 0, 143, 239), // Dark Light Blue
cvf::Color3ub( 0, 112, 136), // Dark Green-Blue
cvf::Color3ub( 51, 204, 255), // Bluer Turquoise
cvf::Color3ub( 0, 221, 221), // Turquoise
cvf::Color3ub( 0, 205, 68), // Bluish Green
cvf::Color3ub( 78, 204, 0), // Clear Green
cvf::Color3ub(164, 193, 0), // Mid Yellowish Green
cvf::Color3ub(236, 188, 0), // Mid Yellow
cvf::Color3ub(236, 118, 0), // Orange
cvf::Color3ub(202, 0, 0), // Red
cvf::Color3ub(248, 0, 170), // Magenta
cvf::Color3ub(201, 168, 206), // Light Violet
cvf::Color3ub(169, 2, 240), // Purple
};
static caf::ColorTable colorTable = caf::ColorTable(colors);
return colorTable;
}

View File

@ -48,4 +48,6 @@ public:
static const caf::ColorTable& summaryCurveNoneRedGreenBlueBrownPaletteColors();
static const caf::ColorTable& wellLogPlotPaletteColors();
static const caf::ColorTable& selectionPaletteColors();
static const caf::ColorTable& timestepsPaletteColors();
};

View File

@ -6,6 +6,7 @@ endif()
set (SOURCE_GROUP_HEADER_FILES
${CEE_CURRENT_LIST_DIR}RicShowWellAllocationPlotFeature.h
${CEE_CURRENT_LIST_DIR}RicShowFlowCharacteristicsPlotFeature.h
${CEE_CURRENT_LIST_DIR}RicAddStoredWellAllocationPlotFeature.h
${CEE_CURRENT_LIST_DIR}RicShowContributingWellsFromPlotFeature.h
${CEE_CURRENT_LIST_DIR}RicShowContributingWellsFeature.h
@ -16,6 +17,7 @@ ${CEE_CURRENT_LIST_DIR}RicSelectViewUI.h
set (SOURCE_GROUP_SOURCE_FILES
${CEE_CURRENT_LIST_DIR}RicShowWellAllocationPlotFeature.cpp
${CEE_CURRENT_LIST_DIR}RicShowFlowCharacteristicsPlotFeature.cpp
${CEE_CURRENT_LIST_DIR}RicAddStoredWellAllocationPlotFeature.cpp
${CEE_CURRENT_LIST_DIR}RicShowContributingWellsFromPlotFeature.cpp
${CEE_CURRENT_LIST_DIR}RicShowContributingWellsFeature.cpp

View File

@ -47,7 +47,7 @@ bool RicAddStoredWellAllocationPlotFeature::isCommandEnabled()
{
RimWellAllocationPlot* wellAllocationPlot = dynamic_cast<RimWellAllocationPlot*>(caf::SelectionManager::instance()->selectedItem());
if (flowPlotColl->defaultPlot() == wellAllocationPlot)
if (flowPlotColl->defaultWellAllocPlot() == wellAllocationPlot)
{
return true;
}
@ -72,7 +72,7 @@ void RicAddStoredWellAllocationPlotFeature::onActionTriggered(bool isChecked)
RimWellAllocationPlot* wellAllocationPlot = dynamic_cast<RimWellAllocationPlot*>(sourceObject->copyByXmlSerialization(caf::PdmDefaultObjectFactory::instance()));
CVF_ASSERT(wellAllocationPlot);
flowPlotColl->addPlot(wellAllocationPlot);
flowPlotColl->addWellAllocPlotToStoredPlots(wellAllocationPlot);
wellAllocationPlot->resolveReferencesRecursively();
wellAllocationPlot->loadDataAndUpdate();

View File

@ -0,0 +1,98 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicShowFlowCharacteristicsPlotFeature.h"
#include "RiaApplication.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimFlowCharacteristicsPlot.h"
#include "RimFlowPlotCollection.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimView.h"
#include "RiuMainPlotWindow.h"
#include <QAction>
CAF_CMD_SOURCE_INIT(RicShowFlowCharacteristicsPlotFeature, "RicShowFlowCharacteristicsPlotFeature");
RimEclipseResultCase* activeEclipseResultCase()
{
RimView * activeView = RiaApplication::instance()->activeReservoirView();
auto eclView = dynamic_cast<RimEclipseView*>(activeView);
if (!eclView) return nullptr;
auto eclCase = dynamic_cast<RimEclipseResultCase*>(eclView->ownerCase());
return eclCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicShowFlowCharacteristicsPlotFeature::isCommandEnabled()
{
RimEclipseResultCase* eclCase = activeEclipseResultCase();
if (!eclCase) return false;
if (!eclCase->defaultFlowDiagSolution()) return false;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowFlowCharacteristicsPlotFeature::onActionTriggered(bool isChecked)
{
RimEclipseResultCase* eclCase = activeEclipseResultCase();
if (eclCase && eclCase->defaultFlowDiagSolution())
{
if (RiaApplication::instance()->project())
{
RimFlowPlotCollection* flowPlotColl = RiaApplication::instance()->project()->mainPlotCollection->flowPlotCollection();
if (flowPlotColl)
{
RiuMainPlotWindow* plotwindow = RiaApplication::instance()->getOrCreateAndShowMainPlotWindow();
flowPlotColl->defaultFlowCharacteristicsPlot()->setFromFlowSolution(eclCase->defaultFlowDiagSolution());
flowPlotColl->defaultFlowCharacteristicsPlot()->updateConnectedEditors();
// Make sure the summary plot window is created and visible
plotwindow->selectAsCurrentItem(flowPlotColl->defaultFlowCharacteristicsPlot());
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicShowFlowCharacteristicsPlotFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setIcon(QIcon(":/WellAllocPlot16x16.png"));
actionToSetup->setText("Plot Flow Characteristics");
}

View File

@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
class RimEclipseWell;
//==================================================================================================
///
//==================================================================================================
class RicShowFlowCharacteristicsPlotFeature : 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;
};

View File

@ -69,12 +69,12 @@ void RicShowWellAllocationPlotFeature::onActionTriggered(bool isChecked)
RimFlowPlotCollection* flowPlotColl = RiaApplication::instance()->project()->mainPlotCollection->flowPlotCollection();
if (flowPlotColl)
{
flowPlotColl->defaultPlot()->setFromSimulationWell(eclWell);
flowPlotColl->defaultPlot()->updateConnectedEditors();
flowPlotColl->defaultWellAllocPlot()->setFromSimulationWell(eclWell);
flowPlotColl->defaultWellAllocPlot()->updateConnectedEditors();
// Make sure the summary plot window is created and visible
RiuMainPlotWindow* plotwindow = RiaApplication::instance()->getOrCreateAndShowMainPlotWindow();
plotwindow->selectAsCurrentItem(flowPlotColl->defaultPlot());
plotwindow->selectAsCurrentItem(flowPlotColl->defaultWellAllocPlot());
}
}
}

View File

@ -23,16 +23,20 @@
#include "RimSummaryPlot.h"
#include "RimView.h"
#include "RimViewWindow.h"
#include "RimWellAllocationPlot.h"
#include "RimWellLogPlot.h"
#include "RiuMainPlotWindow.h"
#include "RiuMainWindow.h"
#include "RiuSummaryQwtPlot.h"
#include "RiuWellAllocationPlot.h"
#include "RiuWellLogPlot.h"
#include <QAction>
#include <QClipboard>
#include <QMdiSubWindow>
#include "RiuFlowCharacteristicsPlot.h"
#include "RimFlowCharacteristicsPlot.h"
CAF_CMD_SOURCE_INIT(RicViewZoomAllFeature, "RicViewZoomAllFeature");
@ -62,21 +66,53 @@ void RicViewZoomAllFeature::onActionTriggered(bool isChecked)
QList<QMdiSubWindow*> subwindows = mainPlotWindow->subWindowList(QMdiArea::StackingOrder);
if (subwindows.size() > 0)
{
RiuSummaryQwtPlot* summaryQwtPlot = dynamic_cast<RiuSummaryQwtPlot*>(subwindows.back()->widget());
if (summaryQwtPlot)
{
RimViewWindow* viewWindow = summaryQwtPlot->ownerPlotDefinition();
RiuSummaryQwtPlot* summaryQwtPlot = dynamic_cast<RiuSummaryQwtPlot*>(subwindows.back()->widget());
if (summaryQwtPlot)
{
RimViewWindow* viewWindow = summaryQwtPlot->ownerPlotDefinition();
viewWindow->zoomAll();
summaryQwtPlot->replot();
viewWindow->zoomAll();
summaryQwtPlot->replot();
return;
}
}
RiuWellLogPlot* wellLogPlot = dynamic_cast<RiuWellLogPlot*>(subwindows.back()->widget());
if (wellLogPlot)
{
RimViewWindow* viewWindow = wellLogPlot->ownerPlotDefinition();
viewWindow->zoomAll();
wellLogPlot->update();
RiuWellLogPlot* wellLogPlot = dynamic_cast<RiuWellLogPlot*>(subwindows.back()->widget());
if (wellLogPlot)
{
RimViewWindow* viewWindow = wellLogPlot->ownerPlotDefinition();
viewWindow->zoomAll();
wellLogPlot->update();
return;
}
}
{
RiuWellAllocationPlot* wellAllocationPlot = dynamic_cast<RiuWellAllocationPlot*>(subwindows.back()->widget());
if (wellAllocationPlot)
{
RimWellAllocationPlot* viewWindow = wellAllocationPlot->ownerPlotDefinition();
viewWindow->zoomAll();
wellAllocationPlot->update();
return;
}
}
{
RiuFlowCharacteristicsPlot* flowCharPlot = dynamic_cast<RiuFlowCharacteristicsPlot*>(subwindows.back()->widget());
if (flowCharPlot)
{
RimFlowCharacteristicsPlot* viewWindow = flowCharPlot->ownerPlotDefinition();
viewWindow->zoomAll();
flowCharPlot->update();
return;
}
}
}
}

View File

@ -11,6 +11,7 @@ ${CEE_CURRENT_LIST_DIR}RimWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RimTotalWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RimWellFlowRateCurve.h
${CEE_CURRENT_LIST_DIR}RimWellAllocationPlotLegend.h
${CEE_CURRENT_LIST_DIR}RimFlowCharacteristicsPlot.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -20,6 +21,7 @@ ${CEE_CURRENT_LIST_DIR}RimWellAllocationPlot.cpp
${CEE_CURRENT_LIST_DIR}RimTotalWellAllocationPlot.cpp
${CEE_CURRENT_LIST_DIR}RimWellFlowRateCurve.cpp
${CEE_CURRENT_LIST_DIR}RimWellAllocationPlotLegend.cpp
${CEE_CURRENT_LIST_DIR}RimFlowCharacteristicsPlot.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,290 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimFlowCharacteristicsPlot.h"
#include "RigFlowDiagResults.h"
#include "RimEclipseResultCase.h"
#include "RimFlowDiagSolution.h"
#include "RimProject.h"
#include "RiuFlowCharacteristicsPlot.h"
#include <cmath> // Needed for HUGE_VAL on Linux
namespace caf
{
template<>
void AppEnum< RimFlowCharacteristicsPlot::TimeSelectionType >::setUp()
{
addItem(RimFlowCharacteristicsPlot::ALL_AVAILABLE, "ALL_AVAILABLE", "All available");
addItem(RimFlowCharacteristicsPlot::SELECT_AVAILABLE, "SELECT_AVAILABLE", "Select");
setDefault(RimFlowCharacteristicsPlot::ALL_AVAILABLE);
}
}
CAF_PDM_SOURCE_INIT(RimFlowCharacteristicsPlot, "FlowCharacteristicsPlot");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot::RimFlowCharacteristicsPlot()
{
CAF_PDM_InitObject("Flow Characteristics", ":/WellAllocPie16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_case, "FlowCase", "Case", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_flowDiagSolution, "FlowDiagSolution", "Flow Diag Solution", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_timeStepSelectionType, "TimeSelectionType", "Time Steps", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_selectedTimeSteps, "SelectedTimeSteps", "", "", "", "");
this->m_showWindow = false;
setAsPlotMdiWindow();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot::~RimFlowCharacteristicsPlot()
{
removeMdiWindowFromMdiArea();
deleteViewWidget();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::setFromFlowSolution(RimFlowDiagSolution* flowSolution)
{
if ( !flowSolution )
{
m_case = nullptr;
}
else
{
RimEclipseResultCase* eclCase;
flowSolution->firstAncestorOrThisOfType(eclCase);
m_case = eclCase;
}
m_flowDiagSolution = flowSolution;
m_showWindow = true;
loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::deleteViewWidget()
{
if (m_flowCharPlotWidget)
{
m_flowCharPlotWidget->deleteLater();
m_flowCharPlotWidget= nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimFlowCharacteristicsPlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_case )
{
RimProject* proj = nullptr;
this->firstAncestorOrThisOfType(proj);
if ( proj )
{
std::vector<RimEclipseResultCase*> cases;
proj->descendantsIncludingThisOfType(cases);
for ( RimEclipseResultCase* c : cases )
{
options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon()));
}
}
}
else if ( fieldNeedingOptions == &m_flowDiagSolution )
{
if ( m_case )
{
std::vector<RimFlowDiagSolution*> flowSols = m_case->flowDiagSolutions();
for ( RimFlowDiagSolution* flowSol : flowSols )
{
options.push_back(caf::PdmOptionItemInfo("None", nullptr));
options.push_back(caf::PdmOptionItemInfo(flowSol->userDescription(), flowSol, false, flowSol->uiIcon()));
}
}
}
else if ( fieldNeedingOptions == &m_selectedTimeSteps )
{
if ( m_flowDiagSolution )
{
RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults();
std::vector<int> calculatedTimesteps = flowResult->calculatedTimeSteps();
std::vector<QDateTime> timeStepDates = m_case->timeStepDates();
for ( int tsIdx : calculatedTimesteps )
{
options.push_back(caf::PdmOptionItemInfo(timeStepDates[tsIdx].toString(), tsIdx));
}
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_case);
uiOrdering.add(&m_flowDiagSolution);
uiOrdering.add(&m_timeStepSelectionType);
if (m_timeStepSelectionType == SELECT_AVAILABLE) uiOrdering.add(&m_selectedTimeSteps);
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimFlowCharacteristicsPlot::viewWidget()
{
return m_flowCharPlotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::zoomAll()
{
if (m_flowCharPlotWidget) m_flowCharPlotWidget->zoomAll();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimViewWindow::fieldChangedByUi(changedField, oldValue, newValue);
if ( &m_case == changedField )
{
m_flowDiagSolution = m_case->defaultFlowDiagSolution();
}
// All fields update plot
this->loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimFlowCharacteristicsPlot::snapshotWindowContent()
{
QImage image;
if (m_flowCharPlotWidget)
{
QPixmap pix = QPixmap::grabWidget(m_flowCharPlotWidget);
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::loadDataAndUpdate()
{
updateMdiWindowVisibility();
if (m_flowDiagSolution && m_flowCharPlotWidget)
{
RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults();
std::vector<int> calculatedTimesteps = flowResult->calculatedTimeSteps();
if (m_timeStepSelectionType == SELECT_AVAILABLE)
{
// Find set intersection of selected and available time steps
std::set<int> calculatedTimeStepsSet;
calculatedTimeStepsSet.insert(calculatedTimesteps.begin(), calculatedTimesteps.end());
calculatedTimesteps.clear();
auto selectedTimeSteps = m_selectedTimeSteps();
for (int tsIdx : selectedTimeSteps)
{
if (calculatedTimeStepsSet.count(tsIdx)) calculatedTimesteps.push_back(tsIdx);
}
}
std::vector<QDateTime> timeStepDates = m_case->timeStepDates();
std::vector<double> lorenzVals(timeStepDates.size(), HUGE_VAL);
m_flowCharPlotWidget->removeAllCurves();
for ( int timeStepIdx: calculatedTimesteps )
{
lorenzVals[timeStepIdx] = flowResult->flowCharacteristicsResults(timeStepIdx).m_lorenzCoefficient;
}
m_flowCharPlotWidget->setLorenzCurve(timeStepDates, lorenzVals);
for ( int timeStepIdx: calculatedTimesteps )
{
const auto & flowCharResults = flowResult->flowCharacteristicsResults(timeStepIdx);
m_flowCharPlotWidget->addFlowCapStorageCapCurve(timeStepDates[timeStepIdx],
flowCharResults.m_flowCapStorageCapCurve.first,
flowCharResults.m_flowCapStorageCapCurve.second);
m_flowCharPlotWidget->addSweepEfficiencyCurve(timeStepDates[timeStepIdx],
flowCharResults.m_sweepEfficiencyCurve.first,
flowCharResults.m_sweepEfficiencyCurve.second);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimFlowCharacteristicsPlot::createViewWidget(QWidget* mainWindowParent)
{
m_flowCharPlotWidget = new RiuFlowCharacteristicsPlot(this, mainWindowParent);
return m_flowCharPlotWidget;
}

View File

@ -0,0 +1,90 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimViewWindow.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include <QPointer>
class RimFlowDiagSolution;
class RimEclipseResultCase;
class RiuFlowCharacteristicsPlot;
namespace caf {
class PdmOptionItemInfo;
}
namespace cvf {
class Color3f;
}
//==================================================================================================
///
///
//==================================================================================================
class RimFlowCharacteristicsPlot : public RimViewWindow
{
CAF_PDM_HEADER_INIT;
public:
RimFlowCharacteristicsPlot();
virtual ~RimFlowCharacteristicsPlot();
void setFromFlowSolution(RimFlowDiagSolution* flowSolution);
// RimViewWindow overrides
virtual QWidget* viewWidget() override;
virtual void zoomAll() override;
virtual QWidget* createViewWidget(QWidget* mainWindowParent) override;
virtual void deleteViewWidget() override;
enum TimeSelectionType
{
ALL_AVAILABLE,
SELECT_AVAILABLE
};
protected:
// RimViewWindow overrides
virtual void loadDataAndUpdate() override;
virtual QImage snapshotWindowContent() override;
// Overridden PDM methods
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
private:
caf::PdmPtrField<RimEclipseResultCase*> m_case;
caf::PdmPtrField<RimFlowDiagSolution*> m_flowDiagSolution;
caf::PdmField<caf::AppEnum<TimeSelectionType> > m_timeStepSelectionType;
caf::PdmField<std::vector<int> > m_selectedTimeSteps;
QPointer<RiuFlowCharacteristicsPlot> m_flowCharPlotWidget;
};

View File

@ -19,6 +19,7 @@
#include "RimFlowPlotCollection.h"
#include "RimWellAllocationPlot.h"
#include "RimFlowCharacteristicsPlot.h"
#include "cvfAssert.h"
@ -33,10 +34,13 @@ RimFlowPlotCollection::RimFlowPlotCollection()
{
CAF_PDM_InitObject("Flow Diagnostics Plots", ":/WellAllocPlots16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_defaultPlot, "DefaultFlowPlot", "", "", "", "");
m_defaultPlot.uiCapability()->setUiHidden(true);
CAF_PDM_InitFieldNoDefault(&m_flowCharacteristicsPlot, "FlowCharacteristicsPlot", "", "", "", "");
m_flowCharacteristicsPlot.uiCapability()->setUiHidden(true);
CAF_PDM_InitFieldNoDefault(&m_flowPlots, "FlowPlots", "Stored Plots", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_defaultWellAllocPlot, "DefaultFlowPlot", "", "", "", "");
m_defaultWellAllocPlot.uiCapability()->setUiHidden(true);
CAF_PDM_InitFieldNoDefault(&m_storedWellAllocPlots, "FlowPlots", "Stored Plots", "", "", "");
}
//--------------------------------------------------------------------------------------------------
@ -44,9 +48,9 @@ RimFlowPlotCollection::RimFlowPlotCollection()
//--------------------------------------------------------------------------------------------------
RimFlowPlotCollection::~RimFlowPlotCollection()
{
delete m_defaultPlot();
delete m_defaultWellAllocPlot();
m_flowPlots.deleteAllChildObjects();
m_storedWellAllocPlots.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
@ -54,12 +58,12 @@ RimFlowPlotCollection::~RimFlowPlotCollection()
//--------------------------------------------------------------------------------------------------
void RimFlowPlotCollection::closeDefaultPlotWindowAndDeletePlots()
{
if ( m_defaultPlot )
if ( m_defaultWellAllocPlot )
{
m_defaultPlot->removeFromMdiAreaAndDeleteViewWidget();
delete m_defaultPlot();
m_defaultWellAllocPlot->removeFromMdiAreaAndDeleteViewWidget();
delete m_defaultWellAllocPlot();
}
m_flowPlots.deleteAllChildObjects();
m_storedWellAllocPlots.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
@ -67,12 +71,12 @@ void RimFlowPlotCollection::closeDefaultPlotWindowAndDeletePlots()
//--------------------------------------------------------------------------------------------------
void RimFlowPlotCollection::loadDataAndUpdate()
{
caf::ProgressInfo plotProgress(m_flowPlots.size() + 1, "");
caf::ProgressInfo plotProgress(m_storedWellAllocPlots.size() + 1, "");
if (m_defaultPlot) m_defaultPlot->loadDataAndUpdate();
if (m_defaultWellAllocPlot) m_defaultWellAllocPlot->loadDataAndUpdate();
plotProgress.incrementProgress();
for (RimWellAllocationPlot* p : m_flowPlots)
for (RimWellAllocationPlot* p : m_storedWellAllocPlots)
{
p->loadDataAndUpdate();
plotProgress.incrementProgress();
@ -85,31 +89,46 @@ void RimFlowPlotCollection::loadDataAndUpdate()
size_t RimFlowPlotCollection::plotCount() const
{
size_t plotCount = 0;
if (m_defaultPlot) plotCount = 1;
plotCount += m_flowPlots.size();
if (m_defaultWellAllocPlot) plotCount = 1;
plotCount += m_storedWellAllocPlots.size();
return plotCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowPlotCollection::addPlot(RimWellAllocationPlot* plot)
void RimFlowPlotCollection::addWellAllocPlotToStoredPlots(RimWellAllocationPlot* plot)
{
m_flowPlots.push_back(plot);
m_storedWellAllocPlots.push_back(plot);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellAllocationPlot* RimFlowPlotCollection::defaultPlot()
RimWellAllocationPlot* RimFlowPlotCollection::defaultWellAllocPlot()
{
if ( !m_defaultPlot() )
if ( !m_defaultWellAllocPlot() )
{
m_defaultPlot = new RimWellAllocationPlot;
m_defaultPlot->setDescription("Default Flow Diagnostics Plot");
m_defaultWellAllocPlot = new RimWellAllocationPlot;
m_defaultWellAllocPlot->setDescription("Default Flow Diagnostics Plot");
}
this->updateConnectedEditors();
return m_defaultPlot();
return m_defaultWellAllocPlot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot* RimFlowPlotCollection::defaultFlowCharacteristicsPlot()
{
if ( !m_flowCharacteristicsPlot() )
{
m_flowCharacteristicsPlot = new RimFlowCharacteristicsPlot;
}
this->updateConnectedEditors();
return m_flowCharacteristicsPlot();
}

View File

@ -23,6 +23,7 @@
#include "cafPdmChildField.h"
class RimWellAllocationPlot;
class RimFlowCharacteristicsPlot;
//==================================================================================================
///
@ -39,10 +40,12 @@ public:
void loadDataAndUpdate();
size_t plotCount() const;
void addPlot(RimWellAllocationPlot* plot);
RimWellAllocationPlot* defaultPlot();
void addWellAllocPlotToStoredPlots(RimWellAllocationPlot* plot);
RimWellAllocationPlot* defaultWellAllocPlot();
RimFlowCharacteristicsPlot* defaultFlowCharacteristicsPlot();
private:
caf::PdmChildField<RimWellAllocationPlot*> m_defaultPlot;
caf::PdmChildArrayField<RimWellAllocationPlot*> m_flowPlots;
caf::PdmChildField<RimFlowCharacteristicsPlot*> m_flowCharacteristicsPlot;
caf::PdmChildField<RimWellAllocationPlot*> m_defaultWellAllocPlot;
caf::PdmChildArrayField<RimWellAllocationPlot*> m_storedWellAllocPlots;
};

View File

@ -296,7 +296,8 @@ void RimWellAllocationPlot::updateFromWell()
QString wellStatusText = QString("(%1)").arg(RimWellAllocationPlot::wellStatusTextForTimeStep(m_wellName, m_case, m_timeStep));
setDescription("Well Allocation: " + m_wellName + " " + wellStatusText + ", " + m_case->timeStepStrings()[m_timeStep] + " (" + m_case->caseUserDescription() + ")");
QString flowTypeText = m_flowType().uiText();
setDescription(flowTypeText + " : " + m_wellName + " " + wellStatusText + ", " + m_case->timeStepStrings()[m_timeStep] + " (" + m_case->caseUserDescription() + ")");
/// Pie chart
@ -491,6 +492,7 @@ QWidget* RimWellAllocationPlot::viewWidget()
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::zoomAll()
{
m_accumulatedWellFlowPlot()->zoomAll();
}
//--------------------------------------------------------------------------------------------------

View File

@ -34,6 +34,8 @@
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimFault.h"
#include "RimFlowDiagSolution.h"
#include "RimFlowPlotCollection.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimGeoMechCase.h"
@ -137,6 +139,7 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
commandIds << "Separator";
commandIds << "RicNewViewFeature";
commandIds << "RicShowFlowCharacteristicsPlotFeature";
commandIds << "RicEclipseCaseNewGroupFeature";
commandIds << "Separator";
commandIds << "RicCopyReferencesToClipboardFeature";
@ -353,6 +356,14 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
{
commandIds << "RicAddStoredWellAllocationPlotFeature";
}
else if (dynamic_cast<RimFlowDiagSolution*>(uiItem))
{
commandIds << "RicShowFlowCharacteristicsPlotFeature";
}
else if (dynamic_cast<RimFlowPlotCollection*>(uiItem))
{
commandIds << "RicShowFlowCharacteristicsPlotFeature";
}
if (dynamic_cast<RimView*>(uiItem))

View File

@ -602,3 +602,19 @@ QString RimEclipseCase::timeStepName(int frameIdx)
return date.toString(m_timeStepFormatString);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QDateTime RimEclipseCase::timeStepDate(int frameIdx)
{
return results(RifReaderInterface::MATRIX_RESULTS)->cellResults()->timeStepDate(0,frameIdx);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QDateTime> RimEclipseCase::timeStepDates()
{
return results(RifReaderInterface::MATRIX_RESULTS)->cellResults()->timeStepDates();
}

View File

@ -86,6 +86,9 @@ public:
virtual std::vector<RimView*> views();
virtual QStringList timeStepStrings();
virtual QString timeStepName(int frameIdx);
virtual QDateTime timeStepDate(int frameIdx);
std::vector<QDateTime> timeStepDates();
virtual cvf::BoundingBox activeCellsBoundingBox() const;
virtual cvf::BoundingBox allCellsBoundingBox() const;

View File

@ -279,6 +279,30 @@ bool RimEclipsePropertyFilter::isPropertyFilterControlled()
return isPropertyFilterControlled;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipsePropertyFilter::setCategoriesFromTracerNames(const std::vector<QString>& tracerNames)
{
std::vector<std::pair<QString, int>> tracerNameValuesSorted;
{
std::set<std::pair<QString, int>> tracerNameSet;
for (size_t i = 0; i < tracerNames.size(); i++)
{
tracerNameSet.insert(std::make_pair(tracerNames[i], static_cast<int>(i)));
}
for (auto it : tracerNameSet)
{
tracerNameValuesSorted.push_back(it);
}
}
setCategoryNamesAndValues(tracerNameValuesSorted);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -337,7 +361,7 @@ void RimEclipsePropertyFilter::computeResultValueRange()
if ( resultDefinition->hasCategoryResult() )
{
setCategoryNames(resultDefinition->flowDiagSolution()->tracerNames());
setCategoriesFromTracerNames(resultDefinition->flowDiagSolution()->tracerNames());
}
}
}
@ -423,7 +447,7 @@ void RimEclipsePropertyFilter::updateFromCurrentTimeStep()
if (resultDefinition->hasCategoryResult())
{
setCategoryNames(resultDefinition->flowDiagSolution()->tracerNames());
setCategoriesFromTracerNames(resultDefinition->flowDiagSolution()->tracerNames());
}
}

View File

@ -71,6 +71,7 @@ private:
void updateReadOnlyStateOfAllFields();
void updateRangeLabel();
bool isPropertyFilterControlled();
void setCategoriesFromTracerNames(const std::vector<QString>& tracerNames);
RimEclipsePropertyFilterCollection* parentContainer();

View File

@ -105,6 +105,8 @@ RimEclipseResultDefinition::RimEclipseResultDefinition()
m_selectedTracersUiField.xmlCapability()->setIOReadable(false);
m_selectedTracersUiField.xmlCapability()->setIOWritable(false);
m_selectedTracersUiField.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_selectedTracersUiFieldFilter, "SelectedTracersFilter", "Filter", "", "", "");
}
//--------------------------------------------------------------------------------------------------
@ -202,10 +204,56 @@ void RimEclipseResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* cha
if ( &m_selectedTracersUiField == changedField )
{
m_flowSolution = m_flowSolutionUiField();
m_selectedTracers = m_selectedTracersUiField();
if (m_selectedTracersUiFieldFilter().isEmpty())
{
m_selectedTracers = m_selectedTracersUiField();
}
else
{
auto filteredTracerNames = tracerNamesMatchingFilter();
// Keep selected strings not part of currently visible selection items
std::vector<QString> newSelection;
for (auto selectedTracer : m_selectedTracers())
{
if (std::find(begin(filteredTracerNames), end(filteredTracerNames), selectedTracer) == end(filteredTracerNames))
{
newSelection.push_back(selectedTracer);
}
}
for (auto selectedTracerUi : m_selectedTracersUiField())
{
newSelection.push_back(selectedTracerUi);
}
m_selectedTracers = newSelection;
}
loadDataAndUpdate();
}
if (&m_selectedTracersUiFieldFilter == changedField)
{
auto visibleTracerNames = tracerNamesMatchingFilter();
std::vector<QString> subSelection;
// Remove hidden items from selection
for (auto selectedTracer : m_selectedTracers())
{
if (std::find(begin(visibleTracerNames), end(visibleTracerNames), selectedTracer) != end(visibleTracerNames))
{
subSelection.push_back(selectedTracer);
}
}
m_selectedTracersUiField = subSelection;
updateConnectedEditors();
}
updateAnyFieldHasChanged();
}
@ -347,6 +395,19 @@ void RimEclipseResultDefinition::loadDataAndUpdate()
}
}
bool isStringMatch(const QString& filterString, const QString& value)
{
if (filterString.isEmpty()) return true;
if (filterString.trimmed() == "*")
{
if (!value.isEmpty()) return true;
else return false;
}
QRegExp searcher(filterString, Qt::CaseInsensitive, QRegExp::WildcardUnix);
return searcher.exactMatch(value);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -356,7 +417,6 @@ QList<caf::PdmOptionItemInfo> RimEclipseResultDefinition::calculateValueOptions(
if ( fieldNeedingOptions == &m_resultTypeUiField )
{
bool hasFlowDiagFluxes = false;
RimEclipseResultCase* eclResCase = dynamic_cast<RimEclipseResultCase*>(m_eclipseCase.p());
if ( eclResCase && eclResCase->eclipseCaseData() )
@ -389,7 +449,7 @@ QList<caf::PdmOptionItemInfo> RimEclipseResultDefinition::calculateValueOptions(
{
if ( fieldNeedingOptions == &m_resultVariableUiField )
{
options = calcOptionsForVariableUiFieldStandard();
options = calcOptionsForVariableUiFieldStandard();
}
}
else
@ -419,7 +479,7 @@ QList<caf::PdmOptionItemInfo> RimEclipseResultDefinition::calculateValueOptions(
RimFlowDiagSolution* flowSol = m_flowSolutionUiField();
if (flowSol)
{
std::vector<QString> tracerNames = flowSol->tracerNames();
std::vector<QString> tracerNames = tracerNamesMatchingFilter();
std::map<QString, QString> prefixedTracerNamesMap;
for ( const QString& tracerName : tracerNames )
{
@ -935,6 +995,7 @@ void RimEclipseResultDefinition::defineUiOrdering(QString uiConfigName, caf::Pdm
if (m_flowTracerSelectionMode == FLOW_TR_BY_SELECTION)
{
uiOrdering.add(&m_selectedTracersUiFieldFilter);
uiOrdering.add(&m_selectedTracersUiField);
}
@ -948,6 +1009,22 @@ void RimEclipseResultDefinition::defineUiOrdering(QString uiConfigName, caf::Pdm
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseResultDefinition::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
{
if (m_resultTypeUiField() == RimDefines::FLOW_DIAGNOSTICS
&& field == &m_resultVariableUiField)
{
caf::PdmUiListEditorAttribute* listEditAttr = dynamic_cast<caf::PdmUiListEditorAttribute*>(attribute);
if (listEditAttr)
{
listEditAttr->m_heightHint = 50;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -973,3 +1050,33 @@ void RimEclipseResultDefinition::removePerCellFaceOptionItems(QList<caf::PdmOpti
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RimEclipseResultDefinition::tracerNamesMatchingFilter() const
{
std::vector<QString> matchingNames;
RimFlowDiagSolution* flowSol = m_flowSolutionUiField();
if (flowSol)
{
std::vector<QString> tracerNames = flowSol->tracerNames();
if (m_selectedTracersUiFieldFilter().isEmpty())
{
matchingNames = tracerNames;
}
else
{
for (const QString& tracerName : tracerNames)
{
if (isStringMatch(m_selectedTracersUiFieldFilter, tracerName))
{
matchingNames.push_back(tracerName);
}
}
}
}
return matchingNames;
}

View File

@ -101,6 +101,7 @@ protected:
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue);
virtual void initAfterRead();
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
protected:
caf::PdmField< caf::AppEnum< RimDefines::ResultCatType > > m_resultType;
@ -122,6 +123,8 @@ protected:
caf::PdmField< caf::AppEnum< FlowTracerSelectionType > > m_flowTracerSelectionMode;
caf::PdmPtrField<RimFlowDiagSolution*> m_flowSolutionUiField;
caf::PdmField<QString> m_selectedTracersUiFieldFilter;
caf::PdmField<std::vector<QString> > m_selectedTracersUiField;
@ -136,5 +139,7 @@ private:
QList<caf::PdmOptionItemInfo> calcOptionsForVariableUiFieldStandard();
QStringList getResultNamesForCurrentUiResultType();
static void removePerCellFaceOptionItems(QList<caf::PdmOptionItemInfo>& optionItems);
std::vector<QString> tracerNamesMatchingFilter() const;
};

View File

@ -102,6 +102,20 @@ void RimPropertyFilter::setCategoryNames(const std::vector<QString>& categoryNam
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPropertyFilter::setCategoryNamesAndValues(const std::vector<std::pair<QString, int>>& categoryNamesAndValues)
{
clearCategories();
for (auto it : categoryNamesAndValues)
{
m_categoryNames.push_back(it.first);
m_categoryValues.push_back(it.second);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -37,6 +37,7 @@ public:
protected:
void setCategoryValues(const std::vector<int>& categoryValues);
void setCategoryNames(const std::vector<QString>& categoryNames);
void setCategoryNamesAndValues(const std::vector<std::pair<QString, int>>& categoryNamesAndValues);
void clearCategories();
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;

View File

@ -160,11 +160,14 @@ void RimViewWindow::updateMdiWindowTitle()
{
if ( viewWidget() )
{
caf::PdmUiFieldHandle* uiFieldHandle = this->userDescriptionField()->uiCapability();
if ( uiFieldHandle )
if ( this->userDescriptionField() )
{
QVariant v = uiFieldHandle->uiValue();
viewWidget()->setWindowTitle(v.toString());
caf::PdmUiFieldHandle* uiFieldHandle = this->userDescriptionField()->uiCapability();
if ( uiFieldHandle )
{
QVariant v = uiFieldHandle->uiValue();
viewWidget()->setWindowTitle(v.toString());
}
}
}
}

View File

@ -64,7 +64,11 @@ private:
{
if (!(*m_cellVisibilities)[cIdx]) continue;
size_t cellResultIndex = actCellInfo->cellResultIndex(cIdx);
size_t cellResultIndex = cIdx;
if (m_caseData->isUsingGlobalActiveIndex(m_scalarResultIndex))
{
cellResultIndex = actCellInfo->cellResultIndex(cIdx);
}
if (cellResultIndex != cvf::UNDEFINED_SIZE_T) accumulator.addValue(values[cellResultIndex]);
}

View File

@ -29,6 +29,8 @@
#include "RigFlowDiagResultFrames.h"
#include "RigStatisticsDataCache.h"
#include <cmath> // Needed for HUGE_VAL on Linux
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -39,6 +41,7 @@ RigFlowDiagResults::RigFlowDiagResults(RimFlowDiagSolution* flowSolution, size_t
m_timeStepCount = timeStepCount;
m_hasAtemptedNativeResults.resize(timeStepCount, false);
m_injProdPairFluxCommunicationTimesteps.resize(timeStepCount);
m_flowCharResultFrames.resize(timeStepCount);
}
//--------------------------------------------------------------------------------------------------
@ -118,6 +121,12 @@ void RigFlowDiagResults::calculateNativeResultsIfNotPreviouslyAttempted(size_t f
m_injProdPairFluxCommunicationTimesteps[frameIndex].swap(nativeTimestepResults.injProdWellPairFluxes());
m_flowCharResultFrames[frameIndex].m_lorenzCoefficient = nativeTimestepResults.lorenzCoefficient();
m_flowCharResultFrames[frameIndex].m_flowCapStorageCapCurve.first.swap(nativeTimestepResults.flowCapStorageCapCurve().first);
m_flowCharResultFrames[frameIndex].m_flowCapStorageCapCurve.second.swap(nativeTimestepResults.flowCapStorageCapCurve().second);
m_flowCharResultFrames[frameIndex].m_sweepEfficiencyCurve.first.swap(nativeTimestepResults.sweepEfficiencyCurve().first);
m_flowCharResultFrames[frameIndex].m_sweepEfficiencyCurve.second.swap(nativeTimestepResults.sweepEfficiencyCurve().second);
m_hasAtemptedNativeResults[frameIndex] = true;
}
}
@ -652,3 +661,26 @@ double RigFlowDiagResults::maxAbsPairFlux(int frameIndex)
return maxFlux;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<int> RigFlowDiagResults::calculatedTimeSteps()
{
std::vector<int> timestepIndices;
for (size_t tsIdx = 0; tsIdx < m_timeStepCount; ++tsIdx)
{
if (m_hasAtemptedNativeResults[tsIdx]) timestepIndices.push_back(static_cast<int>(tsIdx));
}
return timestepIndices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagResults::FlowCharacteristicsResultFrame::FlowCharacteristicsResultFrame()
: m_lorenzCoefficient(HUGE_VAL)
{
}

View File

@ -19,6 +19,10 @@
#include "RigFlowDiagResultAddress.h"
#include "RimFlowDiagSolution.h"
#include "cafPdmPointer.h"
#include "cvfBase.h"
#include "cvfObject.h"
@ -26,9 +30,6 @@
#include <map>
#include <string>
#include "cafPdmPointer.h"
#include "RimFlowDiagSolution.h"
class RigFlowDiagResultFrames;
class RigStatisticsDataCache;
class RigFlowDiagSolverInterface;
@ -62,6 +63,21 @@ public:
std::pair<double, double> injectorProducerPairFluxes(const std::string& injTracername, const std::string& prodTracerName, int frameIndex);
double maxAbsPairFlux(int frameIndex);
std::vector<int> calculatedTimeSteps();
struct FlowCharacteristicsResultFrame
{
FlowCharacteristicsResultFrame();
using Curve = std::pair< std::vector<double>, std::vector<double> >;
Curve m_flowCapStorageCapCurve;
Curve m_sweepEfficiencyCurve;
double m_lorenzCoefficient;
};
const FlowCharacteristicsResultFrame& flowCharacteristicsResults(int frameIndex) { return m_flowCharResultFrames[frameIndex];}
private:
const std::vector<double>* findOrCalculateResult (const RigFlowDiagResultAddress& resVarAddr, size_t frameIndex);
void calculateNativeResultsIfNotPreviouslyAttempted(size_t frameIndex);
@ -118,6 +134,10 @@ private:
using InjectorProducerCommunicationMap = std::map< std::pair<std::string, std::string>, std::pair<double, double> >;
std::vector<InjectorProducerCommunicationMap> m_injProdPairFluxCommunicationTimesteps;
std::vector<FlowCharacteristicsResultFrame> m_flowCharResultFrames;
};

View File

@ -39,7 +39,7 @@
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagTimeStepResult::RigFlowDiagTimeStepResult(size_t activeCellCount)
: m_activeCellCount(activeCellCount)
: m_activeCellCount(activeCellCount), m_lorenzCoefficient(HUGE_VAL)
{
}
@ -107,12 +107,16 @@ void RigFlowDiagTimeStepResult::addResult(const RigFlowDiagResultAddress& resAdd
class RigOpmFldStaticData : public cvf::Object
{
public:
RigOpmFldStaticData(const std::string& grid, const std::string& init) : eclGraph(Opm::ECLGraph::load(grid, init)), m_hasUnifiedRestartFile(false) {}
RigOpmFldStaticData(const std::string& grid, const std::string& init) : m_eclGraph(Opm::ECLGraph::load(grid, init)), m_hasUnifiedRestartFile(false)
{
m_poreVolume = m_eclGraph.poreVolume();
}
Opm::ECLGraph eclGraph;
std::unique_ptr<Opm::FlowDiagnostics::Toolbox> fldToolbox;
bool m_hasUnifiedRestartFile;
QStringList restartFileNames;
Opm::ECLGraph m_eclGraph;
std::vector<double> m_poreVolume;
std::unique_ptr<Opm::FlowDiagnostics::Toolbox> m_fldToolbox;
bool m_hasUnifiedRestartFile;
QStringList m_restartFileNames;
};
@ -168,31 +172,31 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
progressInfo.setProgressDescription("Calculating Connectivities");
const Opm::FlowDiagnostics::ConnectivityGraph connGraph =
Opm::FlowDiagnostics::ConnectivityGraph{ static_cast<int>(m_opmFldData->eclGraph.numCells()),
m_opmFldData->eclGraph.neighbours() };
Opm::FlowDiagnostics::ConnectivityGraph{ static_cast<int>(m_opmFldData->m_eclGraph.numCells()),
m_opmFldData->m_eclGraph.neighbours() };
progressInfo.incrementProgress();
progressInfo.setProgressDescription("Initialize Solver");
// Create the Toolbox.
m_opmFldData->fldToolbox.reset(new Opm::FlowDiagnostics::Toolbox{ connGraph });
m_opmFldData->fldToolbox->assignPoreVolume( m_opmFldData->eclGraph.poreVolume());
m_opmFldData->m_fldToolbox.reset(new Opm::FlowDiagnostics::Toolbox{ connGraph });
m_opmFldData->m_fldToolbox->assignPoreVolume( m_opmFldData->m_poreVolume);
// Look for unified restart file
QString restartFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_UNIFIED_RESTART_FILE);
if ( !restartFileName.isEmpty() )
{
m_opmFldData->eclGraph.assignFluxDataSource(restartFileName.toStdString());
m_opmFldData->m_eclGraph.assignFluxDataSource(restartFileName.toStdString());
m_opmFldData->m_hasUnifiedRestartFile = true;
}
else
{
m_opmFldData->restartFileNames = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE);
m_opmFldData->m_restartFileNames = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE);
size_t restartFileCount = static_cast<size_t>(m_opmFldData->restartFileNames.size());
size_t restartFileCount = static_cast<size_t>(m_opmFldData->m_restartFileNames.size());
size_t maxTimeStepCount = m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->maxTimeStepCount();
if (restartFileCount <= timeStepIndex && restartFileCount != maxTimeStepCount )
@ -201,7 +205,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
return result;
}
m_opmFldData->restartFileNames.sort(); // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file.
m_opmFldData->m_restartFileNames.sort(); // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file.
m_opmFldData->m_hasUnifiedRestartFile = false;
}
}
@ -211,8 +215,8 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
if ( ! m_opmFldData->m_hasUnifiedRestartFile )
{
QString restartFileName = m_opmFldData->restartFileNames[static_cast<int>(timeStepIndex)];
m_opmFldData->eclGraph.assignFluxDataSource(restartFileName.toStdString());
QString restartFileName = m_opmFldData->m_restartFileNames[static_cast<int>(timeStepIndex)];
m_opmFldData->m_eclGraph.assignFluxDataSource(restartFileName.toStdString());
}
size_t resultIndexWithMaxTimeSteps = cvf::UNDEFINED_SIZE_T;
@ -220,7 +224,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
int reportStepNumber = m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->reportStepNumber(resultIndexWithMaxTimeSteps, timeStepIndex);
if ( ! m_opmFldData->eclGraph.selectReportStep(reportStepNumber) )
if ( ! m_opmFldData->m_eclGraph.selectReportStep(reportStepNumber) )
{
QMessageBox::critical(nullptr, "ResInsight", "Flow Diagnostics: Could not find the requested timestep in the result file. Results will not be loaded.");
return result;
@ -231,20 +235,20 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
Opm::FlowDiagnostics::CellSetValues sumWellFluxPrCell;
{
Opm::FlowDiagnostics::ConnectionValues connectionsVals = RigFlowDiagInterfaceTools::extractFluxField(m_opmFldData->eclGraph, false);
Opm::FlowDiagnostics::ConnectionValues connectionsVals = RigFlowDiagInterfaceTools::extractFluxField(m_opmFldData->m_eclGraph, false);
m_opmFldData->fldToolbox->assignConnectionFlux(connectionsVals);
m_opmFldData->m_fldToolbox->assignConnectionFlux(connectionsVals);
progressInfo.incrementProgress();
Opm::ECLWellSolution wsol = Opm::ECLWellSolution{-1.0 , false};
const std::vector<Opm::ECLWellSolution::WellData> well_fluxes =
wsol.solution(m_opmFldData->eclGraph.rawResultData(), m_opmFldData->eclGraph.numGrids());
wsol.solution(m_opmFldData->m_eclGraph.rawResultData(), m_opmFldData->m_eclGraph.numGrids());
sumWellFluxPrCell = RigFlowDiagInterfaceTools::extractWellFlows(m_opmFldData->eclGraph, well_fluxes);
sumWellFluxPrCell = RigFlowDiagInterfaceTools::extractWellFlows(m_opmFldData->m_eclGraph, well_fluxes);
m_opmFldData->fldToolbox->assignInflowFlux(sumWellFluxPrCell);
m_opmFldData->m_fldToolbox->assignInflowFlux(sumWellFluxPrCell);
// Filter connection cells with inconsistent well in flow direction (Hack, we should do something better)
@ -295,7 +299,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
std::unique_ptr<Toolbox::Forward> injectorSolution;
try
{
injectorSolution.reset(new Toolbox::Forward( m_opmFldData->fldToolbox->computeInjectionDiagnostics(injectorCellSets)));
injectorSolution.reset(new Toolbox::Forward( m_opmFldData->m_fldToolbox->computeInjectionDiagnostics(injectorCellSets)));
}
catch (const std::exception& e)
{
@ -325,7 +329,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
std::unique_ptr<Toolbox::Reverse> producerSolution;
try
{
producerSolution.reset(new Toolbox::Reverse(m_opmFldData->fldToolbox->computeProductionDiagnostics(prodjCellSets)));
producerSolution.reset(new Toolbox::Reverse(m_opmFldData->m_fldToolbox->computeProductionDiagnostics(prodjCellSets)));
}
catch ( const std::exception& e )
{
@ -366,6 +370,21 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
}
}
}
try
{
Graph flowCapStorCapCurve = flowCapacityStorageCapacityCurve(*(injectorSolution.get()),
*(producerSolution.get()),
m_opmFldData->m_poreVolume);
result.setFlowCapStorageCapCurve(flowCapStorCapCurve);
result.setSweepEfficiencyCurve(sweepEfficiency(flowCapStorCapCurve));
result.setLorenzCoefficient(lorenzCoefficient(flowCapStorCapCurve));
}
catch ( const std::exception& e )
{
QMessageBox::critical(nullptr, "ResInsight", "Flow Diagnostics: " + QString(e.what()));
}
}
return result; // Relying on implicit move constructor

View File

@ -41,17 +41,30 @@ public:
const std::string& producerTracerName,
const std::pair<double, double>& injProdFluxes) ;
// Use to "steal" the data from this one using swap
std::map<RigFlowDiagResultAddress, std::vector<double> >& nativeResults() { return m_nativeResults; }
using Curve = std::pair< std::vector<double>, std::vector<double> >;
void setFlowCapStorageCapCurve(const Curve& flCapStCapCurve) { m_flowCapStorageCapCurve = flCapStCapCurve;}
void setSweepEfficiencyCurve(const Curve& sweepEffCurve) { m_sweepEfficiencyCurve = sweepEffCurve; }
void setLorenzCoefficient(double coeff) { m_lorenzCoefficient = coeff;}
// Used to "steal" the data from this one using swap
std::map<RigFlowDiagResultAddress, std::vector<double> >& nativeResults() { return m_nativeResults; }
std::map<std::pair<std::string, std::string>, std::pair<double, double> > & injProdWellPairFluxes() { return m_injProdWellPairFluxes; }
Curve& flowCapStorageCapCurve() { return m_flowCapStorageCapCurve; }
Curve& sweepEfficiencyCurve() { return m_sweepEfficiencyCurve; }
double lorenzCoefficient() { return m_lorenzCoefficient;}
private:
void addResult(const RigFlowDiagResultAddress& resAddr, const std::map<int, double>& cellValues);
std::map<RigFlowDiagResultAddress, std::vector<double> > m_nativeResults;
std::map<RigFlowDiagResultAddress, std::vector<double> > m_nativeResults;
std::map<std::pair<std::string, std::string>, std::pair<double, double> > m_injProdWellPairFluxes;
Curve m_flowCapStorageCapCurve;
Curve m_sweepEfficiencyCurve;
double m_lorenzCoefficient;
size_t m_activeCellCount;
};

View File

@ -20,6 +20,8 @@ ${CEE_CURRENT_LIST_DIR}RiuProcessMonitor.h
${CEE_CURRENT_LIST_DIR}RiuProjectPropertyView.h
${CEE_CURRENT_LIST_DIR}RiuPropertyViewTabWidget.h
${CEE_CURRENT_LIST_DIR}RiuQwtScalePicker.h
${CEE_CURRENT_LIST_DIR}RiuQwtCurvePointTracker.h
${CEE_CURRENT_LIST_DIR}RiuQwtPlotWheelZoomer.h
${CEE_CURRENT_LIST_DIR}RiuRecentFileActionProvider.h
${CEE_CURRENT_LIST_DIR}RiuResultInfoPanel.h
${CEE_CURRENT_LIST_DIR}RiuResultQwtPlot.h
@ -39,6 +41,7 @@ ${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.h
${CEE_CURRENT_LIST_DIR}RiuFemTimeHistoryResultAccessor.h
${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h
${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h
${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h
${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h
)
@ -59,6 +62,8 @@ ${CEE_CURRENT_LIST_DIR}RiuProcessMonitor.cpp
${CEE_CURRENT_LIST_DIR}RiuProjectPropertyView.cpp
${CEE_CURRENT_LIST_DIR}RiuPropertyViewTabWidget.cpp
${CEE_CURRENT_LIST_DIR}RiuQwtScalePicker.cpp
${CEE_CURRENT_LIST_DIR}RiuQwtCurvePointTracker.cpp
${CEE_CURRENT_LIST_DIR}RiuQwtPlotWheelZoomer.cpp
${CEE_CURRENT_LIST_DIR}RiuRecentFileActionProvider.cpp
${CEE_CURRENT_LIST_DIR}RiuResultInfoPanel.cpp
${CEE_CURRENT_LIST_DIR}RiuResultQwtPlot.cpp
@ -78,6 +83,7 @@ ${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.cpp
${CEE_CURRENT_LIST_DIR}RiuFemTimeHistoryResultAccessor.cpp
${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.cpp
${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.cpp
${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.cpp
${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.cpp
${CEE_CURRENT_LIST_DIR}RiuMessagePanel.cpp
)
@ -105,8 +111,10 @@ ${CEE_CURRENT_LIST_DIR}RiuWellLogTrack.h
${CEE_CURRENT_LIST_DIR}RiuRecentFileActionProvider.h
${CEE_CURRENT_LIST_DIR}RiuSummaryQwtPlot.h
${CEE_CURRENT_LIST_DIR}RiuQwtScalePicker.h
${CEE_CURRENT_LIST_DIR}RiuQwtPlotWheelZoomer.h
${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h
${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h
${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h
${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h
)

View File

@ -0,0 +1,265 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuFlowCharacteristicsPlot.h"
#include "RimFlowCharacteristicsPlot.h"
#include "RiuResultQwtPlot.h"
#include "qwt_plot.h"
#include "cvfBase.h"
#include "cvfColor3.h"
#include <QBoxLayout>
#include <QContextMenuEvent>
#include <QLabel>
#include <QMenu>
#include "RiuLineSegmentQwtPlotCurve.h"
#include <QDateTime>
#include "RiuSummaryQwtPlot.h"
#include "RiuQwtPlotWheelZoomer.h"
#include "qwt_plot_zoomer.h"
#include "RiaColorTables.h"
#include "qwt_plot_zoneitem.h"
#include "qwt_date.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlot* plotDefinition, QWidget* parent)
: m_plotDefinition(plotDefinition),
QFrame(parent)
{
Q_ASSERT(m_plotDefinition);
QGridLayout* mainLayout = new QGridLayout();
this->setLayout(mainLayout);
this->layout()->setMargin(3);
this->layout()->setSpacing(3);
// White background
QPalette pal = this->palette();
pal.setColor(QPalette::Background, Qt::white);
this->setAutoFillBackground(true);
this->setPalette(pal);
m_lorenzPlot = new QwtPlot(this);
m_flowCapVsStorageCapPlot = new QwtPlot(this);
m_sweepEffPlot = new QwtPlot(this);
mainLayout->addWidget(m_lorenzPlot, 0 ,0, 1, 2);
mainLayout->addWidget(m_flowCapVsStorageCapPlot, 1, 0);
mainLayout->addWidget(m_sweepEffPlot, 1, 1);
RiuSummaryQwtPlot::setCommonPlotBehaviour(m_lorenzPlot);
new RiuQwtPlotWheelZoomer(m_lorenzPlot);
addWindowZoom(m_lorenzPlot);
RiuSummaryQwtPlot::enableDateBasedBottomXAxis(m_lorenzPlot);
m_lorenzPlot->setTitle("Lorenz Coefficient");
RiuSummaryQwtPlot::setCommonPlotBehaviour(m_sweepEffPlot);
new RiuQwtPlotWheelZoomer(m_sweepEffPlot);
addWindowZoom(m_sweepEffPlot);
m_sweepEffPlot->setTitle("Sweep Efficiency");
RiuSummaryQwtPlot::setCommonPlotBehaviour(m_flowCapVsStorageCapPlot);
new RiuQwtPlotWheelZoomer(m_flowCapVsStorageCapPlot);
addWindowZoom(m_flowCapVsStorageCapPlot);
m_flowCapVsStorageCapPlot->setTitle("Flow Capacity vs Storage Capacity");
}
void RiuFlowCharacteristicsPlot::addWindowZoom(QwtPlot* plot)
{
auto zoomer = new QwtPlotZoomer(plot->canvas());
zoomer->setRubberBandPen(QColor(Qt::black));
zoomer->setTrackerMode(QwtPicker::AlwaysOff);
zoomer->setTrackerPen(QColor(Qt::black));
zoomer->initMousePattern(1);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuFlowCharacteristicsPlot::~RiuFlowCharacteristicsPlot()
{
if (m_plotDefinition)
{
m_plotDefinition->handleMdiWindowClosed();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector<QDateTime>& dateTimes, const std::vector<double>& timeHistoryValues)
{
initializeColors(dateTimes);
m_lorenzPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true);
auto curve = createEmptyCurve(m_lorenzPlot, "Lorenz Coefficient", QColor(0, 0, 0));
curve->setSamplesFromDateAndValues(dateTimes, timeHistoryValues, false);
//curve->setSymbol(QwtSymbol )
//size_t tsIdx = 0;
//for ( const QDateTime& dateTime: dateTimes )
//{
// auto curve = createEmptyCurve(m_lorenzPlot, dateTime.toString(), m_dateToColorMap[dateTime]);
// std::vector<QDateTime> timeStep;
// timeStep.push_back(dateTime);
// std::vector<double> lorCoeff;
// lorCoeff.push_back(timeHistoryValues[tsIdx]);
//
// curve->setSamplesFromDateAndValues(timeStep, lorCoeff, false);
//
// ++tsIdx;
//}
//double milliSecSinceEpoch = QwtDate::toDouble(filteredDateTimes[i]);
for ( size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx )
{
double currentTsValue = QwtDate::toDouble(dateTimes[tsIdx]);
double minTsValue = currentTsValue;
if ( tsIdx > 0 ) minTsValue = 0.5 * (currentTsValue + QwtDate::toDouble(dateTimes[tsIdx-1]));
double maxTsValue = currentTsValue;
if ( tsIdx < dateTimes.size()-1 ) maxTsValue = 0.5 * (currentTsValue + QwtDate::toDouble(dateTimes[tsIdx+1]));
auto plotZone = new QwtPlotZoneItem();
plotZone->setOrientation(Qt::Vertical);
plotZone->setInterval(minTsValue, maxTsValue);
plotZone->setBrush(QBrush(m_dateToColorMap[dateTimes[tsIdx]]));
plotZone->attach(m_lorenzPlot);
}
m_lorenzPlot->replot();
}
RiuLineSegmentQwtPlotCurve* RiuFlowCharacteristicsPlot::createEmptyCurve(QwtPlot* plot, const QString& curveName, const QColor& curveColor )
{
RiuLineSegmentQwtPlotCurve* plotCurve = new RiuLineSegmentQwtPlotCurve(curveName);
plotCurve->setTitle(curveName);
plotCurve->setPen(QPen(curveColor));
plotCurve->attach(plot);
return plotCurve;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::addFlowCapStorageCapCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals)
{
CVF_ASSERT(!m_dateToColorMap.empty());
RiuLineSegmentQwtPlotCurve* plotCurve = createEmptyCurve(m_flowCapVsStorageCapPlot, dateTime.toString(), m_dateToColorMap[dateTime]);
plotCurve->setSamplesFromTimeAndValues(xVals, yVals, false);
m_flowCapVsStorageCapPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::addSweepEfficiencyCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals)
{
CVF_ASSERT(!m_dateToColorMap.empty());
RiuLineSegmentQwtPlotCurve* plotCurve = createEmptyCurve(m_sweepEffPlot, dateTime.toString(), m_dateToColorMap[dateTime]);
plotCurve->setSamplesFromTimeAndValues(xVals, yVals, false);
m_sweepEffPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::removeAllCurves()
{
m_lorenzPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true);
m_sweepEffPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true);
m_flowCapVsStorageCapPlot->detachItems(QwtPlotItem::Rtti_PlotCurve, true);
m_dateToColorMap.clear();
}
void zoomAllInPlot(QwtPlot * plot)
{
plot->setAxisAutoScale(QwtPlot::xBottom, true);
plot->setAxisAutoScale(QwtPlot::yLeft, true);
plot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::zoomAll()
{
zoomAllInPlot(m_lorenzPlot);
zoomAllInPlot(m_sweepEffPlot);
zoomAllInPlot(m_flowCapVsStorageCapPlot);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot* RiuFlowCharacteristicsPlot::ownerPlotDefinition()
{
return m_plotDefinition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuFlowCharacteristicsPlot::minimumSizeHint() const
{
return QSize(0, 100);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuFlowCharacteristicsPlot::sizeHint() const
{
return QSize(0, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::setDefaults()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::initializeColors(const std::vector<QDateTime>& dateTimes)
{
CVF_ASSERT(m_dateToColorMap.empty());
const caf::ColorTable& palette = RiaColorTables::timestepsPaletteColors();
cvf::Color3ubArray colorArray = caf::ColorTable::interpolateColorArray(palette.color3ubArray(), dateTimes.size());
for (size_t tsIdx = 0; tsIdx < dateTimes.size(); ++tsIdx)
{
m_dateToColorMap[dateTimes[tsIdx]] = QColor( colorArray[tsIdx].r(), colorArray[tsIdx].g(), colorArray[tsIdx].b());
}
}

View File

@ -0,0 +1,82 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "qwt_plot.h"
#include "cafPdmPointer.h"
#include <QPointer>
#include <QFrame>
class RimFlowCharacteristicsPlot;
class RiuNightchartsWidget;
class RiuResultQwtPlot;
class RiuLineSegmentQwtPlotCurve;
class QLabel;
namespace cvf {
class Color3f;
}
//==================================================================================================
//
//
//
//==================================================================================================
class RiuFlowCharacteristicsPlot : public QFrame
{
Q_OBJECT;
public:
RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlot* plotDefinition, QWidget* parent = NULL);
virtual ~RiuFlowCharacteristicsPlot();
void setLorenzCurve(const std::vector<QDateTime>& dateTimes, const std::vector<double>& timeHistoryValues);
void addFlowCapStorageCapCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals);
void addSweepEfficiencyCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals);
void removeAllCurves();
void zoomAll();
RimFlowCharacteristicsPlot* ownerPlotDefinition();
static void addWindowZoom(QwtPlot* plot);
static RiuLineSegmentQwtPlotCurve* createEmptyCurve(QwtPlot* plot, const QString& curveName, const QColor& curveColor);
protected:
virtual QSize sizeHint() const override;
virtual QSize minimumSizeHint() const override;
private:
void setDefaults();
void initializeColors(const std::vector<QDateTime>& dateTimes);
private:
caf::PdmPointer<RimFlowCharacteristicsPlot> m_plotDefinition;
QPointer<QwtPlot> m_lorenzPlot;
QPointer<QwtPlot> m_flowCapVsStorageCapPlot;
QPointer<QwtPlot> m_sweepEffPlot;
std::map<QDateTime, QColor> m_dateToColorMap;
};

View File

@ -0,0 +1,232 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuQwtCurvePointTracker.h"
#include "qwt_plot_marker.h"
#include "qwt_symbol.h"
#include "qwt_plot_curve.h"
#include "qwt_date_scale_draw.h"
#include <float.h> // For DBL_MAX
#include <QEvent>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtCurvePointTracker::RiuQwtCurvePointTracker(QwtPlot* plot, bool isMainAxisHorizontal)
: QwtPlotPicker(plot->canvas()), m_plot(plot), m_isMainAxisHorizontal(isMainAxisHorizontal)
{
this->setTrackerMode(QwtPicker::AlwaysOn);
m_plotMarker = new QwtPlotMarker;
// QwtPlotMarker takes ownership of the symbol, it is deleted in destructor of QwtPlotMarker
QwtSymbol* mySymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(Qt::black, 2.0), QSize(12, 12));
m_plotMarker->setSymbol(mySymbol);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtCurvePointTracker::~RiuQwtCurvePointTracker()
{
m_plotMarker->detach();
delete m_plotMarker;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtCurvePointTracker::removeMarkerOnFocusLeave()
{
if ( m_plotMarker->plot() )
{
m_plotMarker->detach();
m_plot->replot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuQwtCurvePointTracker::eventFilter(QObject *watched, QEvent *event)
{
if ( event->type() == QEvent::Leave )
{
this->removeMarkerOnFocusLeave();
}
// pass the event on to the parent class
return QwtPlotPicker::eventFilter(watched, event);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QwtText RiuQwtCurvePointTracker::trackerText(const QPoint& pos) const
{
QwtText txt;
if ( m_plot )
{
QwtPlot::Axis relatedYAxis = QwtPlot::yLeft;
QwtPlot::Axis relatedXAxis = QwtPlot::xBottom;
QString mainAxisValueString;
QString valueAxisValueString;
QPointF closestPoint = closestCurvePoint(pos, &valueAxisValueString, &mainAxisValueString, &relatedXAxis, &relatedYAxis);
if ( !closestPoint.isNull() )
{
QString str = valueAxisValueString;
if ( !mainAxisValueString.isEmpty() )
{
str += QString(" (%1)").arg(mainAxisValueString);
}
txt.setText(str);
}
updateClosestCurvePointMarker(closestPoint, relatedXAxis, relatedYAxis);
}
return txt;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QPointF RiuQwtCurvePointTracker::closestCurvePoint(const QPoint& cursorPosition, QString* valueAxisValueString, QString* mainAxisValueString, QwtPlot::Axis* relatedXAxis, QwtPlot::Axis* relatedYAxis) const
{
QPointF samplePoint;
QwtPlotCurve* closestCurve = nullptr;
double distMin = DBL_MAX;
int closestPointSampleIndex = -1;
const QwtPlotItemList& itmList = m_plot->itemList();
for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++ )
{
if ( (*it)->rtti() == QwtPlotItem::Rtti_PlotCurve )
{
QwtPlotCurve* candidateCurve = static_cast<QwtPlotCurve*>(*it);
double dist = DBL_MAX;
int candidateSampleIndex = candidateCurve->closestPoint(cursorPosition, &dist);
if ( dist < distMin )
{
closestCurve = candidateCurve;
distMin = dist;
closestPointSampleIndex = candidateSampleIndex;
}
}
}
if ( closestCurve && distMin < 50 )
{
samplePoint = closestCurve->sample(closestPointSampleIndex);
if ( relatedXAxis ) *relatedXAxis = static_cast<QwtPlot::Axis>(closestCurve->xAxis());
if ( relatedYAxis ) *relatedYAxis = static_cast<QwtPlot::Axis>(closestCurve->yAxis());
}
if ( mainAxisValueString )
{
const QwtScaleDraw* mainAxisScaleDraw = m_isMainAxisHorizontal ? m_plot->axisScaleDraw(*relatedXAxis): m_plot->axisScaleDraw(*relatedYAxis);
auto dateScaleDraw = dynamic_cast<const QwtDateScaleDraw*>(mainAxisScaleDraw) ;
qreal mainAxisSampleVal = 0.0;
if ( m_isMainAxisHorizontal )
mainAxisSampleVal = samplePoint.x();
else
mainAxisSampleVal = samplePoint.y();
if ( dateScaleDraw )
{
QDateTime date = dateScaleDraw->toDateTime(mainAxisSampleVal);
*mainAxisValueString = date.toString("hh:mm dd.MMMM.yyyy");
}
else if ( mainAxisScaleDraw )
{
*mainAxisValueString = mainAxisScaleDraw->label(mainAxisSampleVal).text();
}
}
if ( valueAxisValueString && closestCurve )
{
const QwtScaleDraw* valueAxisScaleDraw = m_isMainAxisHorizontal ? m_plot->axisScaleDraw(*relatedYAxis): m_plot->axisScaleDraw(*relatedXAxis);
qreal valueAxisSampleVal = 0.0;
if ( m_isMainAxisHorizontal )
valueAxisSampleVal = samplePoint.y();
else
valueAxisSampleVal = samplePoint.x();
if ( valueAxisScaleDraw )
{
*valueAxisValueString = valueAxisScaleDraw->label(valueAxisSampleVal).text();
}
}
return samplePoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtCurvePointTracker::updateClosestCurvePointMarker(const QPointF& closestPoint, QwtPlot::Axis relatedXAxis, QwtPlot::Axis relatedYAxis) const
{
bool replotRequired = false;
if ( !closestPoint.isNull() )
{
if ( !m_plotMarker->plot() )
{
m_plotMarker->attach(m_plot);
replotRequired = true;
}
if ( m_plotMarker->value() != closestPoint )
{
m_plotMarker->setValue(closestPoint.x(), closestPoint.y());
// Set the axes that the marker realtes to, to make the positioning correct
m_plotMarker->setAxes(relatedXAxis, relatedYAxis);
// TODO : Should use a color or other visual indicator to show what axis the curve relates to
replotRequired = true;
}
}
else
{
if ( m_plotMarker->plot() )
{
m_plotMarker->detach();
replotRequired = true;
}
}
if ( replotRequired ) m_plot->replot();
}

View File

@ -0,0 +1,55 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "qwt_plot_picker.h"
#include "qwt_plot.h"
#include <QPointer>
class QwtPlotMarker;
//--------------------------------------------------------------------------------------------------
/// Class to add mouse over-tracking of curve points with text marker
//--------------------------------------------------------------------------------------------------
class RiuQwtCurvePointTracker : public QwtPlotPicker
{
public:
explicit RiuQwtCurvePointTracker(QwtPlot* plot, bool isMainAxisHorizontal);
~RiuQwtCurvePointTracker();
protected:
virtual bool eventFilter(QObject *, QEvent *) override;
void removeMarkerOnFocusLeave();
virtual QwtText trackerText(const QPoint& pos) const override;
QPointF closestCurvePoint(const QPoint& cursorPosition,
QString* valueAxisValueString,
QString* mainAxisValueString,
QwtPlot::Axis* relatedXAxis,
QwtPlot::Axis* relatedYAxis) const;
void updateClosestCurvePointMarker(const QPointF& closestPoint,
QwtPlot::Axis relatedXAxis,
QwtPlot::Axis relatedYAxis) const;
QPointer<QwtPlot> m_plot;
QwtPlotMarker* m_plotMarker;
bool m_isMainAxisHorizontal;
};

View File

@ -0,0 +1,73 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuQwtPlotWheelZoomer.h"
#include "qwt_plot.h"
#include <QEvent>
#include <QWheelEvent>
#define RIU_SCROLLWHEEL_ZOOMFACTOR 1.1
#define RIU_SCROLLWHEEL_PANFACTOR 0.1
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtPlotWheelZoomer::RiuQwtPlotWheelZoomer(QwtPlot* plot): QObject(plot), m_plot(plot)
{
plot->canvas()->installEventFilter(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void zoomOnAxis(QwtPlot* plot, QwtPlot::Axis axis, double zoomFactor, int eventPos)
{
QwtScaleMap scaleMap = plot->canvasMap(axis);
double zoomCenter = scaleMap.invTransform(eventPos);
double newMin = zoomCenter - zoomFactor * (zoomCenter - scaleMap.s1());
double newMax = zoomCenter + zoomFactor * (-zoomCenter + scaleMap.s2());
plot->setAxisScale(axis, newMin, newMax);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuQwtPlotWheelZoomer::eventFilter(QObject * watched, QEvent * event)
{
QWheelEvent* wheelEvent = dynamic_cast<QWheelEvent*>(event);
if ( wheelEvent )
{
double zoomFactor = 1.0/RIU_SCROLLWHEEL_ZOOMFACTOR;
if ( wheelEvent->delta() > 0 )
{
zoomFactor = RIU_SCROLLWHEEL_ZOOMFACTOR;
}
zoomOnAxis(m_plot, QwtPlot::xBottom, zoomFactor, wheelEvent->pos().x());
zoomOnAxis(m_plot, QwtPlot::xTop, zoomFactor, wheelEvent->pos().x());
zoomOnAxis(m_plot, QwtPlot::yLeft, zoomFactor, wheelEvent->pos().y());
zoomOnAxis(m_plot, QwtPlot::yRight, zoomFactor, wheelEvent->pos().y());
m_plot->replot();
emit zoomUpdated();
}
return false;
}

View File

@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QObject>
class QwtPlot;
class QEvent;
class RiuQwtPlotWheelZoomer : public QObject
{
Q_OBJECT
public:
RiuQwtPlotWheelZoomer(QwtPlot* plot);
virtual bool eventFilter(QObject * watched, QEvent * event) override;
signals:
void zoomUpdated();
private:
QwtPlot* m_plot;
};

View File

@ -79,6 +79,6 @@ void RiuResultInfoPanel::convertStringToHTML(QString* str)
//--------------------------------------------------------------------------------------------------
QSize RiuResultInfoPanel::sizeHint () const
{
// As small as possible fow now
// As small as possible for now
return QSize(20, 20);
}

View File

@ -39,6 +39,7 @@
#include <QMenu>
#include <QContextMenuEvent>
#include "RiuSummaryQwtPlot.h"
//--------------------------------------------------------------------------------------------------
@ -47,9 +48,6 @@
RiuResultQwtPlot::RiuResultQwtPlot(QWidget* parent)
: QwtPlot(parent)
{
m_grid = new QwtPlotGrid;
m_grid->attach(this);
setDefaults();
}
@ -59,9 +57,6 @@ RiuResultQwtPlot::RiuResultQwtPlot(QWidget* parent)
RiuResultQwtPlot::~RiuResultQwtPlot()
{
deleteAllCurves();
m_grid->detach();
delete m_grid;
}
//--------------------------------------------------------------------------------------------------
@ -152,59 +147,20 @@ void RiuResultQwtPlot::contextMenuEvent(QContextMenuEvent* event)
//--------------------------------------------------------------------------------------------------
void RiuResultQwtPlot::setDefaults()
{
QPalette newPalette(palette());
newPalette.setColor(QPalette::Background, Qt::white);
setPalette(newPalette);
setAutoFillBackground(true);
setCanvasBackground(Qt::white);
QFrame* canvasFrame = dynamic_cast<QFrame*>(canvas());
if (canvasFrame)
{
canvasFrame->setFrameShape(QFrame::NoFrame);
}
canvas()->setMouseTracking(true);
canvas()->installEventFilter(this);
QPen gridPen(Qt::SolidLine);
gridPen.setColor(Qt::lightGray);
m_grid->setPen(gridPen);
RiuSummaryQwtPlot::setCommonPlotBehaviour(this);
enableAxis(QwtPlot::xBottom, true);
enableAxis(QwtPlot::yLeft, true);
enableAxis(QwtPlot::xTop, false);
enableAxis(QwtPlot::yRight, false);
plotLayout()->setAlignCanvasToScales(true);
RiuSummaryQwtPlot::enableDateBasedBottomXAxis(this);
QwtDateScaleDraw* scaleDraw = new QwtDateScaleDraw(Qt::UTC);
scaleDraw->setDateFormat(QwtDate::Year, QString("dd-MM-yyyy"));
setAxisMaxMinor(QwtPlot::xBottom, 2);
setAxisMaxMinor(QwtPlot::yLeft, 3);
QwtDateScaleEngine* scaleEngine = new QwtDateScaleEngine(Qt::UTC);
setAxisScaleEngine(QwtPlot::xBottom, scaleEngine);
setAxisScaleDraw(QwtPlot::xBottom, scaleDraw);
QFont xAxisFont = axisFont(QwtPlot::xBottom);
xAxisFont.setPixelSize(9);
setAxisFont(QwtPlot::xBottom, xAxisFont);
QFont yAxisFont = axisFont(QwtPlot::yLeft);
yAxisFont.setPixelSize(9);
setAxisFont(QwtPlot::yLeft, yAxisFont);
QwtText axisTitleY = axisTitle(QwtPlot::yLeft);
QFont yAxisTitleFont = axisTitleY.font();
yAxisTitleFont.setPixelSize(9);
yAxisTitleFont.setBold(false);
axisTitleY.setFont(yAxisTitleFont);
axisTitleY.setRenderFlags(Qt::AlignRight);
setAxisTitle(QwtPlot::yLeft, axisTitleY);
QwtLegend* legend = new QwtLegend(this);
// The legend will be deleted in the destructor of the plot or when
// another legend is inserted.
QwtLegend* legend = new QwtLegend(this);
this->insertLegend(legend, BottomLegend);
}

View File

@ -40,8 +40,14 @@ public:
explicit RiuResultQwtPlot(QWidget* parent = NULL);
virtual ~RiuResultQwtPlot();
void addCurve(const QString& curveName, const cvf::Color3f& curveColor, const std::vector<QDateTime>& dateTimes, const std::vector<double>& timeHistoryValues);
void addCurve(const QString& curveName, const cvf::Color3f& curveColor, const std::vector<double>& frameTimes, const std::vector<double>& timeHistoryValues);
void addCurve(const QString& curveName,
const cvf::Color3f& curveColor,
const std::vector<QDateTime>& dateTimes,
const std::vector<double>& timeHistoryValues);
void addCurve(const QString& curveName,
const cvf::Color3f& curveColor,
const std::vector<double>& frameTimes,
const std::vector<double>& timeHistoryValues);
void deleteAllCurves();
@ -55,6 +61,5 @@ private:
private:
std::vector<QwtPlotCurve*> m_plotCurves;
QwtPlotGrid* m_grid;
};

View File

@ -26,75 +26,27 @@
#include "RiuMainPlotWindow.h"
#include "RiuQwtScalePicker.h"
#include "RiuQwtCurvePointTracker.h"
#include "cafSelectionManager.h"
#include "qwt_date_scale_draw.h"
#include "qwt_date_scale_engine.h"
#include "qwt_date_scale_draw.h"
#include "qwt_legend.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_grid.h"
#include "qwt_plot_layout.h"
#include "qwt_plot_marker.h"
#include "qwt_plot_panner.h"
#include "qwt_plot_picker.h"
#include "qwt_plot_zoomer.h"
#include "qwt_scale_engine.h"
#include "qwt_symbol.h"
#include <QEvent>
#include <QMenu>
#include <QWheelEvent>
#include <float.h>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiuQwtPlotPicker : public QwtPlotPicker
{
public:
explicit RiuQwtPlotPicker(QWidget *canvas)
: QwtPlotPicker(canvas)
{
}
protected:
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
virtual QwtText trackerText(const QPoint& pos) const override
{
QwtText txt;
const RiuSummaryQwtPlot* sumPlot = dynamic_cast<const RiuSummaryQwtPlot*>(this->plot());
if (sumPlot)
{
int closestYAxis = QwtPlot::yLeft;
QString timeString;
QString valueString;
QPointF closestPoint = sumPlot->closestCurvePoint(pos, &valueString, &timeString, &closestYAxis);
if (!closestPoint.isNull())
{
QString str = valueString;
if (!timeString.isEmpty())
{
str += QString(" (%1)").arg(timeString);
}
txt.setText(str);
}
RiuSummaryQwtPlot* nonConstPlot = const_cast<RiuSummaryQwtPlot*>(sumPlot);
nonConstPlot->updateClosestCurvePointMarker(closestPoint, closestYAxis);
}
return txt;
}
};
#include "qwt_plot_magnifier.h"
#include "RiuQwtPlotWheelZoomer.h"
//--------------------------------------------------------------------------------------------------
///
@ -104,9 +56,6 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* pa
Q_ASSERT(plotDefinition);
m_plotDefinition = plotDefinition;
m_grid = new QwtPlotGrid;
m_grid->attach(this);
setDefaults();
// LeftButton for the zooming
@ -116,32 +65,25 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* pa
m_zoomerLeft->setTrackerPen(QColor(Qt::black));
m_zoomerLeft->initMousePattern(1);
// MidButton for the panning
QwtPlotPanner* panner = new QwtPlotPanner(canvas());
panner->setMouseButton(Qt::MidButton);
connect(m_zoomerLeft, SIGNAL(zoomed( const QRectF & )), SLOT(onZoomedSlot()));
connect(panner, SIGNAL(panned( int , int )), SLOT(onZoomedSlot()));
// Attach a zoomer for the right axis
m_zoomerRight = new QwtPlotZoomer(canvas());
m_zoomerRight->setAxis(xTop, yRight);
m_zoomerRight->setTrackerMode(QwtPicker::AlwaysOff);
m_zoomerRight->initMousePattern(1);
// MidButton for the panning
QwtPlotPanner* panner = new QwtPlotPanner(canvas());
panner->setMouseButton(Qt::MidButton);
auto wheelZoomer = new RiuQwtPlotWheelZoomer(this);
connect(wheelZoomer, SIGNAL(zoomUpdated()), SLOT(onZoomedSlot()));
connect(m_zoomerLeft, SIGNAL(zoomed( const QRectF & )), SLOT(onZoomedSlot()));
connect(panner, SIGNAL(panned( int , int )), SLOT(onZoomedSlot()));
RiuQwtScalePicker* scalePicker = new RiuQwtScalePicker(this);
connect(scalePicker, SIGNAL(clicked(int, double)), this, SLOT(onAxisClicked(int, double)));
// Create a plot picker to display values next to mouse cursor
m_plotPicker = new RiuQwtPlotPicker(this->canvas());
m_plotPicker->setTrackerMode(QwtPicker::AlwaysOn);
m_plotMarker = new QwtPlotMarker;
// QwtPlotMarker takes ownership of the symbol, it is deleted in destructor of QwtPlotMarker
QwtSymbol* mySymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(Qt::black, 2.0), QSize(12, 12));
m_plotMarker->setSymbol(mySymbol);
}
//--------------------------------------------------------------------------------------------------
@ -149,17 +91,11 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* pa
//--------------------------------------------------------------------------------------------------
RiuSummaryQwtPlot::~RiuSummaryQwtPlot()
{
m_grid->detach();
delete m_grid;
if (m_plotDefinition)
{
m_plotDefinition->detachAllCurves();
m_plotDefinition->handleMdiWindowClosed();
}
m_plotMarker->detach();
delete m_plotMarker;
}
//--------------------------------------------------------------------------------------------------
@ -242,180 +178,104 @@ QSize RiuSummaryQwtPlot::sizeHint() const
return QSize(0, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QPointF RiuSummaryQwtPlot::closestCurvePoint(const QPoint& cursorPosition, QString* valueString, QString* timeString, int* yAxis) const
{
QPointF samplePoint;
QwtPlotCurve* closestCurve = nullptr;
double distMin = DBL_MAX;
int closestPointSampleIndex = -1;
const QwtPlotItemList& itmList = itemList();
for (QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++)
{
if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve)
{
QwtPlotCurve* candidateCurve = static_cast<QwtPlotCurve*>(*it);
double dist = DBL_MAX;
int candidateSampleIndex = candidateCurve->closestPoint(cursorPosition, &dist);
if (dist < distMin)
{
closestCurve = candidateCurve;
distMin = dist;
closestPointSampleIndex = candidateSampleIndex;
}
}
}
if (closestCurve && distMin < 50)
{
samplePoint = closestCurve->sample(closestPointSampleIndex);
if (yAxis) *yAxis = closestCurve->yAxis();
}
if (timeString)
{
const QwtScaleDraw* timeAxisScaleDraw = axisScaleDraw(QwtPlot::xBottom);
auto dateScaleDraw = dynamic_cast<const QwtDateScaleDraw*>(timeAxisScaleDraw) ;
if (dateScaleDraw)
{
QDateTime date = dateScaleDraw->toDateTime(samplePoint.x());
*timeString = date.toString("hh:mm dd.MMMM.yyyy");
}
else if (timeAxisScaleDraw)
{
*timeString = timeAxisScaleDraw->label(samplePoint.x()).text();
}
}
if (valueString && closestCurve)
{
const QwtScaleDraw* yAxisScaleDraw = axisScaleDraw(closestCurve->yAxis());
if (yAxisScaleDraw)
{
*valueString = yAxisScaleDraw->label(samplePoint.y()).text();
}
}
return samplePoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryQwtPlot::updateClosestCurvePointMarker(const QPointF& closestPoint, int yAxis)
{
bool replotRequired = false;
if (!closestPoint.isNull())
{
if (!m_plotMarker->plot())
{
m_plotMarker->attach(this);
replotRequired = true;
}
if (m_plotMarker->value() != closestPoint)
{
m_plotMarker->setValue(closestPoint.x(), closestPoint.y());
// Set y-axis to be able to support more than one y-axis. Default y-axis is left axis.
// TODO : Should use a color or other visual indicator to show what axis the curve relates to
m_plotMarker->setYAxis(yAxis);
replotRequired = true;
}
}
else
{
if (m_plotMarker->plot())
{
m_plotMarker->detach();
replotRequired = true;
}
}
if (replotRequired) this->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryQwtPlot::setDefaults()
{
QPalette newPalette(palette());
newPalette.setColor(QPalette::Background, Qt::white);
setPalette(newPalette);
setAutoFillBackground(true);
setCanvasBackground(Qt::white);
QFrame* canvasFrame = dynamic_cast<QFrame*>(canvas());
if (canvasFrame)
{
canvasFrame->setFrameShape(QFrame::NoFrame);
}
canvas()->setMouseTracking(true);
canvas()->installEventFilter(this);
QPen gridPen(Qt::SolidLine);
gridPen.setColor(Qt::lightGray);
m_grid->setPen(gridPen);
setCommonPlotBehaviour(this);
enableAxis(QwtPlot::xBottom, true);
enableAxis(QwtPlot::yLeft, true);
enableAxis(QwtPlot::xTop, false);
enableAxis(QwtPlot::yRight, false);
plotLayout()->setAlignCanvasToScales(true);
useDateBasedTimeAxis();
QFont xAxisFont = axisFont(QwtPlot::xBottom);
xAxisFont.setPixelSize(11);
setAxisFont(QwtPlot::xBottom, xAxisFont);
setAxisMaxMinor(QwtPlot::xBottom, 2);
QFont yAxisFont = axisFont(QwtPlot::yLeft);
yAxisFont.setPixelSize(11);
setAxisFont(QwtPlot::yLeft, yAxisFont);
setAxisMaxMinor(QwtPlot::yLeft, 3);
QwtText axisTitleY = axisTitle(QwtPlot::yLeft);
QFont yAxisTitleFont = axisTitleY.font();
yAxisTitleFont.setPixelSize(11);
yAxisTitleFont.setBold(false);
axisTitleY.setFont(yAxisTitleFont);
axisTitleY.setRenderFlags(Qt::AlignRight);
setAxisTitle(QwtPlot::yLeft, axisTitleY);
QwtLegend* legend = new QwtLegend(this);
// The legend will be deleted in the destructor of the plot or when
// another legend is inserted.
QwtLegend* legend = new QwtLegend(this);
this->insertLegend(legend, BottomLegend);
}
void RiuSummaryQwtPlot::setCommonPlotBehaviour(QwtPlot* plot)
{
// Plot background and frame look
QPalette newPalette(plot->palette());
newPalette.setColor(QPalette::Background, Qt::white);
plot->setPalette(newPalette);
plot->setAutoFillBackground(true);
plot->setCanvasBackground(Qt::white);
QFrame* canvasFrame = dynamic_cast<QFrame*>(plot->canvas());
if (canvasFrame)
{
canvasFrame->setFrameShape(QFrame::NoFrame);
}
// Grid
QwtPlotGrid* grid = new QwtPlotGrid;
grid->attach(plot);
QPen gridPen(Qt::SolidLine);
gridPen.setColor(Qt::lightGray);
grid->setPen(gridPen);
// Axis number font
QFont axisFont = plot->axisFont(QwtPlot::xBottom);
axisFont.setPixelSize(11);
plot->setAxisFont(QwtPlot::xBottom, axisFont);
plot->setAxisFont(QwtPlot::xTop, axisFont);
plot->setAxisFont(QwtPlot::yLeft, axisFont);
plot->setAxisFont(QwtPlot::yRight, axisFont);
// Axis title font
QwtText axisTitle = plot->axisTitle(QwtPlot::xBottom);
QFont axisTitleFont = axisTitle.font();
axisTitleFont.setPixelSize(11);
axisTitleFont.setBold(false);
axisTitle.setFont(axisTitleFont);
axisTitle.setRenderFlags(Qt::AlignRight);
plot->setAxisTitle(QwtPlot::xBottom, axisTitle);
plot->setAxisTitle(QwtPlot::xTop, axisTitle);
plot->setAxisTitle(QwtPlot::yLeft, axisTitle);
plot->setAxisTitle(QwtPlot::yRight, axisTitle);
// Enable mousetracking and event filter
plot->canvas()->setMouseTracking(true);
plot->canvas()->installEventFilter(plot);
plot->plotLayout()->setAlignCanvasToScales(true);
new RiuQwtCurvePointTracker(plot, true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryQwtPlot::useDateBasedTimeAxis()
{
enableDateBasedBottomXAxis(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryQwtPlot::enableDateBasedBottomXAxis(QwtPlot* plot)
{
QwtDateScaleDraw* scaleDraw = new QwtDateScaleDraw(Qt::UTC);
scaleDraw->setDateFormat(QwtDate::Year, QString("dd-MM-yyyy"));
QwtDateScaleEngine* scaleEngine = new QwtDateScaleEngine(Qt::UTC);
setAxisScaleEngine(QwtPlot::xBottom, scaleEngine);
setAxisScaleDraw(QwtPlot::xBottom, scaleDraw);
plot->setAxisScaleEngine(QwtPlot::xBottom, scaleEngine);
plot->setAxisScaleDraw(QwtPlot::xBottom, scaleDraw);
}
//--------------------------------------------------------------------------------------------------
@ -448,18 +308,6 @@ bool RiuSummaryQwtPlot::eventFilter(QObject* watched, QEvent* event)
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryQwtPlot::leaveEvent(QEvent *)
{
if (m_plotMarker->plot())
{
m_plotMarker->detach();
replot();
}
}
//--------------------------------------------------------------------------------------------------
///
@ -500,11 +348,6 @@ void RiuSummaryQwtPlot::selectClosestCurve(const QPoint& pos)
//--------------------------------------------------------------------------------------------------
void RiuSummaryQwtPlot::onZoomedSlot()
{
QwtInterval left, right, time;
currentVisibleWindow(&left, &right, &time);
this->setZoomWindow(left, right, time);
m_plotDefinition->updateZoomWindowFromQwt();
}

View File

@ -57,31 +57,26 @@ public:
const QwtInterval& rightAxis,
const QwtInterval& timeAxis);
static void setCommonPlotBehaviour(QwtPlot* plot);
static void enableDateBasedBottomXAxis(QwtPlot* plot);
protected:
virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual void leaveEvent(QEvent *) override;
virtual QSize sizeHint() const override;
virtual QSize minimumSizeHint() const override;
virtual void contextMenuEvent(QContextMenuEvent *) override;
private:
friend class RiuQwtPlotPicker;
QPointF closestCurvePoint(const QPoint& pos, QString* valueString, QString* timeString, int* yAxis) const;
void updateClosestCurvePointMarker(const QPointF& pos, int yAxis);
void setDefaults();
void selectClosestCurve(const QPoint& pos);
void showToolTip(const QPoint& pos);
private slots:
void onZoomedSlot( );
void onAxisClicked(int axis, double value);
private:
QwtPlotGrid* m_grid;
QwtPicker* m_plotPicker;
QwtPlotMarker* m_plotMarker;
caf::PdmPointer<RimSummaryPlot> m_plotDefinition;
QPointer<QwtPlotZoomer> m_zoomerLeft;

View File

@ -328,6 +328,8 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event)
commandIds << "Separator";
commandIds << "RicNewGridTimeHistoryCurveFeature";
commandIds << "RicShowFlowCharacteristicsPlotFeature";
RimContextCommandBuilder::appendCommandsToMenu(commandIds, &menu);

View File

@ -26,6 +26,7 @@
#include "RimWellLogCurve.h"
#include "RiuMainPlotWindow.h"
#include "RiuQwtCurvePointTracker.h"
#include "qwt_legend.h"
#include "qwt_plot_curve.h"
@ -44,57 +45,11 @@
#include <QWheelEvent>
#include <float.h>
#include "RiuSummaryQwtPlot.h"
#define RIU_SCROLLWHEEL_ZOOMFACTOR 1.1
#define RIU_SCROLLWHEEL_PANFACTOR 0.1
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RiuWellLogTrackQwtPicker : public QwtPlotPicker
{
public:
explicit RiuWellLogTrackQwtPicker(QWidget *canvas)
: QwtPlotPicker(canvas)
{
}
protected:
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
virtual QwtText trackerText(const QPoint& pos) const override
{
QwtText txt;
const RiuWellLogTrack* wellLogTrack = dynamic_cast<const RiuWellLogTrack*>(this->plot());
if (wellLogTrack)
{
QString depthString;
QString valueString;
QPointF closestPoint = wellLogTrack->closestCurvePoint(pos, &valueString, &depthString);
if (!closestPoint.isNull())
{
QString str = valueString;
if (!depthString.isEmpty())
{
str += QString(" (%1)").arg(depthString);
}
txt.setText(str);
}
RiuWellLogTrack* nonConstPlot = const_cast<RiuWellLogTrack*>(wellLogTrack);
nonConstPlot->updateClosestCurvePointMarker(closestPoint);
}
return txt;
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -104,21 +59,8 @@ RiuWellLogTrack::RiuWellLogTrack(RimWellLogTrack* plotTrackDefinition, QWidget*
Q_ASSERT(plotTrackDefinition);
m_plotTrackDefinition = plotTrackDefinition;
m_grid = new QwtPlotGrid();
m_grid->attach(this);
setFocusPolicy(Qt::ClickFocus);
setDefaults();
// Create a plot picker to display values next to mouse cursor
m_plotPicker = new RiuWellLogTrackQwtPicker(this->canvas());
m_plotPicker->setTrackerMode(QwtPicker::AlwaysOn);
m_plotMarker = new QwtPlotMarker;
// QwtPlotMarker takes ownership of the symbol, it is deleted in destructor of QwtPlotMarker
QwtSymbol* mySymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(Qt::black, 2.0), QSize(12, 12));
m_plotMarker->setSymbol(mySymbol);
}
//--------------------------------------------------------------------------------------------------
@ -126,135 +68,22 @@ RiuWellLogTrack::RiuWellLogTrack(RimWellLogTrack* plotTrackDefinition, QWidget*
//--------------------------------------------------------------------------------------------------
RiuWellLogTrack::~RiuWellLogTrack()
{
m_grid->detach();
delete m_grid;
m_plotMarker->detach();
delete m_plotMarker;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QPointF RiuWellLogTrack::closestCurvePoint(const QPoint& pos, QString* valueString, QString* depthString) const
{
QPointF samplePoint;
QwtPlotCurve* closestCurve = nullptr;
double distMin = DBL_MAX;
int closestPointSampleIndex = -1;
const QwtPlotItemList& itmList = itemList();
for (QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++)
{
if ((*it)->rtti() == QwtPlotItem::Rtti_PlotCurve)
{
QwtPlotCurve* candidateCurve = static_cast<QwtPlotCurve*>(*it);
double dist = DBL_MAX;
int candidateSampleIndex = candidateCurve->closestPoint(pos, &dist);
if (dist < distMin)
{
closestCurve = candidateCurve;
distMin = dist;
closestPointSampleIndex = candidateSampleIndex;
}
}
}
if (closestCurve && distMin < 50)
{
samplePoint = closestCurve->sample(closestPointSampleIndex);
}
if (depthString)
{
const QwtScaleDraw* depthAxisScaleDraw = axisScaleDraw(QwtPlot::yLeft);
if (depthAxisScaleDraw)
{
*depthString = depthAxisScaleDraw->label(samplePoint.y()).text();
}
}
if (valueString && closestCurve)
{
const QwtScaleDraw* xAxisScaleDraw = axisScaleDraw(closestCurve->xAxis());
if (xAxisScaleDraw)
{
*valueString = xAxisScaleDraw->label(samplePoint.x()).text();
}
}
return samplePoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWellLogTrack::updateClosestCurvePointMarker(const QPointF& pos)
{
bool replotRequired = false;
if (!pos.isNull())
{
if (!m_plotMarker->plot())
{
m_plotMarker->attach(this);
replotRequired = true;
}
if (m_plotMarker->value() != pos)
{
m_plotMarker->setValue(pos.x(), pos.y());
replotRequired = true;
}
}
else
{
if (m_plotMarker->plot())
{
m_plotMarker->detach();
replotRequired = true;
}
}
if (replotRequired) this->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWellLogTrack::setDefaults()
{
QPalette newPalette(palette());
newPalette.setColor(QPalette::Background, Qt::white);
setPalette(newPalette);
setAutoFillBackground(true);
setCanvasBackground(Qt::white);
QFrame* canvasFrame = dynamic_cast<QFrame*>(canvas());
if (canvasFrame)
{
canvasFrame->setFrameShape(QFrame::NoFrame);
}
canvas()->setMouseTracking(true);
canvas()->installEventFilter(this);
QPen gridPen(Qt::SolidLine);
gridPen.setColor(Qt::lightGray);
m_grid->setPen(gridPen);
RiuSummaryQwtPlot::setCommonPlotBehaviour(this);
enableAxis(QwtPlot::xTop, true);
enableAxis(QwtPlot::yLeft, true);
enableAxis(QwtPlot::xBottom, false);
enableAxis(QwtPlot::yRight, false);
plotLayout()->setAlignCanvasToScales(true);
axisScaleEngine(QwtPlot::yLeft)->setAttribute(QwtScaleEngine::Inverted, true);
// Align the canvas with the actual min and max values of the curves
@ -263,28 +92,6 @@ void RiuWellLogTrack::setDefaults()
setAxisScale(QwtPlot::yLeft, 1000, 0);
setAxisScale(QwtPlot::xTop, -10, 100);
QFont xAxisFont = axisFont(QwtPlot::xTop);
xAxisFont.setPixelSize(9);
setAxisFont(QwtPlot::xTop, xAxisFont);
QwtText axisTitleX = axisTitle(QwtPlot::yLeft);
QFont xAxisTitleFont = axisTitleX.font();
xAxisTitleFont.setPixelSize(9);
xAxisTitleFont.setBold(false);
axisTitleX.setFont(xAxisTitleFont);
axisTitleX.setRenderFlags(Qt::AlignRight);
setAxisTitle(QwtPlot::xTop, axisTitleX);
QFont yAxisFont = axisFont(QwtPlot::yLeft);
yAxisFont.setPixelSize(9);
setAxisFont(QwtPlot::yLeft, yAxisFont);
QwtText axisTitleY = axisTitle(QwtPlot::yLeft);
QFont yAxisTitleFont = axisTitleY.font();
yAxisTitleFont.setPixelSize(9);
yAxisTitleFont.setBold(false);
axisTitleY.setFont(yAxisTitleFont);
axisTitleY.setRenderFlags(Qt::AlignRight);
setAxisTitle(QwtPlot::yLeft, axisTitleY);
}
//--------------------------------------------------------------------------------------------------
@ -447,18 +254,6 @@ QSize RiuWellLogTrack::minimumSizeHint() const
return QSize(0, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWellLogTrack::leaveEvent(QEvent *)
{
if (m_plotMarker->plot())
{
m_plotMarker->detach();
replot();
}
}
//--------------------------------------------------------------------------------------------------
///

View File

@ -58,20 +58,12 @@ protected:
virtual void focusInEvent(QFocusEvent* event);
virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
virtual void leaveEvent(QEvent *) override;
private:
friend class RiuWellLogTrackQwtPicker;
QPointF closestCurvePoint(const QPoint& pos, QString* valueString, QString* depthString) const;
void updateClosestCurvePointMarker(const QPointF& pos);
void setDefaults();
void selectClosestCurve(const QPoint& pos);
private:
caf::PdmPointer<RimWellLogTrack> m_plotTrackDefinition;
QwtPlotGrid* m_grid;
QwtPicker* m_plotPicker;
QwtPlotMarker* m_plotMarker;
};

View File

@ -104,9 +104,6 @@ if(RESINSIGHT_ENABLE_COTIRE)
set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(cotire)
set(CAF_USE_COTIRE TRUE CACHE INTERNAL "CAF: Use cotire")
endif()

View File

@ -141,7 +141,7 @@ target_link_libraries ( ${PROJECT_NAME}
${QT_LIBRARIES}
)
if (CAF_USE_COTIRE)
if (COMMAND cotire)
cotire(${PROJECT_NAME})
# make sure the unity target is included in the active builds to trigger rebuild before debug

View File

@ -33,14 +33,15 @@
// for more details.
//
//##################################################################################################
#include "QMinimizePanel.h"
#include <QApplication>
#include <QFrame>
#include <QLabel>
#include <QPixmap>
#include <QPushButton>
#include <QResizeEvent>
#include <QLabel>
#include "QApplication"
#include <QPixmap>
//--------------------------------------------------------------------------------------------------
///
@ -128,6 +129,9 @@ QMinimizePanel::QMinimizePanel(const QString &title, QWidget* parent/*=0*/)
this->initialize(title);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void QMinimizePanel::initialize(const QString &title)
{
m_titleFrame = new QFrame(this);
@ -159,7 +163,6 @@ void QMinimizePanel::initialize(const QString &title)
QPalette contentFramePalette = m_contentFrame->palette();
contentFramePalette.setBrush(QPalette::Window, QColor(255,250,250,85));
//contentFramePalette.setBrush(QPalette::Foreground, contentFramePalette.dark());
m_contentFrame->setPalette(contentFramePalette);
connect(m_collapseButton, SIGNAL(clicked()),this, SLOT(toggleExpanded()) );
@ -189,6 +192,29 @@ QString QMinimizePanel::title() const
return m_titleLabel->text();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize QMinimizePanel::sizeHint() const
{
QSize labelSize = m_titleLabel->sizeHint();
QSize titleBarHint = labelSize + QSize(4 + labelSize.height() + 8 - 2 + 1, 8);
if (!m_contentFrame->isHidden())
{
QSize titleBarMin(0, labelSize.height() + 8);
QSize contentsMin(m_contentFrame->sizeHint());
QSize total = contentsMin.expandedTo(titleBarMin);
total.rheight() += titleBarMin.height();
return total;
}
else
{
return titleBarHint;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -225,6 +251,7 @@ QSize QMinimizePanel::minimumSizeHint() const
QSize contentsMin(m_contentFrame->minimumSizeHint());
QSize total = contentsMin.expandedTo(titleBarMin);
total.rheight() += titleBarMin.height();
return total;
}
else
@ -254,7 +281,10 @@ void QMinimizePanel::resizeEvent(QResizeEvent *resizeEv )
m_contentFrame->setGeometry(0, titleHeight-1, width, heigth - (titleHeight-1));
}
bool QMinimizePanel::event(QEvent* event)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool QMinimizePanel::event(QEvent* event)
{
if (event->type() == QEvent::LayoutRequest)
{

View File

@ -42,7 +42,12 @@ class QFrame;
class QLabel;
class QPushButton;
class QMinimizePanel: public QWidget
//==================================================================================================
//
//
//
//==================================================================================================
class QMinimizePanel : public QWidget
{
Q_OBJECT
public:
@ -50,30 +55,31 @@ public:
explicit QMinimizePanel(const QString &title, QWidget* parent=0);
~QMinimizePanel();
QFrame * contentFrame() { return m_contentFrame; }
void setTitle (const QString& title);
QString title() const;
QFrame* contentFrame() { return m_contentFrame; }
void setTitle (const QString& title);
QString title() const;
virtual QSize sizeHint() const override;
public slots:
void setExpanded(bool isExpanded);
void toggleExpanded();
void setExpanded(bool isExpanded);
void toggleExpanded();
signals:
void expandedChanged(bool isExpanded);
void expandedChanged(bool isExpanded);
public:
virtual QSize minimumSizeHint() const override;
virtual QSize minimumSizeHint() const override;
protected:
QFrame* m_titleFrame;
QLabel* m_titleLabel;
QPushButton* m_collapseButton;
QFrame* m_contentFrame;
QFrame* m_titleFrame;
QLabel* m_titleLabel;
QPushButton* m_collapseButton;
QFrame* m_contentFrame;
virtual void resizeEvent(QResizeEvent *) override;
virtual bool event(QEvent* event) override; // To catch QEvent::LayoutRequest
virtual void resizeEvent(QResizeEvent *) override;
virtual bool event(QEvent* event) override; // To catch QEvent::LayoutRequest
private:
void initialize(const QString &title);
void initialize(const QString &title);
};

View File

@ -58,7 +58,6 @@
//==================================================================================================
/// Helper class used to override flags to disable editable items
//==================================================================================================
@ -85,6 +84,45 @@ private:
};
//==================================================================================================
/// Helper class used to control height of size hint
//==================================================================================================
class QListViewHeightHint : public QListView
{
public:
explicit QListViewHeightHint(QWidget *parent = 0)
: m_heightHint(-1)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
virtual QSize sizeHint() const override
{
QSize mySize = QListView::sizeHint();
if (m_heightHint > 0)
{
mySize.setHeight(m_heightHint);
}
return mySize;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void setHeightHint(int heightHint)
{
m_heightHint = heightHint;
}
private:
int m_heightHint;
};
namespace caf
{
@ -98,12 +136,12 @@ CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiListEditor);
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiListEditor::PdmUiListEditor(): m_optionsOnly(true)
PdmUiListEditor::PdmUiListEditor() :
m_isEditOperationsAvailable(true),
m_optionItemCount(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -141,6 +179,14 @@ void PdmUiListEditor::configureAndUpdateUi(const QString& uiConfigName)
m_listView->setEnabled(!field()->isUiReadOnly(uiConfigName));
m_listView->setToolTip(field()->uiToolTip(uiConfigName));
bool optionsOnly = true;
QList<PdmOptionItemInfo> options = field()->valueOptions(&optionsOnly);
m_optionItemCount = options.size();
if (options.size() > 0 || field()->isUiReadOnly(uiConfigName))
{
m_isEditOperationsAvailable = false;
}
PdmUiListEditorAttribute attributes;
caf::PdmUiObjectHandle* uiObject = uiObj(field()->fieldHandle()->ownerObject());
if (uiObject)
@ -151,20 +197,20 @@ void PdmUiListEditor::configureAndUpdateUi(const QString& uiConfigName)
myPalette.setColor(QPalette::Base, attributes.m_baseColor);
m_listView->setPalette(myPalette);
m_listView->setHeightHint(attributes.m_heightHint);
}
MyStringListModel* strListModel = dynamic_cast<MyStringListModel*>(m_model.data());
CAF_ASSERT(strListModel);
m_options = field()->valueOptions(&m_optionsOnly);
if (!m_options.isEmpty())
if (!options.isEmpty())
{
CAF_ASSERT(m_optionsOnly); // Handling Additions on the fly not implemented
CAF_ASSERT(optionsOnly); // Handling Additions on the fly not implemented
strListModel->setItemsEditable(false);
QModelIndex currentItem = m_listView->selectionModel()->currentIndex();
QStringList texts = PdmOptionItemInfo::extractUiTexts(m_options);
QStringList texts = PdmOptionItemInfo::extractUiTexts(options);
strListModel->setStringList(texts);
QVariant fieldValue = field()->uiValue();
@ -230,21 +276,25 @@ void PdmUiListEditor::configureAndUpdateUi(const QString& uiConfigName)
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* PdmUiListEditor::createEditorWidget(QWidget * parent)
{
m_listView = new QListView(parent);
m_listView = new QListViewHeightHint(parent);
m_model = new MyStringListModel(m_listView);
m_listView->setModel(m_model);
connect(m_listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection& )), this, SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection& )));
connect(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(slotListItemEdited(const QModelIndex&, const QModelIndex&)));
// Used to track key press
m_listView->installEventFilter(this);
// Used to track mouse events
m_listView->viewport()->installEventFilter(this);
return m_listView;
}
@ -262,7 +312,7 @@ QWidget* PdmUiListEditor::createLabelWidget(QWidget * parent)
//--------------------------------------------------------------------------------------------------
void PdmUiListEditor::slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
{
if (m_options.isEmpty()) return;
if (m_optionItemCount == 0) return;
QVariant fieldValue = field()->uiValue();
if (fieldValue.type() == QVariant::Int || fieldValue.type() == QVariant::UInt)
@ -279,7 +329,7 @@ void PdmUiListEditor::slotSelectionChanged(const QItemSelection & selected, cons
QModelIndexList idxList = m_listView->selectionModel()->selectedIndexes();
if (idxList.size() >= 1)
{
if (idxList[0].row() < m_options.size())
if (idxList[0].row() < m_optionItemCount)
{
this->setValueToField(QVariant(static_cast<unsigned int>(idxList[0].row())));
}
@ -310,7 +360,7 @@ void PdmUiListEditor::slotSelectionChanged(const QItemSelection & selected, cons
QList<QVariant> valuesToSetInField;
for (int i = 0; i < idxList.size(); ++i)
{
if (idxList[i].row() < m_options.size())
if (idxList[i].row() < m_optionItemCount)
{
valuesToSetInField.push_back(QVariant(static_cast<unsigned int>(idxList[i].row())));
}
@ -319,13 +369,13 @@ void PdmUiListEditor::slotSelectionChanged(const QItemSelection & selected, cons
this->setValueToField(valuesToSetInField);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiListEditor::slotListItemEdited(const QModelIndex&, const QModelIndex&)
{
if (m_optionsOnly) return;
CAF_ASSERT(m_options.isEmpty()); // Not supported yet
CAF_ASSERT(m_isEditOperationsAvailable);
QStringList uiList = m_model->stringList();
@ -370,41 +420,62 @@ void PdmUiListEditor::pasteFromString(const QString& content)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiListEditor::eventFilter(QObject * listView, QEvent * event)
bool PdmUiListEditor::eventFilter(QObject* object, QEvent * event)
{
if (listView == m_listView && event->type() == QEvent::KeyPress)
if (object == m_listView->viewport() && event->type() == QEvent::MouseMove)
{
if (m_optionsOnly) return false;
CAF_ASSERT(m_options.isEmpty()); // Not supported yet
QKeyEvent* keyEv = static_cast<QKeyEvent*>(event);
if (keyEv->key() == Qt::Key_Delete || keyEv->key() == Qt::Key_Backspace )
QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event);
if (mouseEvent)
{
QModelIndexList idxList = m_listView->selectionModel()->selectedIndexes();
bool isAnyDeleted = false;
while(idxList.size())
if (mouseEvent->buttons() & Qt::LeftButton
&& mouseEvent->modifiers() & Qt::ControlModifier)
{
m_model->removeRow(idxList[0].row());
idxList = m_listView->selectionModel()->selectedIndexes();
isAnyDeleted = true;
// When Ctrl button is pressed, left mouse button is pressed, and the mouse is moving,
// a possible bug in Qt is observed causing the selection to end up with single item selection
// When returning here without doing anything, system behaves as expected
// NOTE: The mouse event is handled by the viewport() of the list view, not the list view itself
return true;
}
if (isAnyDeleted)
{
QStringList uiList = m_model->stringList();
// Remove dummy elements specifically at the end of list.
QStringList result;
foreach (const QString &str, uiList)
{
if (str != "" && str != " ") result += str;
}
this->setValueToField(result);
}
return true;
}
else if (keyEv->modifiers() & Qt::ControlModifier)
}
if (object == m_listView && event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEv = static_cast<QKeyEvent*>(event);
if (m_isEditOperationsAvailable)
{
if (keyEv->key() == Qt::Key_Delete || keyEv->key() == Qt::Key_Backspace )
{
QModelIndexList idxList = m_listView->selectionModel()->selectedIndexes();
bool isAnyDeleted = false;
while(idxList.size())
{
m_model->removeRow(idxList[0].row());
idxList = m_listView->selectionModel()->selectedIndexes();
isAnyDeleted = true;
}
if (isAnyDeleted)
{
QStringList uiList = m_model->stringList();
// Remove dummy elements specifically at the end of list.
QStringList result;
foreach (const QString &str, uiList)
{
if (str != "" && str != " ") result += str;
}
this->setValueToField(result);
}
return true;
}
}
if (keyEv->modifiers() & Qt::ControlModifier)
{
if (keyEv->key() == Qt::Key_C)
{
@ -417,7 +488,7 @@ bool PdmUiListEditor::eventFilter(QObject * listView, QEvent * event)
return true;
}
}
else if (keyEv->key() == Qt::Key_V)
else if (m_isEditOperationsAvailable && keyEv->key() == Qt::Key_V)
{
QClipboard* clipboard = QApplication::clipboard();
if (clipboard)

View File

@ -39,10 +39,9 @@
#include "cafPdmUiFieldEditorHandle.h"
class QGridLayout;
class QStringListModel;
class QItemSelection;
class QListView;
class QListViewHeightHint;
class QLabel;
class QModelIndex;
@ -56,7 +55,7 @@ class PdmUiListEditorAttribute : public PdmUiEditorAttribute
{
public:
PdmUiListEditorAttribute()
: m_baseColor(Qt::white)
: m_heightHint(2000)
{
QPalette myPalette;
@ -64,7 +63,8 @@ public:
}
public:
QColor m_baseColor;
QColor m_baseColor;
int m_heightHint;
};
@ -95,15 +95,12 @@ private:
void pasteFromString(const QString& content);
private:
QPointer<QListView> m_listView;
QPointer<QListViewHeightHint> m_listView;
QPointer<QLabel> m_label;
QPointer<QStringListModel> m_model;
QList<PdmOptionItemInfo> m_options;
bool m_optionsOnly;
bool m_isEditOperationsAvailable;
int m_optionItemCount;
};