Files
ResInsight/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlot.cpp
Gaute Lindkvist a010fc03d7 3d Cross Plot: First implementation (#4127)
* First cross plot commit

* Made cross plot deal with "all time steps" and categorise curves based on time step

* Support STATIC vs DYNAMIC plotting

* #4115 Avoid updating plots in RimEclipseCase::computeCachedData()

* Make sure loading of Cross plot from file works

* Show Legend in Cross Plot

* Uncheck / Check curves to disable/enable

* Axis titles and checkable data set

* Name config and setting of common plot look

* Fix category indentation in GeoMech results

* Support name configuration for Grid Cross Plot

* Support adding new curve sets

* Improve colors and symbols with better cycling

* Moved GridCrossPlot files to sub directory in ProjectDataModel and Commands

* #4111 3D calculations : Always show difference options

* Whitespace

* #4111 Move resultDefinition field to private

* Whitespace

* #4087 Ensemble : When importing and ensemble, show by default an ensemble plot

* #4085 3D view: Improve overlay item colors

* #4106 Crash on Linux

Temporary workaround to avoid crash

* #4106 Stop trying to do recursive setting tab order widget

* The double pointer was handled wrongly and shift-tab order isn't working anyway.

* #4114 Regression Test : Remove cached pointer to eclipse case

* Revert "#4114 Regression Test : Remove cached pointer to eclipse case"

This reverts commit f2146c6007.

* #4114 Regression Test : Missing data for flow diag property filter

* #4085 3D view: Add check box for version info text

* Whtespace

* Improve labelling of static results

* Fix update of result property when changing type
2019-02-21 12:52:23 +01:00

372 lines
12 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimGridCrossPlot.h"
#include "RiuQwtPlotTools.h"
#include "RimGridCrossPlotCurveSet.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cvfAssert.h"
#include "qwt_legend.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include <QDebug>
CAF_PDM_SOURCE_INIT(RimGridCrossPlot, "RimGridCrossPlot");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlot::RimGridCrossPlot()
{
CAF_PDM_InitObject("Grid Cross Plot", ":/SummaryXPlotLight16x16.png", "", "");
CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Show Legend", "", "", "");
CAF_PDM_InitField(&m_legendFontSize, "LegendFontSize", 10, "Legend Font Size", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_nameConfig, "NameConfig", "Name Config", "", "", "");
m_nameConfig.uiCapability()->setUiTreeHidden(true);
m_nameConfig.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_crossPlotCurveSets, "CrossPlotCurve", "Cross Plot Data Set", "", "", "");
m_crossPlotCurveSets.uiCapability()->setUiHidden(true);
m_nameConfig = new RimGridCrossPlotNameConfig(this);
createCurveSet();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotCurveSet* RimGridCrossPlot::createCurveSet()
{
RimGridCrossPlotCurveSet* curveSet = new RimGridCrossPlotCurveSet();
m_crossPlotCurveSets.push_back(curveSet);
return curveSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimGridCrossPlot::indexOfCurveSet(const RimGridCrossPlotCurveSet* curveSet) const
{
for (size_t i = 0; i < m_crossPlotCurveSets.size(); ++i)
{
if (curveSet == m_crossPlotCurveSets[i])
{
return static_cast<int>(i);
}
}
return -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimGridCrossPlot::viewWidget()
{
return m_qwtPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimGridCrossPlot::snapshotWindowContent()
{
QImage image;
if (m_qwtPlot)
{
QPixmap pix = QPixmap::grabWidget(m_qwtPlot);
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::zoomAll()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::calculateZoomRangeAndUpdateQwt()
{
// this->calculateXZoomRange();
m_qwtPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::reattachCurvesToQwtAndReplot()
{
for (auto curveSet : m_crossPlotCurveSets)
{
curveSet->setParentQwtPlotNoReplot(m_qwtPlot);
}
m_qwtPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::createAutoName() const
{
QStringList autoName;
if (!m_nameConfig->customName().isEmpty())
{
autoName += m_nameConfig->customName();
}
if (m_nameConfig->addDataSetNames())
{
QStringList dataSets;
for (auto curveSet : m_crossPlotCurveSets)
{
dataSets += curveSet->createAutoName();
}
if (!dataSets.isEmpty())
{
autoName += QString("(%1)").arg(dataSets.join(", "));
}
}
return autoName.join(" ");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimGridCrossPlot::userDescriptionField()
{
return m_nameConfig->nameField();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimGridCrossPlot::createViewWidget(QWidget* mainWindowParent)
{
if (!m_qwtPlot)
{
m_qwtPlot = new QwtPlot(QString("Grid Cross Plot"), mainWindowParent);
}
return m_qwtPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::deleteViewWidget()
{
if (m_qwtPlot)
{
m_qwtPlot->deleteLater();
m_qwtPlot = nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
CVF_ASSERT(m_qwtPlot);
for (auto curveSet : m_crossPlotCurveSets)
{
curveSet->loadDataAndUpdate(false);
curveSet->setParentQwtPlotNoReplot(m_qwtPlot);
}
performAutoNameUpdate();
m_qwtPlot->setAxisAutoScale(QwtPlot::xBottom);
m_qwtPlot->setAxisAutoScale(QwtPlot::yLeft);
m_qwtPlot->setAxisTitle(QwtPlot::xBottom, QwtText(xAxisParameterString()));
m_qwtPlot->setAxisTitle(QwtPlot::yLeft, QwtText(yAxisParameterString()));
RiuQwtPlotTools::setCommonPlotBehaviour(m_qwtPlot);
RiuQwtPlotTools::setDefaultAxes(m_qwtPlot);
if (m_showLegend())
{
// Will be released in plot destructor or when a new legend is set
QwtLegend* legend = new QwtLegend(m_qwtPlot);
auto font = legend->font();
font.setPixelSize(m_legendFontSize());
legend->setFont(font);
m_qwtPlot->insertLegend(legend, QwtPlot::BottomLegend);
}
else
{
m_qwtPlot->insertLegend(nullptr);
}
m_qwtPlot->replot();
m_qwtPlot->show();
this->updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_showLegend);
if (m_showLegend())
{
uiOrdering.add(&m_legendFontSize);
}
caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup("Name Configuration");
m_nameConfig->uiOrdering(uiConfigName, *nameGroup);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue)
{
onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimGridCrossPlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_legendFontSize)
{
std::vector<int> fontSizes;
fontSizes.push_back(8);
fontSizes.push_back(10);
fontSizes.push_back(12);
fontSizes.push_back(14);
fontSizes.push_back(16);
for (int value : fontSizes)
{
QString text = QString("%1").arg(value);
options.push_back(caf::PdmOptionItemInfo(text, value));
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlot::performAutoNameUpdate()
{
if (m_qwtPlot)
{
m_qwtPlot->setTitle(this->createAutoName());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::xAxisParameterString() const
{
QStringList xAxisParams;
for (auto curveSet : m_crossPlotCurveSets)
{
xAxisParams.push_back(curveSet->xAxisName());
}
xAxisParams.removeDuplicates();
if (xAxisParams.size() > 5)
{
return QString("%1 parameters").arg(xAxisParams.size());
}
return xAxisParams.join(", ");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGridCrossPlot::yAxisParameterString() const
{
QStringList yAxisParams;
for (auto curveSet : m_crossPlotCurveSets)
{
yAxisParams.push_back(curveSet->yAxisName());
}
yAxisParams.removeDuplicates();
if (yAxisParams.size() > 5)
{
return QString("%1 parameters").arg(yAxisParams.size());
}
return yAxisParams.join(", ");
}
//--------------------------------------------------------------------------------------------------
/// Name Configuration
///
//--------------------------------------------------------------------------------------------------
CAF_PDM_SOURCE_INIT(RimGridCrossPlotNameConfig, "RimGridCrossPlotNameConfig");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGridCrossPlotNameConfig::RimGridCrossPlotNameConfig(RimNameConfigHolderInterface* holder /*= nullptr*/)
: RimNameConfig(holder)
{
CAF_PDM_InitObject("Cross Plot Name Generator", "", "", "");
CAF_PDM_InitField(&addDataSetNames, "AddDataSetNames", true, "Add Data Set Names", "", "", "");
setCustomName("Cross Plot");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGridCrossPlotNameConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimNameConfig::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(&addDataSetNames);
}