From ba1dfee4e6f2265a9452fbae77b96d7f32e99d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 27 Mar 2017 10:38:26 +0200 Subject: [PATCH] #1321 Finalized plot marker refactoring --- .../UserInterface/CMakeLists_files.cmake | 2 + .../UserInterface/RiuQwtCurvePointTracker.cpp | 213 ++++++++++++++++++ .../UserInterface/RiuQwtCurvePointTracker.h | 47 ++++ .../UserInterface/RiuSummaryQwtPlot.cpp | 205 +---------------- .../UserInterface/RiuSummaryQwtPlot.h | 7 +- 5 files changed, 269 insertions(+), 205 deletions(-) create mode 100644 ApplicationCode/UserInterface/RiuQwtCurvePointTracker.cpp create mode 100644 ApplicationCode/UserInterface/RiuQwtCurvePointTracker.h diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index 501cb99546..7f5299f69f 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -20,6 +20,7 @@ ${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}RiuRecentFileActionProvider.h ${CEE_CURRENT_LIST_DIR}RiuResultInfoPanel.h ${CEE_CURRENT_LIST_DIR}RiuResultQwtPlot.h @@ -60,6 +61,7 @@ ${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}RiuRecentFileActionProvider.cpp ${CEE_CURRENT_LIST_DIR}RiuResultInfoPanel.cpp ${CEE_CURRENT_LIST_DIR}RiuResultQwtPlot.cpp diff --git a/ApplicationCode/UserInterface/RiuQwtCurvePointTracker.cpp b/ApplicationCode/UserInterface/RiuQwtCurvePointTracker.cpp new file mode 100644 index 0000000000..7786f4599e --- /dev/null +++ b/ApplicationCode/UserInterface/RiuQwtCurvePointTracker.cpp @@ -0,0 +1,213 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiuQwtCurvePointTracker.h" + +#include "qwt_plot_marker.h" +#include "qwt_symbol.h" + +#include "qwt_plot_curve.h" +#include "qwt_date_scale_draw.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +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(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +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(*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(closestCurve->xAxis()); + if ( relatedYAxis ) *relatedYAxis = static_cast(closestCurve->yAxis()); + } + + + if ( mainAxisValueString ) + { + const QwtScaleDraw* mainAxisScaleDraw = m_isMainAxisHorizontal ? m_plot->axisScaleDraw(*relatedXAxis): m_plot->axisScaleDraw(*relatedYAxis); + auto dateScaleDraw = dynamic_cast(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(); +} diff --git a/ApplicationCode/UserInterface/RiuQwtCurvePointTracker.h b/ApplicationCode/UserInterface/RiuQwtCurvePointTracker.h new file mode 100644 index 0000000000..f53e3f353c --- /dev/null +++ b/ApplicationCode/UserInterface/RiuQwtCurvePointTracker.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "qwt_plot_picker.h" +#include "qwt_plot.h" + +#include + +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(); + + void removeMarkerOnFocusLeave(); + +protected: + 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 m_plot; + QwtPlotMarker* m_plotMarker; + bool m_isMainAxisHorizontal; +}; + diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp index 6d5529ea8d..56533c9da6 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp @@ -26,21 +26,19 @@ #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 #include @@ -48,199 +46,6 @@ #include - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -class RiuQwtPlotPicker : public QwtPlotPicker -{ -public: - explicit RiuQwtPlotPicker(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); - } - - ~RiuQwtPlotPicker() - { - m_plotMarker->detach(); - delete m_plotMarker; - } - - void removeMarker() - { - if (m_plotMarker->plot()) - { - m_plotMarker->detach(); - - m_plot->replot(); - } - } - -protected: - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - virtual QwtText trackerText(const QPoint& pos) const override - { - 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 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(*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( closestCurve->xAxis()); - if (relatedYAxis) *relatedYAxis = static_cast( closestCurve->yAxis()); - } - - - if (mainAxisValueString) - { - const QwtScaleDraw* mainAxisScaleDraw = m_isMainAxisHorizontal ? m_plot->axisScaleDraw(*relatedXAxis): m_plot->axisScaleDraw(*relatedYAxis); - auto dateScaleDraw = dynamic_cast(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.x(); - else - valueAxisSampleVal = samplePoint.y(); - - if (valueAxisScaleDraw) - { - *valueAxisValueString = valueAxisScaleDraw->label(valueAxisSampleVal).text(); - } - } - - return samplePoint; - } - - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - void 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(); - } - - QPointer m_plot; - QwtPlotMarker* m_plotMarker; - bool m_isMainAxisHorizontal; -}; - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -279,7 +84,7 @@ RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* pa 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, true); + m_curvePointTracker = new RiuQwtCurvePointTracker(this, true); } @@ -486,7 +291,7 @@ bool RiuSummaryQwtPlot::eventFilter(QObject* watched, QEvent* event) //-------------------------------------------------------------------------------------------------- void RiuSummaryQwtPlot::leaveEvent(QEvent *) { - m_plotPicker->removeMarker(); + m_curvePointTracker->removeMarkerOnFocusLeave(); } //-------------------------------------------------------------------------------------------------- @@ -530,7 +335,7 @@ void RiuSummaryQwtPlot::onZoomedSlot() { QwtInterval left, right, time; currentVisibleWindow(&left, &right, &time); - + this->setZoomWindow(left, right, time); m_plotDefinition->updateZoomWindowFromQwt(); diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h index 4882a04181..0447ef0a85 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h @@ -30,7 +30,7 @@ class QwtInterval; class QwtPicker; class QwtPlotMarker; -class RiuQwtPlotPicker; +class RiuQwtCurvePointTracker; class RimSummaryPlot; //================================================================================================== @@ -67,9 +67,6 @@ protected: 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); @@ -80,7 +77,7 @@ private slots: private: QwtPlotGrid* m_grid; - RiuQwtPlotPicker* m_plotPicker; + RiuQwtCurvePointTracker* m_curvePointTracker; caf::PdmPointer m_plotDefinition;