From 141257c83e37f5db9d78f2dd9a719931ca03144f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 16 Mar 2017 08:23:27 +0100 Subject: [PATCH] #1293 Added "Show Plot Data" to context menu of plots --- .../RicShowPlotDataFeature.cpp | 7 +- .../RimContextCommandBuilder.cpp | 14 +- .../UserInterface/RiuSummaryQwtPlot.cpp | 1009 +++++++++-------- .../UserInterface/RiuSummaryQwtPlot.h | 180 +-- .../UserInterface/RiuWellLogPlot.cpp | 28 +- .../UserInterface/RiuWellLogPlot.h | 1 + 6 files changed, 638 insertions(+), 601 deletions(-) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp index 6af86ae9c2..5ed31001e8 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp @@ -42,14 +42,11 @@ bool RicShowPlotDataFeature::isCommandEnabled() { std::vector selectedSummaryPlots; caf::SelectionManager::instance()->objectsByType(&selectedSummaryPlots); + if (selectedSummaryPlots.size() > 0) return true; std::vector wellLogPlots; caf::SelectionManager::instance()->objectsByType(&wellLogPlots); - - if (selectedSummaryPlots.size() > 0 || wellLogPlots.size() > 0) - { - return true; - } + if (wellLogPlots.size() > 0) return true; return false; } diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index cdc6d8a4b9..1d80dadfae 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -402,15 +402,10 @@ QStringList RimContextCommandBuilder::commandsFromSelection() dynamic_cast(uiItem) ) { commandIds << "RicSummaryCurveSwitchAxisFeature"; - } else if (dynamic_cast(uiItem)) { - // Do not add twice to make sure the first position in the menu is used for the action - if (!commandIds.contains("RicAsciiExportSummaryPlotFeature")) - { - commandIds << "RicAsciiExportSummaryPlotFeature"; - } + commandIds << "RicAsciiExportSummaryPlotFeature"; } else if (dynamic_cast(uiItem)) { @@ -501,6 +496,13 @@ void RimContextCommandBuilder::appendCommandsToMenu(const QStringList& commandId QAction* act = commandManager->action(commandIds[i]); CVF_ASSERT(act); + for (QAction* existingAct : menu->actions()) + { + // If action exist, continue to make sure the action is positioned at the first + // location of a command ID + if (existingAct == act) continue; + } + menu->addAction(act); } } diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp index 4929194889..e902ce697c 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.cpp @@ -1,499 +1,510 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// 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 "RiuSummaryQwtPlot.h" - -#include "RiaApplication.h" - -#include "RimSummaryCurve.h" -#include "RimSummaryPlot.h" - -#include "RiuMainPlotWindow.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_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 - -#include - - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -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(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(sumPlot); - nonConstPlot->updateClosestCurvePointMarker(closestPoint, closestYAxis); - } - - return txt; - } -}; - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* parent) : QwtPlot(parent) -{ - Q_ASSERT(plotDefinition); - m_plotDefinition = plotDefinition; - - m_grid = new QwtPlotGrid; - m_grid->attach(this); - - setDefaults(); - - // LeftButton for the zooming - m_zoomerLeft = new QwtPlotZoomer(canvas()); - m_zoomerLeft->setRubberBandPen(QColor(Qt::black)); - m_zoomerLeft->setTrackerMode(QwtPicker::AlwaysOff); - 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); - - - 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); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RiuSummaryQwtPlot::~RiuSummaryQwtPlot() -{ - m_grid->detach(); - delete m_grid; - - if (m_plotDefinition) - { - m_plotDefinition->detachAllCurves(); - m_plotDefinition->handleMdiWindowClosed(); - } - - m_plotMarker->detach(); - delete m_plotMarker; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimSummaryPlot* RiuSummaryQwtPlot::ownerPlotDefinition() -{ - return m_plotDefinition; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::currentVisibleWindow(QwtInterval* leftAxis, QwtInterval* rightAxis, QwtInterval* timeAxis) const -{ - *leftAxis = axisScaleDiv(yLeft).interval(); - *rightAxis = axisScaleDiv(yRight).interval(); - *timeAxis = axisScaleDiv(xBottom).interval(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::setZoomWindow(const QwtInterval& leftAxis, const QwtInterval& rightAxis, const QwtInterval& timeAxis) -{ - { - QRectF zoomWindow; - zoomWindow.setLeft(timeAxis.minValue()); - zoomWindow.setRight(timeAxis.maxValue()); - zoomWindow.setTop(leftAxis.maxValue()); - zoomWindow.setBottom(leftAxis.minValue()); - - m_zoomerLeft->zoom(zoomWindow); - } - - { - QRectF zoomWindow; - zoomWindow.setLeft(timeAxis.minValue()); - zoomWindow.setRight(timeAxis.maxValue()); - zoomWindow.setTop(rightAxis.maxValue()); - zoomWindow.setBottom(rightAxis.minValue()); - - m_zoomerRight->zoom(zoomWindow); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QSize RiuSummaryQwtPlot::minimumSizeHint() const -{ - return QSize(0, 100); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -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(*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(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(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); - - 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. - this->insertLegend(legend, BottomLegend); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::useDateBasedTimeAxis() -{ - 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); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::useTimeBasedTimeAxis() -{ - setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine()); - setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw()); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiuSummaryQwtPlot::eventFilter(QObject* watched, QEvent* event) -{ - if(watched == canvas()) - { - QMouseEvent* mouseEvent = dynamic_cast(event); - if(mouseEvent) - { - if(mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease) - { - selectClosestCurve(mouseEvent->pos()); - } - } - } - - return QwtPlot::eventFilter(watched, event); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::leaveEvent(QEvent *) -{ - if (m_plotMarker->plot()) - { - m_plotMarker->detach(); - - replot(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::selectClosestCurve(const QPoint& pos) -{ - QwtPlotCurve* closestCurve = NULL; - double distMin = DBL_MAX; - - 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; - candidateCurve->closestPoint(pos, &dist); - if(dist < distMin) - { - closestCurve = candidateCurve; - distMin = dist; - } - } - } - - if(closestCurve && distMin < 20) - { - RimSummaryCurve* selectedCurve = m_plotDefinition->findRimCurveFromQwtCurve(closestCurve); - if(selectedCurve) - { - RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(selectedCurve); - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::onZoomedSlot() -{ - QwtInterval left, right, time; - currentVisibleWindow(&left, &right, &time); - - this->setZoomWindow(left, right, time); - - m_plotDefinition->updateZoomFromQwt(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuSummaryQwtPlot::onAxisClicked(int axis, double value) -{ - if (!m_plotDefinition) return; - - m_plotDefinition->selectAxisInPropertyEditor(axis); -} +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RiuSummaryQwtPlot.h" + +#include "RiaApplication.h" + +#include "RimContextCommandBuilder.h" +#include "RimSummaryCurve.h" +#include "RimSummaryPlot.h" + +#include "RiuMainPlotWindow.h" +#include "RiuQwtScalePicker.h" + +#include "cafSelectionManager.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_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 +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +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(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(sumPlot); + nonConstPlot->updateClosestCurvePointMarker(closestPoint, closestYAxis); + } + + return txt; + } +}; + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuSummaryQwtPlot::RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* parent) : QwtPlot(parent) +{ + Q_ASSERT(plotDefinition); + m_plotDefinition = plotDefinition; + + m_grid = new QwtPlotGrid; + m_grid->attach(this); + + setDefaults(); + + // LeftButton for the zooming + m_zoomerLeft = new QwtPlotZoomer(canvas()); + m_zoomerLeft->setRubberBandPen(QColor(Qt::black)); + m_zoomerLeft->setTrackerMode(QwtPicker::AlwaysOff); + 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); + + + 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); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuSummaryQwtPlot::~RiuSummaryQwtPlot() +{ + m_grid->detach(); + delete m_grid; + + if (m_plotDefinition) + { + m_plotDefinition->detachAllCurves(); + m_plotDefinition->handleMdiWindowClosed(); + } + + m_plotMarker->detach(); + delete m_plotMarker; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimSummaryPlot* RiuSummaryQwtPlot::ownerPlotDefinition() +{ + return m_plotDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::currentVisibleWindow(QwtInterval* leftAxis, QwtInterval* rightAxis, QwtInterval* timeAxis) const +{ + *leftAxis = axisScaleDiv(yLeft).interval(); + *rightAxis = axisScaleDiv(yRight).interval(); + *timeAxis = axisScaleDiv(xBottom).interval(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::setZoomWindow(const QwtInterval& leftAxis, const QwtInterval& rightAxis, const QwtInterval& timeAxis) +{ + { + QRectF zoomWindow; + zoomWindow.setLeft(timeAxis.minValue()); + zoomWindow.setRight(timeAxis.maxValue()); + zoomWindow.setTop(leftAxis.maxValue()); + zoomWindow.setBottom(leftAxis.minValue()); + + m_zoomerLeft->zoom(zoomWindow); + } + + { + QRectF zoomWindow; + zoomWindow.setLeft(timeAxis.minValue()); + zoomWindow.setRight(timeAxis.maxValue()); + zoomWindow.setTop(rightAxis.maxValue()); + zoomWindow.setBottom(rightAxis.minValue()); + + m_zoomerRight->zoom(zoomWindow); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize RiuSummaryQwtPlot::minimumSizeHint() const +{ + return QSize(0, 100); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::contextMenuEvent(QContextMenuEvent* event) +{ + QMenu menu; QStringList commandIds; + caf::SelectionManager::instance()->setSelectedItem(ownerPlotDefinition()); + commandIds << "RicShowPlotDataFeature"; + RimContextCommandBuilder::appendCommandsToMenu(commandIds, &menu); + if (menu.actions().size() > 0) { menu.exec(event->globalPos()); } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +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(*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(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(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); + + 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. + this->insertLegend(legend, BottomLegend); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::useDateBasedTimeAxis() +{ + 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); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::useTimeBasedTimeAxis() +{ + setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine()); + setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuSummaryQwtPlot::eventFilter(QObject* watched, QEvent* event) +{ + if(watched == canvas()) + { + QMouseEvent* mouseEvent = dynamic_cast(event); + if(mouseEvent) + { + if(mouseEvent->button() == Qt::LeftButton && mouseEvent->type() == QMouseEvent::MouseButtonRelease) + { + selectClosestCurve(mouseEvent->pos()); + } + } + } + + return QwtPlot::eventFilter(watched, event); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::leaveEvent(QEvent *) +{ + if (m_plotMarker->plot()) + { + m_plotMarker->detach(); + + replot(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::selectClosestCurve(const QPoint& pos) +{ + QwtPlotCurve* closestCurve = NULL; + double distMin = DBL_MAX; + + 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; + candidateCurve->closestPoint(pos, &dist); + if(dist < distMin) + { + closestCurve = candidateCurve; + distMin = dist; + } + } + } + + if(closestCurve && distMin < 20) + { + RimSummaryCurve* selectedCurve = m_plotDefinition->findRimCurveFromQwtCurve(closestCurve); + if(selectedCurve) + { + RiaApplication::instance()->getOrCreateAndShowMainPlotWindow()->selectAsCurrentItem(selectedCurve); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::onZoomedSlot() +{ + QwtInterval left, right, time; + currentVisibleWindow(&left, &right, &time); + + this->setZoomWindow(left, right, time); + + m_plotDefinition->updateZoomFromQwt(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuSummaryQwtPlot::onAxisClicked(int axis, double value) +{ + if (!m_plotDefinition) return; + + m_plotDefinition->selectAxisInPropertyEditor(axis); +} diff --git a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h index 7c48f489cb..d6a9058195 100644 --- a/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h +++ b/ApplicationCode/UserInterface/RiuSummaryQwtPlot.h @@ -1,90 +1,90 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// 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. -// -///////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "qwt_plot.h" -#include "cafPdmPointer.h" - -#include - -class QwtPlotCurve; -class QwtPlotGrid; -class QwtPlotZoomer; -class QwtInterval; -class QwtPicker; -class QwtPlotMarker; - -class RimSummaryPlot; - -//================================================================================================== -// -// -// -//================================================================================================== -class RiuSummaryQwtPlot : public QwtPlot -{ - Q_OBJECT; -public: - RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* parent = NULL); - virtual ~RiuSummaryQwtPlot(); - - RimSummaryPlot* ownerPlotDefinition(); - - void useDateBasedTimeAxis(); - void useTimeBasedTimeAxis(); - - void currentVisibleWindow(QwtInterval* leftAxis, - QwtInterval* rightAxis, - QwtInterval* timeAxis) const; - - void setZoomWindow(const QwtInterval& leftAxis, - const QwtInterval& rightAxis, - const QwtInterval& timeAxis); - -protected: - virtual bool eventFilter(QObject* watched, QEvent* event) override; - virtual void leaveEvent(QEvent *) override; - - virtual QSize sizeHint() const override; - virtual QSize minimumSizeHint() const 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 m_plotDefinition; - - QPointer m_zoomerLeft; - QPointer m_zoomerRight; -}; - +///////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "qwt_plot.h" +#include "cafPdmPointer.h" + +#include + +class QwtPlotCurve; +class QwtPlotGrid; +class QwtPlotZoomer; +class QwtInterval; +class QwtPicker; +class QwtPlotMarker; + +class RimSummaryPlot; + +//================================================================================================== +// +// +// +//================================================================================================== +class RiuSummaryQwtPlot : public QwtPlot +{ + Q_OBJECT; +public: + RiuSummaryQwtPlot(RimSummaryPlot* plotDefinition, QWidget* parent = NULL); + virtual ~RiuSummaryQwtPlot(); + + RimSummaryPlot* ownerPlotDefinition(); + + void useDateBasedTimeAxis(); + void useTimeBasedTimeAxis(); + + void currentVisibleWindow(QwtInterval* leftAxis, + QwtInterval* rightAxis, + QwtInterval* timeAxis) const; + + void setZoomWindow(const QwtInterval& leftAxis, + const QwtInterval& rightAxis, + const QwtInterval& timeAxis); + +protected: + virtual bool eventFilter(QObject* watched, QEvent* event) override; + virtual void leaveEvent(QEvent *) override; + + virtual QSize sizeHint() const override; + virtual QSize minimumSizeHint() const override; + virtual void contextMenuEvent(QContextMenuEvent *) override; +private: + friend class RiuQwtPlotPicker; + QPointF closestCurvePoint(const QPoint& pos, QString* valueString, QString* timeString, int* yAxis) const; + void updateClosestCurvePointMarker(const QPointF& pos, int yAxis); + + void setDefaults(); + void selectClosestCurve(const QPoint& pos); + void showToolTip(const QPoint& pos); + +private slots: + void onZoomedSlot( ); + void onAxisClicked(int axis, double value); + +private: + QwtPlotGrid* m_grid; + QwtPicker* m_plotPicker; + QwtPlotMarker* m_plotMarker; + + caf::PdmPointer m_plotDefinition; + + QPointer m_zoomerLeft; + QPointer m_zoomerRight; +}; + diff --git a/ApplicationCode/UserInterface/RiuWellLogPlot.cpp b/ApplicationCode/UserInterface/RiuWellLogPlot.cpp index 412dd33b43..2672d1862b 100644 --- a/ApplicationCode/UserInterface/RiuWellLogPlot.cpp +++ b/ApplicationCode/UserInterface/RiuWellLogPlot.cpp @@ -19,20 +19,25 @@ #include "RiuWellLogPlot.h" +#include "RimContextCommandBuilder.h" #include "RimWellLogPlot.h" #include "RimWellLogTrack.h" + #include "RiuMainWindow.h" #include "RiuWellLogTrack.h" -#include "qwt_legend.h" +#include "cafSelectionManager.h" #include "cvfAssert.h" +#include "qwt_legend.h" + #include #include #include #include #include +#include #include @@ -203,6 +208,27 @@ QSize RiuWellLogPlot::sizeHint() const return QSize(1,1); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuWellLogPlot::contextMenuEvent(QContextMenuEvent* event) +{ + QMenu menu; + QStringList commandIds; + + caf::SelectionManager::instance()->setSelectedItem(ownerPlotDefinition()); + + commandIds << "RicShowPlotDataFeature"; + commandIds << "RicShowContributingWellsFromPlotFeature"; + + RimContextCommandBuilder::appendCommandsToMenu(commandIds, &menu); + + if (menu.actions().size() > 0) + { + menu.exec(event->globalPos()); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuWellLogPlot.h b/ApplicationCode/UserInterface/RiuWellLogPlot.h index 7162209057..b7d6a747a0 100644 --- a/ApplicationCode/UserInterface/RiuWellLogPlot.h +++ b/ApplicationCode/UserInterface/RiuWellLogPlot.h @@ -62,6 +62,7 @@ protected: virtual void showEvent(QShowEvent *); virtual void changeEvent(QEvent *); virtual QSize sizeHint() const override; + virtual void contextMenuEvent(QContextMenuEvent *) override; private: void updateScrollBar(double minDepth, double maxDepth);