mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Merge remote-tracking branch 'origin/dev' into hdf-prototype
This commit is contained in:
commit
354e44b617
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -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))
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ private:
|
||||
void updateReadOnlyStateOfAllFields();
|
||||
void updateRangeLabel();
|
||||
bool isPropertyFilterControlled();
|
||||
void setCategoriesFromTracerNames(const std::vector<QString>& tracerNames);
|
||||
|
||||
RimEclipsePropertyFilterCollection* parentContainer();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
265
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp
Normal file
265
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp
Normal 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());
|
||||
}
|
||||
}
|
||||
|
82
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h
Normal file
82
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h
Normal 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;
|
||||
};
|
||||
|
232
ApplicationCode/UserInterface/RiuQwtCurvePointTracker.cpp
Normal file
232
ApplicationCode/UserInterface/RiuQwtCurvePointTracker.cpp
Normal 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();
|
||||
}
|
55
ApplicationCode/UserInterface/RiuQwtCurvePointTracker.h
Normal file
55
ApplicationCode/UserInterface/RiuQwtCurvePointTracker.h
Normal 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;
|
||||
};
|
||||
|
73
ApplicationCode/UserInterface/RiuQwtPlotWheelZoomer.cpp
Normal file
73
ApplicationCode/UserInterface/RiuQwtPlotWheelZoomer.cpp
Normal 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;
|
||||
}
|
||||
|
40
ApplicationCode/UserInterface/RiuQwtPlotWheelZoomer.h
Normal file
40
ApplicationCode/UserInterface/RiuQwtPlotWheelZoomer.h
Normal 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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
RiuSummaryQwtPlot::enableDateBasedBottomXAxis(this);
|
||||
|
||||
QwtLegend* legend = new QwtLegend(this);
|
||||
setAxisMaxMinor(QwtPlot::xBottom, 2);
|
||||
setAxisMaxMinor(QwtPlot::yLeft, 3);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
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;
|
||||
|
@ -328,6 +328,8 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event)
|
||||
|
||||
commandIds << "Separator";
|
||||
commandIds << "RicNewGridTimeHistoryCurveFeature";
|
||||
commandIds << "RicShowFlowCharacteristicsPlotFeature";
|
||||
|
||||
|
||||
RimContextCommandBuilder::appendCommandsToMenu(commandIds, &menu);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -103,22 +58,9 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
void setDepthZoom(double minDepth, double maxDepth);
|
||||
void setDepthTitle(const QString& title);
|
||||
void setXTitle(const QString& title);
|
||||
|
||||
|
||||
void setXRange(double min, double max);
|
||||
|
||||
bool isRimTrackVisible();
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user