///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016- 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 "RiuQwtPlot.h" #include "RiaColorTools.h" #include "RimProject.h" #include "RiuPlotMainWindowTools.h" #include "RiuQwtCurvePointTracker.h" #include "RiuQwtPlotTools.h" #include "RiuQwtPlotWheelZoomer.h" #include "RiuQwtPlotZoomer.h" #include "RiuQwtScalePicker.h" #include "qwt_date_scale_draw.h" #include "qwt_date_scale_engine.h" #include "qwt_legend.h" #include "qwt_plot_curve.h" #include "qwt_plot_grid.h" #include "qwt_plot_layout.h" #include "qwt_plot_magnifier.h" #include "qwt_plot_marker.h" #include "qwt_plot_panner.h" #include "qwt_plot_zoomer.h" #include "qwt_scale_engine.h" #include "qwt_symbol.h" #include #include #include #include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuQwtPlot::RiuQwtPlot(RimViewWindow* viewWindow, QWidget* parent) : QwtPlot(parent) { Q_ASSERT(viewWindow); m_ownerViewWindow = viewWindow; // LeftButton for the zooming m_zoomerLeft = new RiuQwtPlotZoomer(canvas()); m_zoomerLeft->setRubberBandPen(QColor(Qt::black)); m_zoomerLeft->setTrackerMode(QwtPicker::AlwaysOff); m_zoomerLeft->setTrackerPen(QColor(Qt::black)); m_zoomerLeft->initMousePattern(1); // Attach a zoomer for the right axis m_zoomerRight = new RiuQwtPlotZoomer(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))); RiuQwtPlotTools::setCommonPlotBehaviour(this); RiuQwtPlotTools::setDefaultAxes(this); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuQwtPlot::~RiuQwtPlot() { if (ownerPlotDefinition()) { ownerPlotDefinition()->detachAllCurves(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimRiuQwtPlotOwnerInterface* RiuQwtPlot::ownerPlotDefinition() const { RimRiuQwtPlotOwnerInterface* plotDefinition = dynamic_cast(ownerViewWindow()); return plotDefinition; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimViewWindow* RiuQwtPlot::ownerViewWindow() const { return m_ownerViewWindow; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QSize RiuQwtPlot::minimumSizeHint() const { return QSize(0, 100); } //-------------------------------------------------------------------------------------------------- /// Empty default implementation //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::selectSample(QwtPlotCurve* curve, int sampleNumber) { } //-------------------------------------------------------------------------------------------------- /// Empty default implementation //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::clearSampleSelection() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::hideEvent(QHideEvent* event) { resetCurveHighlighting(); QwtPlot::hideEvent(event); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QSize RiuQwtPlot::sizeHint() const { return QSize(0, 0); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QwtInterval RiuQwtPlot::currentAxisRange(QwtPlot::Axis axis) { return axisScaleDiv(axis).interval(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiuQwtPlot::eventFilter(QObject* watched, QEvent* event) { if(watched == canvas()) { QMouseEvent* mouseEvent = dynamic_cast(event); if(mouseEvent) { if(mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease) { bool anyZoomingActive = false; if (m_zoomerLeft && m_zoomerLeft->isActiveAndValid()) { anyZoomingActive = true; } if (m_zoomerRight && m_zoomerRight->isActiveAndValid()) { anyZoomingActive = true; } if (!anyZoomingActive) { selectClosestCurve(mouseEvent->pos()); } } } } return QwtPlot::eventFilter(watched, event); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::selectClosestCurve(const QPoint& pos) { QwtPlotCurve* closestCurve = nullptr; double distMin = DBL_MAX; int closestCurvePoint = -1; const QwtPlotItemList& itmList = 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 curvePoint = candidateCurve->closestPoint(pos, &dist); if(dist < distMin) { closestCurve = candidateCurve; distMin = dist; closestCurvePoint = curvePoint; } } } resetCurveHighlighting(); if (closestCurve && distMin < 20) { CVF_ASSERT(closestCurvePoint >= 0); caf::PdmObject* selectedPlotObject = ownerPlotDefinition()->findRimPlotObjectFromQwtCurve(closestCurve); if (selectedPlotObject) { RimProject* proj = nullptr; selectedPlotObject->firstAncestorOrThisOfType(proj); if (proj) { RiuPlotMainWindowTools::showPlotMainWindow(); RiuPlotMainWindowTools::selectAsCurrentItem(selectedPlotObject); highlightCurve(closestCurve); } } } if (closestCurve && distMin < 10) { selectSample(closestCurve, closestCurvePoint); } else { clearSampleSelection(); } replot(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::highlightCurve(const QwtPlotCurve* closestCurve) { // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list // plotCurve->setZ() causes the ordering of items in the list to change auto plotItemList = this->itemList(); for (QwtPlotItem* plotItem : plotItemList) { QwtPlotCurve* plotCurve = dynamic_cast(plotItem); if (plotCurve) { QPen existingPen = plotCurve->pen(); QColor bgColor = this->canvasBackground().color(); QColor curveColor = existingPen.color(); QColor symbolColor; QColor symbolLineColor; QwtSymbol* symbol = const_cast(plotCurve->symbol()); if (symbol) { symbolColor = symbol->brush().color(); symbolLineColor = symbol->pen().color(); } double zValue = plotCurve->z(); if (plotCurve == closestCurve) { plotCurve->setZ(zValue + 100.0); } else { QColor blendedColor = RiaColorTools::blendQColors(bgColor, curveColor, 3, 1); QColor blendedSymbolColor = RiaColorTools::blendQColors(bgColor, symbolColor, 3, 1); QColor blendedSymbolLineColor = RiaColorTools::blendQColors(bgColor, symbolLineColor, 3, 1); plotCurve->setPen(blendedColor, existingPen.width(), existingPen.style()); if (symbol) { symbol->setColor(blendedSymbolColor); symbol->setPen(blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style()); } } CurveColors curveColors = {curveColor, symbolColor, symbolLineColor}; m_originalCurveColors.insert(std::make_pair(plotCurve, curveColors)); m_originalZValues.insert(std::make_pair(plotCurve, zValue)); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::resetCurveHighlighting() { // NB! Create a copy of the item list before the loop to avoid invalidated iterators when iterating the list // plotCurve->setZ() causes the ordering of items in the list to change auto plotItemList = this->itemList(); for (QwtPlotItem* plotItem : plotItemList) { QwtPlotCurve* plotCurve = dynamic_cast(plotItem); if (plotCurve && m_originalCurveColors.count(plotCurve)) { const QPen& existingPen = plotCurve->pen(); auto colors = m_originalCurveColors[plotCurve]; double zValue = m_originalZValues[plotCurve]; plotCurve->setPen(colors.lineColor, existingPen.width(), existingPen.style()); plotCurve->setZ(zValue); QwtSymbol* symbol = const_cast(plotCurve->symbol()); if (symbol) { symbol->setColor(colors.symbolColor); symbol->setPen(colors.symbolLineColor, symbol->pen().width(), symbol->pen().style()); } } } m_originalCurveColors.clear(); m_originalZValues.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::onZoomedSlot() { ownerPlotDefinition()->updateZoomWindowFromQwt(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuQwtPlot::onAxisClicked(int axis, double value) { ownerPlotDefinition()->selectAxisInPropertyEditor(axis); }