Multi page plot works

This commit is contained in:
Gaute Lindkvist
2019-12-19 11:37:40 +01:00
parent 27788b1abd
commit 9ffbd97f8c
26 changed files with 1465 additions and 598 deletions

View File

@@ -116,6 +116,7 @@
#include "cvfqtUtils.h"
#include <QDebug>
#include <QDesktopWidget>
#include <QDir>
#include <QErrorMessage>
#include <QFileDialog>
@@ -1718,6 +1719,18 @@ void RiaGuiApplication::applyGuiPreferences( const RiaPreferences* oldPreference
{
m_mainWindow->applyFontSizesToDockedPlots();
}
if ( oldPreferences->defaultPageLayout() != m_preferences->defaultPageLayout() )
{
for ( RimViewWindow* viewWindow : allViewWindows )
{
RimPlotWindow* plotWindow = dynamic_cast<RimPlotWindow*>( viewWindow );
if ( plotWindow )
{
plotWindow->updateLayout();
}
}
}
}
std::vector<caf::PdmUiItem*> uiEditorsToUpdate;
@@ -1752,6 +1765,14 @@ void RiaGuiApplication::updateGrpcServer()
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiaGuiApplication::applicationResolution()
{
return RiaGuiApplication::instance()->desktop()->logicalDpiX();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -125,6 +125,7 @@ public:
static void clearAllSelections();
void applyGuiPreferences( const RiaPreferences* oldPreferences = nullptr );
void updateGrpcServer();
static int applicationResolution();
// Public RiaApplication overrides
void initialize() override;

View File

@@ -17,6 +17,7 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RiaPlotWindowRedrawScheduler.h"
#include "RiuMultiPlotPage.h"
#include "RiuMultiPlotWindow.h"
#include "RiuQwtPlotWidget.h"
@@ -40,13 +41,23 @@ RiaPlotWindowRedrawScheduler* RiaPlotWindowRedrawScheduler::instance()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaPlotWindowRedrawScheduler::schedulePlotWindowUpdate( RiuMultiPlotWindow* plotWindow )
void RiaPlotWindowRedrawScheduler::scheduleMultiPlotWindowUpdate( RiuMultiPlotWindow* plotWindow )
{
m_plotWindowsToUpdate.push_back( plotWindow );
startTimer( 0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaPlotWindowRedrawScheduler::scheduleMultiPlotPageUpdate( RiuMultiPlotPage* plotPage )
{
m_plotPagesToUpdate.push_back( plotPage );
startTimer( 0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -70,6 +81,7 @@ void RiaPlotWindowRedrawScheduler::clearAllScheduledUpdates()
}
}
m_plotWidgetsToReplot.clear();
m_plotPagesToUpdate.clear();
m_plotWindowsToUpdate.clear();
}
@@ -80,6 +92,7 @@ void RiaPlotWindowRedrawScheduler::performScheduledUpdatesAndReplots()
{
std::set<RiuQwtPlotWidget*> updatedPlots;
std::set<RiuMultiPlotWindow*> updatedPlotWindows;
std::set<RiuMultiPlotPage*> updatedPlotPages;
for ( RiuMultiPlotWindow* plotWindow : m_plotWindowsToUpdate )
{
@@ -87,6 +100,19 @@ void RiaPlotWindowRedrawScheduler::performScheduledUpdatesAndReplots()
{
plotWindow->performUpdate();
updatedPlotWindows.insert( plotWindow );
for ( RiuMultiPlotPage* page : plotWindow->pages() )
{
updatedPlotPages.insert( page );
}
}
}
for ( RiuMultiPlotPage* plotPage : m_plotPagesToUpdate )
{
if ( plotPage && !updatedPlotPages.count( plotPage ) )
{
plotPage->performUpdate();
updatedPlotPages.insert( plotPage );
}
}
@@ -101,6 +127,7 @@ void RiaPlotWindowRedrawScheduler::performScheduledUpdatesAndReplots()
}
m_plotWidgetsToReplot.clear();
m_plotPagesToUpdate.clear();
m_plotWindowsToUpdate.clear();
}

View File

@@ -26,6 +26,7 @@
#include <vector>
class RiuMultiPlotPage;
class RiuMultiPlotWindow;
class RiuQwtPlotWidget;
@@ -35,7 +36,8 @@ class RiaPlotWindowRedrawScheduler : public QObject
public:
static RiaPlotWindowRedrawScheduler* instance();
void schedulePlotWindowUpdate( RiuMultiPlotWindow* plotWindow );
void scheduleMultiPlotWindowUpdate( RiuMultiPlotWindow* plotWindow );
void scheduleMultiPlotPageUpdate( RiuMultiPlotPage* plotWindow );
void schedulePlotWidgetReplot( RiuQwtPlotWidget* plotWidget );
void clearAllScheduledUpdates();
void performScheduledUpdatesAndReplots();
@@ -52,5 +54,6 @@ private:
private:
std::vector<QPointer<RiuQwtPlotWidget>> m_plotWidgetsToReplot;
std::vector<QPointer<RiuMultiPlotWindow>> m_plotWindowsToUpdate;
std::vector<QPointer<RiuMultiPlotPage>> m_plotPagesToUpdate;
QScopedPointer<QTimer> m_plotWindowUpdateTimer;
};

View File

@@ -944,10 +944,15 @@ void RiaPreferences::writePreferencesToApplicationStore()
QPageLayout RiaPreferences::defaultPageLayout() const
{
QPageSize pageSize( m_pageSize() );
QPageLayout layout( pageSize,
m_pageOrientation(),
QMarginsF( m_pageLeftMargin, m_pageTopMargin, m_pageRightMargin, m_pageBottomMargin ),
(QPageLayout::Unit)pageSize.definitionUnits() );
QPageLayout layout( pageSize, m_pageOrientation(), margins(), (QPageLayout::Unit)pageSize.definitionUnits() );
layout.setMode( QPageLayout::StandardMode );
return layout;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QMarginsF RiaPreferences::margins() const
{
return QMarginsF( m_pageLeftMargin, m_pageTopMargin, m_pageRightMargin, m_pageBottomMargin );
}

View File

@@ -105,6 +105,7 @@ public:
void writePreferencesToApplicationStore();
QPageLayout defaultPageLayout() const;
QMarginsF margins() const;
public: // Pdm Fields
caf::PdmField<caf::AppEnum<RiaGuiApplication::RINavigationPolicy>> navigationPolicy;

View File

@@ -89,10 +89,9 @@ void RicSnapshotViewToFileFeature::savePlotPDFReportAs( const QString& fileName,
pdfPrinter.setPageLayout( plot->pageLayout() );
pdfPrinter.setCreator( QCoreApplication::applicationName() );
pdfPrinter.setResolution( resolution );
QRect widgetRect = plot->viewWidget()->contentsRect();
QRect fullPageRect = pdfPrinter.pageLayout().fullRectPixels( resolution );
QRect paintRect = pdfPrinter.pageLayout().paintRectPixels( resolution );
plot->viewWidget()->resize( paintRect.size() );
QRect widgetRect = plot->viewWidget()->contentsRect();
QRect pageRect = pdfPrinter.pageLayout().fullRectPixels( resolution );
plot->viewWidget()->resize( pageRect.size() );
plot->renderWindowContent( &pdfPrinter );
plot->viewWidget()->resize( widgetRect.size() );
}

View File

@@ -21,7 +21,7 @@
#include "RicWellLogPlotCurveFeatureImpl.h"
#include "RiaGuiApplication.h"
#include "RiuMultiPlotWindow.h"
#include "RiuMultiPlotPage.h"
#include "RiuPlotMainWindow.h"
#include "RiuQwtPlotWidget.h"

View File

@@ -72,7 +72,7 @@ RimWellDistributionPlotCollection::RimWellDistributionPlotCollection()
"" );
m_plotWindowTitle = "Well Distribution Plots";
m_columnCountEnum = RimMultiPlotWindow::COLUMNS_UNLIMITED;
m_columnCount = RimMultiPlotWindow::COLUMNS_UNLIMITED;
m_showPlotLegends = false;
m_showWindow = false;

View File

@@ -19,10 +19,11 @@
#include "RimPlot.h"
#include "RiuMultiPlotWindow.h"
#include "RiuPlotMainWindow.h"
#include "RiuPlotMainWindowTools.h"
#include <QPainter>
#include <QPaintDevice>
#include <QRegularExpression>
#include <cvfAssert.h>
@@ -39,6 +40,16 @@ void RimMultiPlotWindow::ColumnCountEnum::setUp()
addItem( RimMultiPlotWindow::COLUMNS_UNLIMITED, "UNLIMITED", "Unlimited" );
setDefault( RimMultiPlotWindow::COLUMNS_2 );
}
template <>
void RimMultiPlotWindow::RowCountEnum::setUp()
{
addItem( RimMultiPlotWindow::ROWS_1, "1", "1 Row" );
addItem( RimMultiPlotWindow::ROWS_2, "2", "2 Rows" );
addItem( RimMultiPlotWindow::ROWS_3, "3", "3 Rows" );
addItem( RimMultiPlotWindow::ROWS_4, "4", "4 Rows" );
setDefault( RimMultiPlotWindow::ROWS_2 );
}
} // namespace caf
CAF_PDM_SOURCE_INIT( RimMultiPlotWindow, "MultiPlot" );
@@ -58,7 +69,8 @@ RimMultiPlotWindow::RimMultiPlotWindow( bool hidePlotsInTreeView )
m_plots.uiCapability()->setUiHidden( true );
m_plots.uiCapability()->setUiTreeChildrenHidden( hidePlotsInTreeView );
CAF_PDM_InitFieldNoDefault( &m_columnCountEnum, "NumberOfColumns", "Number of Columns", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_columnCount, "NumberOfColumns", "Number of Columns", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_rowsPerPage, "RowsPerPage", "Rows per Page", "", "", "" );
CAF_PDM_InitField( &m_showIndividualPlotTitles, "ShowPlotTitles", false, "Show Sub Plot Titles", "", "", "" );
@@ -91,7 +103,13 @@ RimMultiPlotWindow& RimMultiPlotWindow::operator=( RimMultiPlotWindow&& rhs )
m_plots.push_back( plot );
}
m_columnCountEnum = rhs.m_columnCountEnum;
m_showPlotWindowTitle = rhs.m_showPlotWindowTitle;
m_plotWindowTitle = rhs.m_plotWindowTitle;
m_columnCount = rhs.m_columnCount;
m_rowsPerPage = rhs.m_rowsPerPage;
m_showIndividualPlotTitles = rhs.m_showIndividualPlotTitles;
m_acceptDrops = rhs.m_acceptDrops;
return *this;
}
@@ -274,7 +292,7 @@ std::vector<RimPlot*> RimMultiPlotWindow::visiblePlots() const
//--------------------------------------------------------------------------------------------------
void RimMultiPlotWindow::doUpdateLayout()
{
if ( m_showWindow )
if ( m_showWindow && m_viewer )
{
m_viewer->scheduleUpdate();
}
@@ -350,11 +368,19 @@ void RimMultiPlotWindow::setAutoScaleYEnabled( bool enabled )
//--------------------------------------------------------------------------------------------------
int RimMultiPlotWindow::columnCount() const
{
if ( m_columnCountEnum() == COLUMNS_UNLIMITED )
if ( m_columnCount() == COLUMNS_UNLIMITED )
{
return std::numeric_limits<int>::max();
}
return static_cast<int>( m_columnCountEnum() );
return static_cast<int>( m_columnCount() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimMultiPlotWindow::rowsPerPage() const
{
return static_cast<int>( m_rowsPerPage() );
}
//--------------------------------------------------------------------------------------------------
@@ -362,7 +388,15 @@ int RimMultiPlotWindow::columnCount() const
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimMultiPlotWindow::columnCountField()
{
return &m_columnCountEnum;
return &m_columnCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimMultiPlotWindow::rowsPerPageField()
{
return &m_rowsPerPage;
}
//--------------------------------------------------------------------------------------------------
@@ -494,7 +528,7 @@ void RimMultiPlotWindow::fieldChangedByUi( const caf::PdmFieldHandle* changedFie
updatePlotWindowTitle();
applyPlotWindowTitleToWidgets();
}
else if ( changedField == &m_columnCountEnum )
else if ( changedField == &m_columnCount || changedField == &m_rowsPerPage )
{
updateLayout();
RiuPlotMainWindowTools::refreshToolbars();
@@ -520,7 +554,8 @@ void RimMultiPlotWindow::uiOrderingForPlotLayout( QString uiConfigName, caf::Pdm
uiOrdering.add( &m_plotWindowTitle );
uiOrdering.add( &m_showIndividualPlotTitles );
RimPlotWindow::uiOrderingForLegendSettings( uiConfigName, uiOrdering );
uiOrdering.add( &m_columnCountEnum );
uiOrdering.add( &m_columnCount );
uiOrdering.add( &m_rowsPerPage );
}
//--------------------------------------------------------------------------------------------------
@@ -531,7 +566,7 @@ QList<caf::PdmOptionItemInfo> RimMultiPlotWindow::calculateValueOptions( const c
{
QList<caf::PdmOptionItemInfo> options = RimPlotWindow::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
if ( fieldNeedingOptions == &m_columnCountEnum )
if ( fieldNeedingOptions == &m_columnCount )
{
for ( size_t i = 0; i < ColumnCountEnum::size(); ++i )
{

View File

@@ -18,7 +18,7 @@
#pragma once
#include "RimPlotWindow.h"
#include "RiuMultiPlotWindow.h"
#include "RiuMultiPlotInterface.h"
#include "cafAppEnum.h"
#include "cafPdmChildArrayField.h"
@@ -49,6 +49,15 @@ public:
};
using ColumnCountEnum = caf::AppEnum<ColumnCount>;
enum RowCount
{
ROWS_1 = 1,
ROWS_2 = 2,
ROWS_3 = 3,
ROWS_4 = 4,
};
using RowCountEnum = caf::AppEnum<RowCount>;
public:
RimMultiPlotWindow( bool hidePlotsInTreeView = false );
~RimMultiPlotWindow() override;
@@ -82,7 +91,9 @@ public:
void setAutoScaleYEnabled( bool enabled );
int columnCount() const;
int rowsPerPage() const;
caf::PdmFieldHandle* columnCountField();
caf::PdmFieldHandle* rowsPerPageField();
bool showPlotTitles() const;
void zoomAll() override;
@@ -134,11 +145,12 @@ private:
protected:
caf::PdmField<bool> m_showPlotWindowTitle;
caf::PdmField<QString> m_plotWindowTitle;
caf::PdmField<ColumnCountEnum> m_columnCountEnum;
caf::PdmField<ColumnCountEnum> m_columnCount;
caf::PdmField<RowCountEnum> m_rowsPerPage;
caf::PdmField<bool> m_showIndividualPlotTitles;
friend class RiuMultiPlotWindow;
QPointer<RiuMultiPlotWindow> m_viewer;
friend class RiuMultiPlotInterface;
QPointer<RiuMultiPlotInterface> m_viewer;
private:
caf::PdmChildArrayField<RimPlot*> m_plots;

View File

@@ -32,7 +32,7 @@
#include "RimWellLogCurveCommonDataSource.h"
#include "RimWellLogTrack.h"
#include "RiuMultiPlotWindow.h"
#include "RiuMultiPlotPage.h"
#include "RiuPlotMainWindow.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtPlotWidget.h"
@@ -105,7 +105,7 @@ RimWellLogPlot::RimWellLogPlot()
m_maxAvailableDepth = -HUGE_VAL;
m_commonDataSourceEnabled = true;
m_columnCountEnum = RimMultiPlotWindow::COLUMNS_UNLIMITED;
m_columnCount = RimMultiPlotWindow::COLUMNS_UNLIMITED;
m_plotWindowTitle.xmlCapability()->setIOWritable( false );
m_plotLegendsHorizontal = false;
@@ -616,7 +616,7 @@ void RimWellLogPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
caf::PdmUiGroup* titleAndLegendsGroup = uiOrdering.addNewGroup( "Plot Layout" );
uiOrderingForAutoName( uiConfigName, *titleAndLegendsGroup );
RimPlotWindow::uiOrderingForLegendSettings( uiConfigName, *titleAndLegendsGroup );
titleAndLegendsGroup->add( &m_columnCountEnum );
titleAndLegendsGroup->add( &m_columnCount );
uiOrdering.skipRemainingFields( true );
}
@@ -683,7 +683,7 @@ void RimWellLogPlot::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_columnCountEnum )
if ( field == &m_columnCount )
{
auto comboAttr = dynamic_cast<caf::PdmUiComboBoxEditorAttribute*>( attribute );
if ( comboAttr )

View File

@@ -35,7 +35,7 @@
#include <set>
class RimWellLogCurveCommonDataSource;
class RiuMultiPlotWindow;
class RiuMultiPlotPage;
class RimPlotWindow;
class QKeyEvent;

View File

@@ -67,7 +67,6 @@
#include "RimWellRftPlot.h"
#include "RiuMainWindow.h"
#include "RiuMultiPlotWindow.h"
#include "RiuPlotAnnotationTool.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtPlotWidget.h"

View File

@@ -52,7 +52,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuCellAndNncPickEventHandler.h
${CMAKE_CURRENT_LIST_DIR}/RiuPickItemInfo.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotInterface.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotWindow.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.h
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.h
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.h
${CMAKE_CURRENT_LIST_DIR}/RiuPlotAnnotationTool.h
@@ -144,6 +147,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuCellAndNncPickEventHandler.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuPickItemInfo.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotWindow.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.cpp
@@ -209,6 +213,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuViewerCommands.h
${CMAKE_CURRENT_LIST_DIR}/RiuTreeViewEventFilter.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogPlot.h
${CMAKE_CURRENT_LIST_DIR}/RiuWellLogTrack.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotInterface.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotPage.h
${CMAKE_CURRENT_LIST_DIR}/RiuMultiPlotWindow.h
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotWidget.h
${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotLegend.h

View File

@@ -139,7 +139,7 @@ std::vector<std::pair<QPoint, QString>> RiuAbstractLegendFrame::visibleLabels( c
{
const int textX = layout.tickEndX + layout.tickTextLeadSpace;
const double overlapTolerance = 1.1 * layout.charHeight;
const double overlapTolerance = 1.2 * layout.charHeight;
int lastVisibleTextY = 0;
std::vector<std::pair<QPoint, QString>> visibleTickLabels;

View File

@@ -100,6 +100,9 @@ int RiuCategoryLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index
{
float categoryHeight = static_cast<float>( layout.colorBarRect.height() ) / labelCount();
int textY = static_cast<int>( layout.colorBarRect.top() + index * categoryHeight + categoryHeight / 2 );
textY += layout.charAscent / 2;
int offset = layout.charAscent - static_cast<int>( std::ceil( layout.charHeight / 2.0 ) );
textY += offset;
return textY;
}

View File

@@ -0,0 +1,58 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QWidget>
class RiuQwtPlotWidget;
class QPaintDevice;
class QScrollBar;
//==================================================================================================
//
// RiuMultiPlotInterface
//
//==================================================================================================
class RiuMultiPlotInterface : public QWidget
{
Q_OBJECT
public:
RiuMultiPlotInterface( QWidget* parent = nullptr )
: QWidget( parent )
{
}
virtual ~RiuMultiPlotInterface() {}
virtual void addPlot( RiuQwtPlotWidget* plotWidget ) = 0;
virtual void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) = 0;
virtual void removePlot( RiuQwtPlotWidget* plotWidget ) = 0;
virtual int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) = 0;
virtual void setPlotTitle( const QString& plotTitle ) = 0;
virtual void setTitleVisible( bool visible ) = 0;
virtual void setFontSize( int fontSize ) = 0;
virtual int fontSize() const = 0;
virtual void scheduleUpdate() = 0;
virtual void scheduleReplotOfAllPlots() = 0;
virtual void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) = 0;
virtual void renderTo( QPaintDevice* paintDevice ) = 0;
};

View File

@@ -0,0 +1,902 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// 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 "RiuMultiPlotPage.h"
#include "RiaApplication.h"
#include "RiaPlotWindowRedrawScheduler.h"
#include "RiaPreferences.h"
#include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h"
#include "RiaGuiApplication.h"
#include "RimContextCommandBuilder.h"
#include "RimMultiPlotWindow.h"
#include "RimWellLogTrack.h"
#include "RiuMainWindow.h"
#include "RiuPlotMainWindow.h"
#include "RiuPlotObjectPicker.h"
#include "RiuQwtPlotLegend.h"
#include "RiuQwtPlotWidget.h"
#include "cafCmdFeatureMenuBuilder.h"
#include "cafSelectionManager.h"
#include "cvfAssert.h"
#include "qwt_legend.h"
#include "qwt_plot_layout.h"
#include "qwt_plot_renderer.h"
#include "qwt_scale_draw.h"
#include <QDebug>
#include <QDesktopWidget>
#include <QFocusEvent>
#include <QFontMetrics>
#include <QGraphicsDropShadowEffect>
#include <QHBoxLayout>
#include <QMdiSubWindow>
#include <QMenu>
#include <QScrollBar>
#include <QTimer>
#include <cmath>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuMultiPlotPage::RiuMultiPlotPage( RimMultiPlotWindow* plotDefinition, QWidget* parent )
: RiuMultiPlotInterface( parent )
, m_plotDefinition( plotDefinition )
{
Q_ASSERT( plotDefinition );
m_plotDefinition = plotDefinition;
m_layout = new QVBoxLayout( this );
m_layout->setMargin( 0 );
m_layout->setSpacing( 2 );
m_plotTitle = createTitleLabel();
m_layout->addWidget( m_plotTitle );
m_plotLayout = new QHBoxLayout;
m_layout->addLayout( m_plotLayout );
m_plotWidgetFrame = new QFrame;
m_plotWidgetFrame->setVisible( true );
m_plotLayout->addWidget( m_plotWidgetFrame, 1 );
m_gridLayout = new QGridLayout( m_plotWidgetFrame );
m_gridLayout->setContentsMargins( 0, 0, 0, 0 );
m_gridLayout->setSpacing( 1 );
QPalette newPalette( palette() );
newPalette.setColor( QPalette::Window, Qt::white );
setPalette( newPalette );
setAutoFillBackground( true );
new RiuPlotObjectPicker( m_plotTitle, m_plotDefinition );
m_dropTargetPlaceHolder = new QLabel( "Drag plots here" );
m_dropTargetPlaceHolder->setAlignment( Qt::AlignCenter );
m_dropTargetPlaceHolder->setObjectName(
QString( "%1" ).arg( reinterpret_cast<uint64_t>( m_dropTargetPlaceHolder.data() ) ) );
m_dropTargetStyleSheet = createDropTargetStyleSheet();
m_dropTargetStyleSheet.applyToWidget( m_dropTargetPlaceHolder );
this->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding );
setFocusPolicy( Qt::StrongFocus );
setAcceptDrops( m_plotDefinition->acceptDrops() );
RiaApplication* app = RiaApplication::instance();
int defaultFontSize = RiaFontCache::pointSizeFromFontSizeEnum( app->preferences()->defaultPlotFontSize() );
setFontSize( defaultFontSize );
this->setObjectName( QString( "%1" ).arg( reinterpret_cast<uint64_t>( this ) ) );
this->setBackgroundRole( QPalette::Window );
QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect( this );
dropShadowEffect->setOffset( 4.0, 4.0 );
dropShadowEffect->setBlurRadius( 4.0 );
dropShadowEffect->setColor( QColor( 40, 40, 40, 40 ) );
this->setGraphicsEffect( dropShadowEffect );
updateMarginsFromPageLayout();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuMultiPlotPage::~RiuMultiPlotPage() {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMultiPlotWindow* RiuMultiPlotPage::ownerPlotDefinition()
{
return m_plotDefinition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::addPlot( RiuQwtPlotWidget* plotWidget )
{
// Insert the plot to the left of the scroll bar
insertPlot( plotWidget, m_plotWidgets.size() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::insertPlot( RiuQwtPlotWidget* plotWidget, size_t index )
{
plotWidget->setDraggable( true ); // Becomes draggable when added to a grid plot window
m_plotWidgets.insert( static_cast<int>( index ), plotWidget );
plotWidget->setVisible( false );
QLabel* subTitle = new QLabel( plotWidget->plotDefinition()->description() );
subTitle->setAlignment( Qt::AlignRight );
subTitle->setVisible( false );
m_subTitles.insert( static_cast<int>( index ), subTitle );
RiuQwtPlotLegend* legend = new RiuQwtPlotLegend( this );
int legendColumns = 1;
if ( m_plotDefinition->legendsHorizontal() )
{
legendColumns = 4; // unlimited
}
legend->setMaxColumns( legendColumns );
legend->horizontalScrollBar()->setVisible( false );
legend->verticalScrollBar()->setVisible( false );
legend->connect( plotWidget,
SIGNAL( legendDataChanged( const QVariant&, const QList<QwtLegendData>& ) ),
SLOT( updateLegend( const QVariant&, const QList<QwtLegendData>& ) ) );
QObject::connect( legend, SIGNAL( legendUpdated() ), this, SLOT( onLegendUpdated() ) );
legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
legend->setVisible( false );
plotWidget->updateLegend();
m_legends.insert( static_cast<int>( index ), legend );
scheduleUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::removePlot( RiuQwtPlotWidget* plotWidget )
{
if ( !plotWidget ) return;
int plotWidgetIdx = m_plotWidgets.indexOf( plotWidget );
if ( plotWidgetIdx < 0 ) return;
m_plotWidgets.removeAt( plotWidgetIdx );
plotWidget->setParent( nullptr );
RiuQwtPlotLegend* legend = m_legends[plotWidgetIdx];
legend->setParent( nullptr );
m_legends.removeAt( plotWidgetIdx );
delete legend;
QLabel* subTitle = m_subTitles[plotWidgetIdx];
subTitle->setParent( nullptr );
m_subTitles.removeAt( plotWidgetIdx );
delete subTitle;
scheduleUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::removeAllPlots()
{
auto plotWidgets = m_plotWidgets;
for ( RiuQwtPlotWidget* plotWidget : plotWidgets )
{
removePlot( plotWidget );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::setPlotTitle( const QString& plotTitle )
{
m_plotTitle->setText( plotTitle );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::setTitleVisible( bool visible )
{
m_plotTitle->setVisible( visible );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::setSelectionsVisible( bool visible )
{
for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets )
{
if ( visible && caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), 0 ) )
{
plotWidget->setWidgetState( "selected" );
}
else
{
caf::UiStyleSheet::clearWidgetStates( plotWidget );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::setFontSize( int fontSize )
{
QFont font = m_plotTitle->font();
font.setPointSize( fontSize + 1 );
font.setBold( true );
m_plotTitle->setFont( font );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuMultiPlotPage::fontSize() const
{
return m_plotTitle->font().pointSize() - 1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuMultiPlotPage::indexOfPlotWidget( RiuQwtPlotWidget* plotWidget )
{
return m_plotWidgets.indexOf( plotWidget );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::scheduleUpdate()
{
RiaPlotWindowRedrawScheduler::instance()->scheduleMultiPlotPageUpdate( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::scheduleReplotOfAllPlots()
{
for ( RiuQwtPlotWidget* plotWidget : visiblePlotWidgets() )
{
plotWidget->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::renderTo( QPaintDevice* paintDevice )
{
QPainter painter( paintDevice );
renderTo( &painter );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::renderTo( QPainter* painter )
{
setSelectionsVisible( false );
m_plotTitle->render( painter );
// Subtract margins because we are rendering into part inside the margins
QPoint marginOffset( m_layout->contentsMargins().left(), m_layout->contentsMargins().top() );
for ( auto subTitle : subTitlesForVisiblePlots() )
{
if ( subTitle->isVisible() )
{
QPoint renderOffset = m_plotWidgetFrame->mapToParent( subTitle->frameGeometry().topLeft() ) - marginOffset;
subTitle->render( painter, renderOffset );
}
}
for ( auto legend : legendsForVisiblePlots() )
{
QPoint renderOffset = m_plotWidgetFrame->mapToParent( legend->frameGeometry().topLeft() ) - marginOffset;
legend->render( painter, renderOffset );
}
for ( auto plotWidget : visiblePlotWidgets() )
{
QRect plotWidgetGeometry = plotWidget->frameGeometry();
QPoint plotWidgetTopLeft = plotWidgetGeometry.topLeft();
QPoint plotWidgetFrameTopLeft = m_plotWidgetFrame->frameGeometry().topLeft();
plotWidgetGeometry.moveTo( plotWidgetTopLeft + plotWidgetFrameTopLeft - marginOffset );
plotWidget->renderTo( painter, plotWidgetGeometry );
}
setSelectionsVisible( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::contextMenuEvent( QContextMenuEvent* event )
{
QMenu menu;
caf::CmdFeatureMenuBuilder menuBuilder;
caf::SelectionManager::instance()->setSelectedItem( ownerPlotDefinition() );
menuBuilder << "RicShowPlotDataFeature";
menuBuilder << "RicShowContributingWellsFromPlotFeature";
menuBuilder.appendToMenu( &menu );
if ( menu.actions().size() > 0 )
{
menu.exec( event->globalPos() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QLabel* RiuMultiPlotPage::createTitleLabel() const
{
QLabel* plotTitle = new QLabel( "PLOT TITLE HERE", nullptr );
plotTitle->setVisible( m_plotDefinition->isMultiPlotTitleVisible() );
plotTitle->setAlignment( Qt::AlignHCenter );
plotTitle->setWordWrap( true );
plotTitle->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
return plotTitle;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::showEvent( QShowEvent* event )
{
QWidget::showEvent( event );
scheduleUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::dragEnterEvent( QDragEnterEvent* event )
{
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source )
{
setWidgetState( "dragTargetInto" );
event->acceptProposedAction();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::dragMoveEvent( QDragMoveEvent* event )
{
if ( event->answerRect().intersects( this->geometry() ) )
{
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source && willAcceptDroppedPlot( source ) )
{
setWidgetState( "dragTargetInto" );
QRect originalGeometry = source->geometry();
QPoint offset = source->dragStartPosition();
QRect newRect( event->pos() - offset, originalGeometry.size() );
QList<QPointer<RiuQwtPlotWidget>> visiblePlotWidgets = this->visiblePlotWidgets();
int insertBeforeIndex = visiblePlotWidgets.size();
for ( int visibleIndex = 0; visibleIndex < visiblePlotWidgets.size(); ++visibleIndex )
{
caf::UiStyleSheet::clearWidgetStates( visiblePlotWidgets[visibleIndex] );
if ( visiblePlotWidgets[visibleIndex]->frameIsInFrontOfThis( newRect ) )
{
insertBeforeIndex = std::min( insertBeforeIndex, visibleIndex );
}
}
if ( insertBeforeIndex >= 0 && insertBeforeIndex < visiblePlotWidgets.size() )
{
visiblePlotWidgets[insertBeforeIndex]->setWidgetState( "dragTargetBefore" );
}
if ( insertBeforeIndex > 0 )
{
int insertAfterIndex = insertBeforeIndex - 1;
visiblePlotWidgets[insertAfterIndex]->setWidgetState( "dragTargetAfter" );
}
event->acceptProposedAction();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::dragLeaveEvent( QDragLeaveEvent* event )
{
caf::UiStyleSheet::clearWidgetStates( this );
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::dropEvent( QDropEvent* event )
{
caf::UiStyleSheet::clearWidgetStates( this );
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] );
}
if ( this->geometry().contains( event->pos() ) )
{
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source && willAcceptDroppedPlot( source ) )
{
event->acceptProposedAction();
QRect originalGeometry = source->geometry();
QPoint offset = source->dragStartPosition();
QRect newRect( event->pos() - offset, originalGeometry.size() );
int beforeIndex = m_plotWidgets.size();
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
if ( m_plotWidgets[tIdx]->isVisible() )
{
if ( m_plotWidgets[tIdx]->frameIsInFrontOfThis( newRect ) )
{
beforeIndex = tIdx;
break;
}
}
}
RimPlot* insertAfter = nullptr;
if ( beforeIndex > 0 )
{
insertAfter = m_plotWidgets[beforeIndex - 1]->plotDefinition();
}
RimPlot* plotToMove = source->plotDefinition();
if ( insertAfter != plotToMove )
{
m_plotDefinition->movePlotsToThis( {plotToMove}, insertAfter );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuMultiPlotPage::hasHeightForWidth() const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuMultiPlotPage::heightForWidth( int width ) const
{
QPageLayout pageLayout = m_plotDefinition->pageLayout();
QRectF rect = pageLayout.fullRectPoints();
double aspectRatio = rect.height() / rect.width();
int height = static_cast<int>( width * aspectRatio );
return height;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::updateMarginsFromPageLayout()
{
QPageLayout pageLayout = m_plotDefinition->pageLayout();
const int resolution = RiaGuiApplication::applicationResolution();
QMargins margins = pageLayout.marginsPixels( resolution );
m_layout->setContentsMargins( margins );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuMultiPlotPage::sizeHint() const
{
QPageLayout pageLayout = m_plotDefinition->pageLayout();
const int resolution = RiaGuiApplication::applicationResolution();
QRect rect = pageLayout.fullRectPixels( resolution );
return rect.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuMultiPlotPage::minimumSizeHint() const
{
QSize fullSizeHint = sizeHint();
return QSize( fullSizeHint.width() / 2, fullSizeHint.height() / 2 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuMultiPlotPage::willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<int, int> RiuMultiPlotPage::rowAndColumnCount( int plotWidgetCount ) const
{
if ( plotWidgetCount == 0 )
{
return std::make_pair( 0, 0 );
}
int columnCount = std::max( 1, m_plotDefinition->columnCount() );
int rowCount = static_cast<int>( std::ceil( plotWidgetCount / static_cast<double>( columnCount ) ) );
return std::make_pair( rowCount, columnCount );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::onSelectionManagerSelectionChanged( const std::set<int>& changedSelectionLevels )
{
for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets )
{
CAF_ASSERT( plotWidget );
bool isSelected = false;
for ( int changedLevel : changedSelectionLevels )
{
isSelected = isSelected ||
caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), changedLevel );
}
if ( isSelected )
{
plotWidget->setWidgetState( "selected" );
}
else
{
caf::UiStyleSheet::clearWidgetStates( plotWidget );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::setWidgetState( const QString& widgetState )
{
m_dropTargetStyleSheet.setWidgetState( m_dropTargetPlaceHolder, widgetState );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuMultiPlotPage::showYAxis( int row, int column ) const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::performUpdate()
{
updateMarginsFromPageLayout();
reinsertPlotWidgets();
alignCanvasTops();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::onLegendUpdated()
{
scheduleUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::reinsertPlotWidgets()
{
clearGridLayout();
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
if ( m_plotWidgets[tIdx] )
{
m_plotWidgets[tIdx]->hide();
}
if ( m_legends[tIdx] )
{
m_legends[tIdx]->hide();
}
if ( m_subTitles[tIdx] )
{
m_subTitles[tIdx]->hide();
}
}
QList<QPointer<QLabel>> subTitles = this->subTitlesForVisiblePlots();
QList<QPointer<RiuQwtPlotLegend>> legends = this->legendsForVisiblePlots();
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = this->visiblePlotWidgets();
if ( plotWidgets.empty() && acceptDrops() )
{
m_gridLayout->addWidget( m_dropTargetPlaceHolder, 0, 0 );
m_gridLayout->setRowStretch( 0, 1 );
m_dropTargetPlaceHolder->setVisible( true );
}
else
{
m_dropTargetPlaceHolder->setVisible( false );
auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() );
int row = 0;
int column = 0;
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
int expextedColSpan = static_cast<int>( plotWidgets[visibleIndex]->plotDefinition()->colSpan() );
int colSpan = std::min( expextedColSpan, rowAndColumnCount.second );
int rowSpan = plotWidgets[visibleIndex]->plotDefinition()->rowSpan();
std::tie( row, column ) = findAvailableRowAndColumn( row, column, colSpan, rowAndColumnCount.second );
m_gridLayout->addWidget( subTitles[visibleIndex], 3 * row, column, 1, colSpan );
m_gridLayout
->addWidget( legends[visibleIndex], 3 * row + 1, column, 1, colSpan, Qt::AlignHCenter | Qt::AlignBottom );
m_gridLayout->addWidget( plotWidgets[visibleIndex], 3 * row + 2, column, 1 + ( rowSpan - 1 ) * 3, colSpan );
subTitles[visibleIndex]->setVisible( m_plotDefinition->showPlotTitles() );
plotWidgets[visibleIndex]->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft, showYAxis( row, column ) );
plotWidgets[visibleIndex]->setAxisTitleEnabled( QwtPlot::yLeft, showYAxis( row, column ) );
plotWidgets[visibleIndex]->show();
if ( m_plotDefinition->legendsVisible() )
{
int legendColumns = 1;
if ( m_plotDefinition->legendsHorizontal() )
{
legendColumns = 4; // unlimited
}
legends[visibleIndex]->setMaxColumns( legendColumns );
QFont legendFont = legends[visibleIndex]->font();
legendFont.setPointSize( m_plotDefinition->legendFontSize() );
legends[visibleIndex]->setFont( legendFont );
legends[visibleIndex]->show();
}
else
{
legends[visibleIndex]->hide();
}
// Set basic row and column stretches
for ( int r = row; r < row + rowSpan; ++r )
{
m_gridLayout->setRowStretch( 3 * r + 2, 1 );
}
for ( int c = column; c < column + colSpan; ++c )
{
int colStretch = 1;
if ( showYAxis( row, column ) ) colStretch += 1;
m_gridLayout->setColumnStretch( c, std::max( colStretch, m_gridLayout->columnStretch( c ) ) );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuMultiPlotPage::alignCanvasTops()
{
CVF_ASSERT( m_legends.size() == m_plotWidgets.size() );
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = visiblePlotWidgets();
QList<QPointer<RiuQwtPlotLegend>> legends = legendsForVisiblePlots();
if ( plotWidgets.empty() ) return 0;
auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() );
std::vector<double> maxExtents( rowAndColumnCount.first, 0.0 );
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
int row = visibleIndex / rowAndColumnCount.second;
QFont font = m_plotWidgets[visibleIndex]->axisFont( QwtPlot::xTop );
maxExtents[row] = std::max( maxExtents[row],
plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->extent( font ) );
}
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
int row = visibleIndex / rowAndColumnCount.second;
plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( maxExtents[row] );
legends[visibleIndex]->adjustSize();
}
return maxExtents[0];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotPage::clearGridLayout()
{
if ( m_gridLayout )
{
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
m_gridLayout->removeWidget( m_subTitles[tIdx] );
m_gridLayout->removeWidget( m_legends[tIdx] );
m_gridLayout->removeWidget( m_plotWidgets[tIdx] );
}
QLayoutItem* item;
while ( ( item = m_gridLayout->takeAt( 0 ) ) != nullptr )
{
}
QWidget().setLayout( m_gridLayout );
delete m_gridLayout;
m_gridLayout = new QGridLayout( m_plotWidgetFrame );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet RiuMultiPlotPage::createDropTargetStyleSheet()
{
caf::UiStyleSheet styleSheet;
styleSheet.set( "background-color", "white" );
styleSheet.set( "border", "1px dashed black" );
styleSheet.set( "font-size", "14pt" );
styleSheet.property( "dragTargetInto" ).set( "border", "1px dashed lime" );
styleSheet.property( "dragTargetInto" ).set( "background-color", "#DDFFDD" );
return styleSheet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<RiuQwtPlotWidget>> RiuMultiPlotPage::visiblePlotWidgets() const
{
QList<QPointer<RiuQwtPlotWidget>> plotWidgets;
for ( QPointer<RiuQwtPlotWidget> plotWidget : m_plotWidgets )
{
if ( plotWidget->isChecked() )
{
plotWidgets.push_back( plotWidget );
}
}
return plotWidgets;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<RiuQwtPlotLegend>> RiuMultiPlotPage::legendsForVisiblePlots() const
{
QList<QPointer<RiuQwtPlotLegend>> legends;
for ( int i = 0; i < m_plotWidgets.size(); ++i )
{
if ( m_plotWidgets[i]->isChecked() )
{
legends.push_back( m_legends[i] );
}
}
return legends;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<QLabel>> RiuMultiPlotPage::subTitlesForVisiblePlots() const
{
QList<QPointer<QLabel>> subTitles;
for ( int i = 0; i < m_plotWidgets.size(); ++i )
{
if ( m_plotWidgets[i]->isChecked() )
{
subTitles.push_back( m_subTitles[i] );
}
}
return subTitles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<int, int>
RiuMultiPlotPage::findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const
{
int availableRow = startRow;
int availableColumn = startColumn;
while ( true )
{
for ( ; availableColumn < columnCount; ++availableColumn )
{
bool fits = true;
for ( int c = availableColumn; ( c < availableColumn + columnSpan ) && fits; ++c )
{
if ( c >= columnCount )
{
fits = false;
}
if ( m_gridLayout->itemAtPosition( 3 * availableRow, c ) != nullptr )
{
fits = false;
}
}
if ( fits )
{
return std::make_pair( availableRow, availableColumn );
}
}
availableColumn = 0;
availableRow++;
}
return std::make_pair( availableRow, availableColumn );
}

View File

@@ -0,0 +1,145 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuMultiPlotInterface.h"
#include "cafUiStyleSheet.h"
#include "cafPdmPointer.h"
#include "cafSelectionChangedReceiver.h"
#include <QFrame>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QList>
#include <QPointer>
#include <QWidget>
#include <map>
class RiaPlotWindowRedrawScheduler;
class RimMultiPlotWindow;
class RiuQwtPlotLegend;
class RiuQwtPlotWidget;
class QFocusEvent;
class QLabel;
class QPaintDevice;
class QScrollBar;
class QwtLegend;
class QwtLegendData;
class QwtPlot;
//==================================================================================================
//
// RiuMultiPlotPage
//
//==================================================================================================
class RiuMultiPlotPage : public RiuMultiPlotInterface, public caf::SelectionChangedReceiver
{
Q_OBJECT
public:
RiuMultiPlotPage( RimMultiPlotWindow* plotDefinition, QWidget* parent = nullptr );
~RiuMultiPlotPage() override;
RimMultiPlotWindow* ownerPlotDefinition();
void addPlot( RiuQwtPlotWidget* plotWidget ) override;
void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) override;
void removePlot( RiuQwtPlotWidget* plotWidget ) override;
void removeAllPlots();
int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget ) override;
void setSelectionsVisible( bool visible );
void setPlotTitle( const QString& plotTitle ) override;
void setTitleVisible( bool visible ) override;
void setFontSize( int fontSize ) override;
int fontSize() const override;
void scheduleUpdate() override;
void scheduleReplotOfAllPlots() override;
void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) override {}
void renderTo( QPaintDevice* paintDevice ) override;
void renderTo( QPainter* painter );
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
int heightForWidth( int width ) const override;
protected:
void contextMenuEvent( QContextMenuEvent* ) override;
QLabel* createTitleLabel() const;
void showEvent( QShowEvent* event ) override;
void dragEnterEvent( QDragEnterEvent* event ) override;
void dragMoveEvent( QDragMoveEvent* event ) override;
void dragLeaveEvent( QDragLeaveEvent* event ) override;
void dropEvent( QDropEvent* event ) override;
bool hasHeightForWidth() const override;
void updateMarginsFromPageLayout();
virtual bool willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const;
std::pair<int, int> rowAndColumnCount( int plotWidgetCount ) const;
virtual void onSelectionManagerSelectionChanged( const std::set<int>& changedSelectionLevels ) override;
void setWidgetState( const QString& widgetState );
virtual bool showYAxis( int row, int column ) const;
void reinsertPlotWidgets();
int alignCanvasTops();
void clearGridLayout();
caf::UiStyleSheet createDropTargetStyleSheet();
QList<QPointer<RiuQwtPlotWidget>> visiblePlotWidgets() const;
QList<QPointer<RiuQwtPlotLegend>> legendsForVisiblePlots() const;
QList<QPointer<QLabel>> subTitlesForVisiblePlots() const;
std::pair<int, int> findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const;
private slots:
virtual void performUpdate();
void onLegendUpdated();
protected:
friend class RiuMultiPlotWindow;
QPointer<QVBoxLayout> m_layout;
QPointer<QHBoxLayout> m_plotLayout;
QPointer<QFrame> m_plotWidgetFrame;
QPointer<QGridLayout> m_gridLayout;
QPointer<QLabel> m_plotTitle;
QList<QPointer<QLabel>> m_subTitles;
QList<QPointer<RiuQwtPlotLegend>> m_legends;
QList<QPointer<RiuQwtPlotWidget>> m_plotWidgets;
caf::PdmPointer<RimMultiPlotWindow> m_plotDefinition;
QPointer<QLabel> m_dropTargetPlaceHolder;
caf::UiStyleSheet m_dropTargetStyleSheet;
private:
friend class RiaPlotWindowRedrawScheduler;
};

View File

@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
// 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
@@ -19,17 +18,16 @@
#include "RiuMultiPlotWindow.h"
#include "RiaApplication.h"
#include "RiaGuiApplication.h"
#include "RiaPlotWindowRedrawScheduler.h"
#include "RiaPreferences.h"
#include "WellLogCommands/RicWellLogPlotTrackFeatureImpl.h"
#include "RimContextCommandBuilder.h"
#include "RimMultiPlotWindow.h"
#include "RimWellLogTrack.h"
#include "RiuMainWindow.h"
#include "RiuMultiPlotPage.h"
#include "RiuPlotMainWindow.h"
#include "RiuPlotObjectPicker.h"
#include "RiuQwtPlotLegend.h"
@@ -51,63 +49,98 @@
#include <QHBoxLayout>
#include <QMdiSubWindow>
#include <QMenu>
#include <QPagedPaintDevice>
#include <QScrollArea>
#include <QScrollBar>
#include <QTimer>
#include <algorithm>
#include <cmath>
class BookFrame : public QFrame
{
public:
BookFrame( int margins, QWidget* parent = nullptr )
: QFrame( parent )
, m_margins( margins )
{
}
QSize calculateSize( int width ) const
{
int pageWidth = width - 2 * m_margins;
QList<RiuMultiPlotPage*> pages = this->findChildren<RiuMultiPlotPage*>();
QSize fullSize( 0, 0 );
for ( auto page : pages )
{
fullSize.setWidth( pageWidth );
fullSize.setHeight( fullSize.height() + m_margins + page->heightForWidth( pageWidth ) );
}
QSize minSize = minimumSizeHint();
return QSize( std::max( minSize.width(), fullSize.width() ), std::max( minSize.height(), fullSize.height() ) );
}
protected:
QSize minimumSizeHint() const override
{
QList<RiuMultiPlotPage*> pages = this->findChildren<RiuMultiPlotPage*>();
QSize fullSize( 0, 0 );
for ( auto page : pages )
{
fullSize.setWidth( std::max( fullSize.width(), page->minimumSizeHint().width() ) );
fullSize.setHeight( fullSize.height() + 8 + page->minimumSizeHint().height() );
}
return fullSize;
}
private:
int m_margins;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuMultiPlotWindow::RiuMultiPlotWindow( RimMultiPlotWindow* plotDefinition, QWidget* parent )
: QWidget( parent )
: RiuMultiPlotInterface( parent )
, m_plotDefinition( plotDefinition )
, m_plotTitle( "Multi Plot" )
, m_titleVisible( true )
{
Q_ASSERT( plotDefinition );
m_plotDefinition = plotDefinition;
const int spacing = 8;
this->setBackgroundRole( QPalette::Dark );
this->setContentsMargins( 0, 0, 0, 0 );
m_layout = new QVBoxLayout( this );
m_layout->setMargin( 0 );
m_layout->setSpacing( 2 );
m_plotTitle = createTitleLabel();
m_layout->addWidget( m_plotTitle );
m_plotLayout = new QHBoxLayout;
m_layout->addLayout( m_plotLayout );
m_plotWidgetFrame = new QFrame;
m_plotWidgetFrame->setVisible( true );
m_plotLayout->addWidget( m_plotWidgetFrame, 1 );
m_gridLayout = new QGridLayout( m_plotWidgetFrame );
m_gridLayout->setContentsMargins( 1, 1, 1, 1 );
m_gridLayout->setSpacing( 1 );
QPalette newPalette( palette() );
newPalette.setColor( QPalette::Window, Qt::white );
setPalette( newPalette );
m_layout->setContentsMargins( 0, 0, 0, 0 );
m_scrollArea = new QScrollArea( this );
m_scrollArea->setFrameStyle( QFrame::NoFrame );
m_scrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_scrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
m_layout->addWidget( m_scrollArea );
m_book = new BookFrame( spacing );
m_book->setFrameStyle( QFrame::NoFrame );
m_scrollArea->setWidget( m_book );
m_scrollArea->setWidgetResizable( true );
m_book->setBackgroundRole( QPalette::Dark );
m_bookLayout = new QVBoxLayout( m_book );
m_bookLayout->setSpacing( spacing );
m_scrollArea->setVisible( true );
m_book->setVisible( true );
setAutoFillBackground( true );
new RiuPlotObjectPicker( m_plotTitle, m_plotDefinition );
m_dropTargetPlaceHolder = new QLabel( "Drag plots here" );
m_dropTargetPlaceHolder->setAlignment( Qt::AlignCenter );
m_dropTargetPlaceHolder->setObjectName(
QString( "%1" ).arg( reinterpret_cast<uint64_t>( m_dropTargetPlaceHolder.data() ) ) );
m_dropTargetStyleSheet = createDropTargetStyleSheet();
m_dropTargetStyleSheet.applyToWidget( m_dropTargetPlaceHolder );
this->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding );
setFocusPolicy( Qt::StrongFocus );
setAcceptDrops( m_plotDefinition->acceptDrops() );
RiaApplication* app = RiaApplication::instance();
int defaultFontSize = RiaFontCache::pointSizeFromFontSizeEnum( app->preferences()->defaultPlotFontSize() );
setFontSize( defaultFontSize );
QSize pageSize = m_plotDefinition->pageLayout().fullRectPixels( RiaGuiApplication::applicationResolution() ).size();
setBookSize( pageSize.width() );
this->setObjectName( QString( "%1" ).arg( reinterpret_cast<uint64_t>( this ) ) );
}
@@ -137,7 +170,7 @@ RimViewWindow* RiuMultiPlotWindow::ownerViewWindow() const
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::addPlot( RiuQwtPlotWidget* plotWidget )
{
// Insert the plot to the left of the scroll bar
// Push the plot to the back of the list
insertPlot( plotWidget, m_plotWidgets.size() );
}
@@ -148,29 +181,6 @@ void RiuMultiPlotWindow::insertPlot( RiuQwtPlotWidget* plotWidget, size_t index
{
plotWidget->setDraggable( true ); // Becomes draggable when added to a grid plot window
m_plotWidgets.insert( static_cast<int>( index ), plotWidget );
QLabel* subTitle = new QLabel( plotWidget->plotDefinition()->description() );
subTitle->setAlignment( Qt::AlignRight );
m_subTitles.insert( static_cast<int>( index ), subTitle );
RiuQwtPlotLegend* legend = new RiuQwtPlotLegend( this );
int legendColumns = 1;
if ( m_plotDefinition->legendsHorizontal() )
{
legendColumns = 4; // unlimited
}
legend->setMaxColumns( legendColumns );
legend->horizontalScrollBar()->setVisible( false );
legend->verticalScrollBar()->setVisible( false );
legend->connect( plotWidget,
SIGNAL( legendDataChanged( const QVariant&, const QList<QwtLegendData>& ) ),
SLOT( updateLegend( const QVariant&, const QList<QwtLegendData>& ) ) );
QObject::connect( legend, SIGNAL( legendUpdated() ), this, SLOT( onLegendUpdated() ) );
legend->contentsWidget()->layout()->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
plotWidget->updateLegend();
m_legends.insert( static_cast<int>( index ), legend );
scheduleUpdate();
}
@@ -185,17 +195,6 @@ void RiuMultiPlotWindow::removePlot( RiuQwtPlotWidget* plotWidget )
CVF_ASSERT( plotWidgetIdx >= 0 );
m_plotWidgets.removeAt( plotWidgetIdx );
plotWidget->setParent( nullptr );
RiuQwtPlotLegend* legend = m_legends[plotWidgetIdx];
legend->setParent( nullptr );
m_legends.removeAt( plotWidgetIdx );
delete legend;
QLabel* subTitle = m_subTitles[plotWidgetIdx];
subTitle->setParent( nullptr );
m_subTitles.removeAt( plotWidgetIdx );
delete subTitle;
scheduleUpdate();
}
@@ -205,7 +204,11 @@ void RiuMultiPlotWindow::removePlot( RiuQwtPlotWidget* plotWidget )
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::setPlotTitle( const QString& plotTitle )
{
m_plotTitle->setText( plotTitle );
m_plotTitle = plotTitle;
for ( int i = 0; i < m_pages.size(); ++i )
{
m_pages[i]->setPlotTitle( QString( "%1 %2/%3" ).arg( m_plotTitle ).arg( i + 1 ).arg( m_pages.size() ) );
}
}
//--------------------------------------------------------------------------------------------------
@@ -213,7 +216,11 @@ void RiuMultiPlotWindow::setPlotTitle( const QString& plotTitle )
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::setTitleVisible( bool visible )
{
m_plotTitle->setVisible( visible );
m_titleVisible = visible;
for ( auto page : m_pages )
{
page->setTitleVisible( visible );
}
}
//--------------------------------------------------------------------------------------------------
@@ -239,11 +246,8 @@ void RiuMultiPlotWindow::setSelectionsVisible( bool visible )
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::setFontSize( int fontSize )
{
QFont font = m_plotTitle->font();
font.setPointSize( fontSize + 1 );
font.setBold( true );
m_plotTitle->setFont( font );
QFont font = this->font();
font.setPointSize( fontSize );
}
//--------------------------------------------------------------------------------------------------
@@ -251,7 +255,7 @@ void RiuMultiPlotWindow::setFontSize( int fontSize )
//--------------------------------------------------------------------------------------------------
int RiuMultiPlotWindow::fontSize() const
{
return m_plotTitle->font().pointSize() - 1;
return this->font().pointSize();
}
//--------------------------------------------------------------------------------------------------
@@ -267,7 +271,7 @@ int RiuMultiPlotWindow::indexOfPlotWidget( RiuQwtPlotWidget* plotWidget )
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::scheduleUpdate()
{
RiaPlotWindowRedrawScheduler::instance()->schedulePlotWindowUpdate( this );
RiaPlotWindowRedrawScheduler::instance()->scheduleMultiPlotWindowUpdate( this );
}
//--------------------------------------------------------------------------------------------------
@@ -286,7 +290,25 @@ void RiuMultiPlotWindow::scheduleReplotOfAllPlots()
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::renderTo( QPaintDevice* paintDevice )
{
doRenderTo( paintDevice );
setSelectionsVisible( false );
bool firstPage = true;
QPainter painter( paintDevice );
for ( RiuMultiPlotPage* page : m_pages )
{
if ( !firstPage )
{
QPagedPaintDevice* pagedDevice = dynamic_cast<QPagedPaintDevice*>( paintDevice );
if ( pagedDevice )
{
pagedDevice->newPage();
}
}
page->renderTo( &painter );
firstPage = false;
}
setSelectionsVisible( true );
}
//--------------------------------------------------------------------------------------------------
@@ -310,155 +332,37 @@ void RiuMultiPlotWindow::contextMenuEvent( QContextMenuEvent* event )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QLabel* RiuMultiPlotWindow::createTitleLabel() const
{
QLabel* plotTitle = new QLabel( "PLOT TITLE HERE", nullptr );
plotTitle->setVisible( m_plotDefinition->isMultiPlotTitleVisible() );
plotTitle->setAlignment( Qt::AlignHCenter );
plotTitle->setWordWrap( true );
plotTitle->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
return plotTitle;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::showEvent( QShowEvent* event )
{
QWidget::showEvent( event );
scheduleUpdate();
performUpdate();
setBookSize( width() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::dragEnterEvent( QDragEnterEvent* event )
void RiuMultiPlotWindow::resizeEvent( QResizeEvent* event )
{
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source )
{
setWidgetState( "dragTargetInto" );
event->acceptProposedAction();
}
setBookSize( event->size().width() );
QWidget::resizeEvent( event );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::dragMoveEvent( QDragMoveEvent* event )
void RiuMultiPlotWindow::setBookSize( int frameWidth )
{
if ( event->answerRect().intersects( this->geometry() ) )
for ( auto page : m_pages )
{
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source && willAcceptDroppedPlot( source ) )
{
setWidgetState( "dragTargetInto" );
QRect originalGeometry = source->geometry();
QPoint offset = source->dragStartPosition();
QRect newRect( event->pos() - offset, originalGeometry.size() );
QList<QPointer<RiuQwtPlotWidget>> visiblePlotWidgets = this->visiblePlotWidgets();
int insertBeforeIndex = visiblePlotWidgets.size();
for ( int visibleIndex = 0; visibleIndex < visiblePlotWidgets.size(); ++visibleIndex )
{
caf::UiStyleSheet::clearWidgetStates( visiblePlotWidgets[visibleIndex] );
if ( visiblePlotWidgets[visibleIndex]->frameIsInFrontOfThis( newRect ) )
{
insertBeforeIndex = std::min( insertBeforeIndex, visibleIndex );
}
}
if ( insertBeforeIndex >= 0 && insertBeforeIndex < visiblePlotWidgets.size() )
{
visiblePlotWidgets[insertBeforeIndex]->setWidgetState( "dragTargetBefore" );
}
if ( insertBeforeIndex > 0 )
{
int insertAfterIndex = insertBeforeIndex - 1;
visiblePlotWidgets[insertAfterIndex]->setWidgetState( "dragTargetAfter" );
}
event->acceptProposedAction();
}
int width = page->width();
int heightForWidth = page->heightForWidth( width );
page->resize( width, heightForWidth );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::dragLeaveEvent( QDragLeaveEvent* event )
{
caf::UiStyleSheet::clearWidgetStates( this );
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::dropEvent( QDropEvent* event )
{
caf::UiStyleSheet::clearWidgetStates( this );
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] );
}
if ( this->geometry().contains( event->pos() ) )
{
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source && willAcceptDroppedPlot( source ) )
{
event->acceptProposedAction();
QRect originalGeometry = source->geometry();
QPoint offset = source->dragStartPosition();
QRect newRect( event->pos() - offset, originalGeometry.size() );
int beforeIndex = m_plotWidgets.size();
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
if ( m_plotWidgets[tIdx]->isVisible() )
{
if ( m_plotWidgets[tIdx]->frameIsInFrontOfThis( newRect ) )
{
beforeIndex = tIdx;
break;
}
}
}
RimPlot* insertAfter = nullptr;
if ( beforeIndex > 0 )
{
insertAfter = m_plotWidgets[beforeIndex - 1]->plotDefinition();
}
RimPlot* plotToMove = source->plotDefinition();
if ( insertAfter != plotToMove )
{
m_plotDefinition->movePlotsToThis( {plotToMove}, insertAfter );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuMultiPlotWindow::willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const
{
return true;
m_book->setFixedSize( m_book->calculateSize( frameWidth ) );
}
//--------------------------------------------------------------------------------------------------
@@ -476,40 +380,6 @@ std::pair<int, int> RiuMultiPlotWindow::rowAndColumnCount( int plotWidgetCount )
return std::make_pair( rowCount, columnCount );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::onSelectionManagerSelectionChanged( const std::set<int>& changedSelectionLevels )
{
for ( RiuQwtPlotWidget* plotWidget : m_plotWidgets )
{
CAF_ASSERT( plotWidget );
bool isSelected = false;
for ( int changedLevel : changedSelectionLevels )
{
isSelected = isSelected ||
caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), changedLevel );
}
if ( isSelected )
{
plotWidget->setWidgetState( "selected" );
}
else
{
caf::UiStyleSheet::clearWidgetStates( plotWidget );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::setWidgetState( const QString& widgetState )
{
m_dropTargetStyleSheet.setWidgetState( m_dropTargetPlaceHolder, widgetState );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -523,183 +393,9 @@ bool RiuMultiPlotWindow::showYAxis( int row, int column ) const
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::performUpdate()
{
reinsertPlotWidgets();
alignCanvasTops();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::onLegendUpdated()
{
scheduleUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::reinsertPlotWidgets()
{
clearGridLayout();
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
if ( m_plotWidgets[tIdx] )
{
m_plotWidgets[tIdx]->hide();
}
if ( m_legends[tIdx] )
{
m_legends[tIdx]->hide();
}
if ( m_subTitles[tIdx] )
{
m_subTitles[tIdx]->hide();
}
}
QList<QPointer<QLabel>> subTitles = this->subTitlesForVisiblePlots();
QList<QPointer<RiuQwtPlotLegend>> legends = this->legendsForVisiblePlots();
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = this->visiblePlotWidgets();
if ( plotWidgets.empty() && acceptDrops() )
{
m_gridLayout->addWidget( m_dropTargetPlaceHolder, 0, 0 );
m_gridLayout->setRowStretch( 0, 1 );
m_dropTargetPlaceHolder->setVisible( true );
}
else
{
m_dropTargetPlaceHolder->setVisible( false );
auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() );
int row = 0;
int column = 0;
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
int expextedColSpan = static_cast<int>( plotWidgets[visibleIndex]->plotDefinition()->colSpan() );
int colSpan = std::min( expextedColSpan, rowAndColumnCount.second );
int rowSpan = plotWidgets[visibleIndex]->plotDefinition()->rowSpan();
std::tie( row, column ) = findAvailableRowAndColumn( row, column, colSpan, rowAndColumnCount.second );
m_gridLayout->addWidget( subTitles[visibleIndex], 3 * row, column, 1, colSpan );
m_gridLayout
->addWidget( legends[visibleIndex], 3 * row + 1, column, 1, colSpan, Qt::AlignHCenter | Qt::AlignBottom );
m_gridLayout->addWidget( plotWidgets[visibleIndex], 3 * row + 2, column, 1 + ( rowSpan - 1 ) * 3, colSpan );
subTitles[visibleIndex]->setVisible( m_plotDefinition->showPlotTitles() );
plotWidgets[visibleIndex]->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft, showYAxis( row, column ) );
plotWidgets[visibleIndex]->setAxisTitleEnabled( QwtPlot::yLeft, showYAxis( row, column ) );
plotWidgets[visibleIndex]->show();
if ( m_plotDefinition->legendsVisible() )
{
int legendColumns = 1;
if ( m_plotDefinition->legendsHorizontal() )
{
legendColumns = 4; // unlimited
}
legends[visibleIndex]->setMaxColumns( legendColumns );
QFont legendFont = legends[visibleIndex]->font();
legendFont.setPointSize( m_plotDefinition->legendFontSize() );
legends[visibleIndex]->setFont( legendFont );
legends[visibleIndex]->show();
}
else
{
legends[visibleIndex]->hide();
}
// Set basic row and column stretches
for ( int r = row; r < row + rowSpan; ++r )
{
m_gridLayout->setRowStretch( 3 * r + 2, 1 );
}
for ( int c = column; c < column + colSpan; ++c )
{
int colStretch = 1;
if ( showYAxis( row, column ) ) colStretch += 1;
m_gridLayout->setColumnStretch( c, std::max( colStretch, m_gridLayout->columnStretch( c ) ) );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiuMultiPlotWindow::alignCanvasTops()
{
CVF_ASSERT( m_legends.size() == m_plotWidgets.size() );
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = visiblePlotWidgets();
QList<QPointer<RiuQwtPlotLegend>> legends = legendsForVisiblePlots();
if ( plotWidgets.empty() ) return 0;
auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() );
std::vector<double> maxExtents( rowAndColumnCount.first, 0.0 );
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
int row = visibleIndex / rowAndColumnCount.second;
QFont font = m_plotWidgets[visibleIndex]->axisFont( QwtPlot::xTop );
maxExtents[row] = std::max( maxExtents[row],
plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->extent( font ) );
}
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
int row = visibleIndex / rowAndColumnCount.second;
plotWidgets[visibleIndex]->axisScaleDraw( QwtPlot::xTop )->setMinimumExtent( maxExtents[row] );
legends[visibleIndex]->adjustSize();
}
return maxExtents[0];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::clearGridLayout()
{
if ( m_gridLayout )
{
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
m_gridLayout->removeWidget( m_subTitles[tIdx] );
m_gridLayout->removeWidget( m_legends[tIdx] );
m_gridLayout->removeWidget( m_plotWidgets[tIdx] );
}
QLayoutItem* item;
while ( ( item = m_gridLayout->takeAt( 0 ) ) != nullptr )
{
}
QWidget().setLayout( m_gridLayout );
delete m_gridLayout;
m_gridLayout = new QGridLayout( m_plotWidgetFrame );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet RiuMultiPlotWindow::createDropTargetStyleSheet()
{
caf::UiStyleSheet styleSheet;
styleSheet.set( "background-color", "white" );
styleSheet.set( "border", "1px dashed black" );
styleSheet.set( "font-size", "14pt" );
styleSheet.property( "dragTargetInto" ).set( "border", "1px dashed lime" );
styleSheet.property( "dragTargetInto" ).set( "background-color", "#DDFFDD" );
return styleSheet;
deleteAllPages();
createPages();
updateGeometry();
}
//--------------------------------------------------------------------------------------------------
@@ -721,102 +417,61 @@ QList<QPointer<RiuQwtPlotWidget>> RiuMultiPlotWindow::visiblePlotWidgets() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<RiuQwtPlotLegend>> RiuMultiPlotWindow::legendsForVisiblePlots() const
void RiuMultiPlotWindow::deleteAllPages()
{
QList<QPointer<RiuQwtPlotLegend>> legends;
for ( int i = 0; i < m_plotWidgets.size(); ++i )
for ( RiuMultiPlotPage* page : m_pages )
{
if ( m_plotWidgets[i]->isChecked() )
{
legends.push_back( m_legends[i] );
}
m_bookLayout->removeWidget( page );
page->removeAllPlots();
delete page;
}
return legends;
m_pages.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<QPointer<QLabel>> RiuMultiPlotWindow::subTitlesForVisiblePlots() const
void RiuMultiPlotWindow::createPages()
{
QList<QPointer<QLabel>> subTitles;
for ( int i = 0; i < m_plotWidgets.size(); ++i )
QList<QPointer<RiuQwtPlotWidget>> plotWidgets = this->visiblePlotWidgets();
auto rowAndColumnCount = this->rowAndColumnCount( plotWidgets.size() );
int rowsPerPage = m_plotDefinition->rowsPerPage();
int row = 0;
int column = 0;
RiuMultiPlotPage* page = new RiuMultiPlotPage( m_plotDefinition, this );
m_pages.push_back( page );
m_bookLayout->addWidget( page );
for ( int visibleIndex = 0; visibleIndex < plotWidgets.size(); ++visibleIndex )
{
if ( m_plotWidgets[i]->isChecked() )
int expextedColSpan = static_cast<int>( plotWidgets[visibleIndex]->plotDefinition()->colSpan() );
int colSpan = std::min( expextedColSpan, rowAndColumnCount.second );
std::tie( row, column ) = page->findAvailableRowAndColumn( row, column, colSpan, rowAndColumnCount.second );
if ( row >= rowsPerPage )
{
subTitles.push_back( m_subTitles[i] );
page = new RiuMultiPlotPage( m_plotDefinition, this );
m_pages.push_back( page );
m_bookLayout->addWidget( page );
row = 0;
column = 0;
}
page->addPlot( plotWidgets[visibleIndex] );
page->setVisible( true );
page->performUpdate();
}
return subTitles;
// Reapply plot titles
setPlotTitle( m_plotTitle );
setTitleVisible( m_titleVisible );
m_book->adjustSize();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<int, int>
RiuMultiPlotWindow::findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const
const QList<QPointer<RiuMultiPlotPage>>& RiuMultiPlotWindow::pages() const
{
int availableRow = startRow;
int availableColumn = startColumn;
while ( true )
{
for ( ; availableColumn < columnCount; ++availableColumn )
{
bool fits = true;
for ( int c = availableColumn; ( c < availableColumn + columnSpan ) && fits; ++c )
{
if ( c >= columnCount )
{
fits = false;
}
if ( m_gridLayout->itemAtPosition( 3 * availableRow, c ) != nullptr )
{
fits = false;
}
}
if ( fits )
{
return std::make_pair( availableRow, availableColumn );
}
}
availableColumn = 0;
availableRow++;
}
return std::make_pair( availableRow, availableColumn );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::doRenderTo( QPaintDevice* paintDevice )
{
QPainter painter( paintDevice );
setSelectionsVisible( false );
m_plotTitle->render( &painter );
for ( auto subTitle : subTitlesForVisiblePlots() )
{
if ( subTitle->isVisible() )
{
subTitle->render( &painter, m_plotWidgetFrame->mapToParent( subTitle->frameGeometry().topLeft() ) );
}
}
for ( auto legend : legendsForVisiblePlots() )
{
legend->render( &painter, m_plotWidgetFrame->mapToParent( legend->frameGeometry().topLeft() ) );
}
for ( auto plotWidget : visiblePlotWidgets() )
{
QRect plotWidgetGeometry = plotWidget->frameGeometry();
QPoint plotWidgetTopLeft = plotWidgetGeometry.topLeft();
QPoint plotWidgetFrameTopLeft = m_plotWidgetFrame->frameGeometry().topLeft();
plotWidgetGeometry.moveTo( plotWidgetTopLeft + plotWidgetFrameTopLeft );
plotWidget->renderTo( &painter, plotWidgetGeometry );
}
setSelectionsVisible( true );
return m_pages;
}

View File

@@ -1,7 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
// 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
@@ -20,6 +19,8 @@
#pragma once
#include "RiuInterfaceToViewWindow.h"
#include "RiuMultiPlotInterface.h"
#include "cafUiStyleSheet.h"
#include "cafPdmPointer.h"
@@ -36,15 +37,15 @@
class RiaPlotWindowRedrawScheduler;
class RimMultiPlotWindow;
class RiuQwtPlotLegend;
class RiuMultiPlotPage;
class RiuQwtPlotWidget;
class BookFrame;
class QFocusEvent;
class QLabel;
class QPainter;
class QPaintDevice;
class QScrollArea;
class QScrollBar;
class QwtLegend;
class QwtLegendData;
class QwtPlot;
//==================================================================================================
@@ -52,7 +53,7 @@ class QwtPlot;
// RiuMultiPlotWidget
//
//==================================================================================================
class RiuMultiPlotWindow : public QWidget, public RiuInterfaceToViewWindow, public caf::SelectionChangedReceiver
class RiuMultiPlotWindow : public RiuMultiPlotInterface, public RiuInterfaceToViewWindow
{
Q_OBJECT
@@ -63,13 +64,13 @@ public:
RimMultiPlotWindow* ownerPlotDefinition();
RimViewWindow* ownerViewWindow() const override;
void addPlot( RiuQwtPlotWidget* plotWidget );
void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index );
void removePlot( RiuQwtPlotWidget* plotWidget );
void addPlot( RiuQwtPlotWidget* plotWidget ) override;
void insertPlot( RiuQwtPlotWidget* plotWidget, size_t index ) override;
void removePlot( RiuQwtPlotWidget* plotWidget ) override;
void setPlotTitle( const QString& plotTitle );
void setPlotTitle( const QString& plotTitle ) override;
void setTitleVisible( bool visible );
void setTitleVisible( bool visible ) override;
void setSelectionsVisible( bool visible );
void setFontSize( int fontSize );
@@ -77,63 +78,45 @@ public:
int indexOfPlotWidget( RiuQwtPlotWidget* plotWidget );
void scheduleUpdate();
void scheduleReplotOfAllPlots();
virtual void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) {}
void scheduleUpdate();
void scheduleReplotOfAllPlots();
void updateVerticalScrollBar( double visibleMin, double visibleMax, double totalMin, double totalMax ) override {}
void renderTo( QPaintDevice* paintDevice );
void renderTo( QPaintDevice* painter ) override;
protected:
void contextMenuEvent( QContextMenuEvent* ) override;
QLabel* createTitleLabel() const;
void contextMenuEvent( QContextMenuEvent* ) override;
void showEvent( QShowEvent* event ) override;
void dragEnterEvent( QDragEnterEvent* event ) override;
void dragMoveEvent( QDragMoveEvent* event ) override;
void dragLeaveEvent( QDragLeaveEvent* event ) override;
void dropEvent( QDropEvent* event ) override;
virtual bool willAcceptDroppedPlot( const RiuQwtPlotWidget* plotWidget ) const;
void showEvent( QShowEvent* event ) override;
void resizeEvent( QResizeEvent* event ) override;
void setBookSize( int frameWidth );
std::pair<int, int> rowAndColumnCount( int plotWidgetCount ) const;
virtual void onSelectionManagerSelectionChanged( const std::set<int>& changedSelectionLevels ) override;
void setWidgetState( const QString& widgetState );
virtual bool showYAxis( int row, int column ) const;
void reinsertPlotWidgets();
int alignCanvasTops();
void clearGridLayout();
caf::UiStyleSheet createDropTargetStyleSheet();
QList<QPointer<RiuQwtPlotWidget>> visiblePlotWidgets() const;
QList<QPointer<RiuQwtPlotLegend>> legendsForVisiblePlots() const;
QList<QPointer<QLabel>> subTitlesForVisiblePlots() const;
std::pair<int, int> findAvailableRowAndColumn( int startRow, int startColumn, int columnSpan, int columnCount ) const;
virtual void doRenderTo( QPaintDevice* paintDevice );
private:
void deleteAllPages();
void createPages();
const QList<QPointer<RiuMultiPlotPage>>& pages() const;
private slots:
virtual void performUpdate();
void onLegendUpdated();
protected:
QPointer<QVBoxLayout> m_layout;
QPointer<QHBoxLayout> m_plotLayout;
QPointer<QFrame> m_plotWidgetFrame;
QPointer<QGridLayout> m_gridLayout;
QPointer<QLabel> m_plotTitle;
QList<QPointer<QLabel>> m_subTitles;
QList<QPointer<RiuQwtPlotLegend>> m_legends;
friend class RiaPlotWindowRedrawScheduler;
QPointer<QVBoxLayout> m_layout;
QPointer<QScrollArea> m_scrollArea;
QPointer<BookFrame> m_book;
QPointer<QVBoxLayout> m_bookLayout;
QList<QPointer<RiuMultiPlotPage>> m_pages;
QList<QPointer<RiuQwtPlotWidget>> m_plotWidgets;
caf::PdmPointer<RimMultiPlotWindow> m_plotDefinition;
QPointer<QLabel> m_dropTargetPlaceHolder;
caf::UiStyleSheet m_dropTargetStyleSheet;
private:
friend class RiaPlotWindowRedrawScheduler;
QString m_plotTitle;
bool m_titleVisible;
};

View File

@@ -43,7 +43,7 @@
#include "RiuDockWidgetTools.h"
#include "RiuDragDrop.h"
#include "RiuMdiSubWindow.h"
#include "RiuMultiPlotWindow.h"
#include "RiuMultiPlotPage.h"
#include "RiuToolTipMenu.h"
#include "RiuTreeViewEventFilter.h"
#include "RiuWellAllocationPlot.h"

View File

@@ -199,5 +199,6 @@ void RiuScalarMapperLegendFrame::renderRect( QPainter* painter, const LayoutInfo
int RiuScalarMapperLegendFrame::labelPixelPosY( const LayoutInfo& layout, int index ) const
{
int indexFromBottom = labelCount() - index - 1;
return layout.colorBarRect.bottom() - layout.tickYPixelPos[indexFromBottom] + layout.charAscent / 2;
int offset = layout.charAscent - static_cast<int>( std::ceil( layout.charHeight / 2.0 ) );
return layout.colorBarRect.bottom() - layout.tickYPixelPos[indexFromBottom] + offset;
}

View File

@@ -15,7 +15,7 @@
///
//--------------------------------------------------------------------------------------------------
RiuWellLogPlot::RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent )
: RiuMultiPlotWindow( plotDefinition, parent )
: RiuMultiPlotPage( plotDefinition, parent )
{
m_trackScrollBar = new QScrollBar( nullptr );
m_trackScrollBar->setOrientation( Qt::Vertical );
@@ -40,11 +40,9 @@ RimWellLogPlot* RiuWellLogPlot::wellLogPlotDefinition()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWellLogPlot::doRenderTo( QPaintDevice* paintDevice )
RimViewWindow* RiuWellLogPlot::ownerViewWindow() const
{
m_trackScrollBar->setVisible( false );
RiuMultiPlotWindow::doRenderTo( paintDevice );
m_trackScrollBar->setVisible( true );
return m_plotDefinition;
}
//--------------------------------------------------------------------------------------------------
@@ -66,6 +64,16 @@ void RiuWellLogPlot::updateVerticalScrollBar( double minVisible, double maxVisib
m_trackScrollBar->blockSignals( false );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWellLogPlot::renderTo( QPaintDevice* paintDevice )
{
m_trackScrollBar->setVisible( false );
RiuMultiPlotPage::renderTo( paintDevice );
m_trackScrollBar->setVisible( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -17,18 +17,22 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiuMultiPlotWindow.h"
#include "RiuInterfaceToViewWindow.h"
#include "RiuMultiPlotPage.h"
class RiuQwtPlotWidget;
class RimWellLogPlot;
class RiuWellLogPlot : public RiuMultiPlotWindow
class RiuWellLogPlot : public RiuMultiPlotPage, public RiuInterfaceToViewWindow
{
Q_OBJECT
public:
RiuWellLogPlot( RimWellLogPlot* plotDefinition, QWidget* parent );
RimViewWindow* ownerViewWindow() const override;
void updateVerticalScrollBar( double minVisible, double maxVisible, double minAvailable, double maxAvailable ) override;
void renderTo( QPaintDevice* paintDevice ) override;
protected:
void keyPressEvent( QKeyEvent* event ) override;
@@ -37,7 +41,6 @@ protected:
void reinsertScrollbar();
void alignScrollbar( int offset );
void doRenderTo( QPaintDevice* paintDevice ) override;
private:
RimWellLogPlot* wellLogPlotDefinition();