QGIS/external/qwt-6.3.0/qwt_plot_abstract_canvas.cpp
Juergen E. Fischer 33fc476d89 * replace external qwtpolar with qwt 6.3
* require qwt >=6.2 (and fallback to internal 6.3 if system's qwt doesn't suffice)
* debian doesn't have qwt for Qt6 and won't have it for trixie
2025-07-23 07:11:51 +10:00

1130 lines
29 KiB
C++

/******************************************************************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_plot_abstract_canvas.h"
#include "qwt_plot.h"
#include "qwt_painter.h"
#include "qwt_null_paintdevice.h"
#include "qwt_math.h"
#include <qpainter.h>
#include <qpainterpath.h>
#include <qstyle.h>
#include <qstyleoption.h>
namespace
{
class QwtStyleSheetRecorder QWT_FINAL : public QwtNullPaintDevice
{
public:
explicit QwtStyleSheetRecorder( const QSize& size )
: m_size( size )
{
}
virtual void updateState( const QPaintEngineState& state ) QWT_OVERRIDE
{
if ( state.state() & QPaintEngine::DirtyPen )
{
m_pen = state.pen();
}
if ( state.state() & QPaintEngine::DirtyBrush )
{
m_brush = state.brush();
}
if ( state.state() & QPaintEngine::DirtyBrushOrigin )
{
m_origin = state.brushOrigin();
}
}
virtual void drawRects(const QRectF* rects, int count ) QWT_OVERRIDE
{
for ( int i = 0; i < count; i++ )
border.rectList += rects[i];
}
virtual void drawRects(const QRect* rects, int count ) QWT_OVERRIDE
{
for ( int i = 0; i < count; i++ )
border.rectList += rects[i];
}
virtual void drawPath( const QPainterPath& path ) QWT_OVERRIDE
{
const QRectF rect( QPointF( 0.0, 0.0 ), m_size );
if ( path.controlPointRect().contains( rect.center() ) )
{
setCornerRects( path );
alignCornerRects( rect );
background.path = path;
background.brush = m_brush;
background.origin = m_origin;
}
else
{
border.pathList += path;
}
}
void setCornerRects( const QPainterPath& path )
{
QPointF pos( 0.0, 0.0 );
for ( int i = 0; i < path.elementCount(); i++ )
{
QPainterPath::Element el = path.elementAt(i);
switch( el.type )
{
case QPainterPath::MoveToElement:
case QPainterPath::LineToElement:
{
pos.setX( el.x );
pos.setY( el.y );
break;
}
case QPainterPath::CurveToElement:
{
QRectF r( pos, QPointF( el.x, el.y ) );
clipRects += r.normalized();
pos.setX( el.x );
pos.setY( el.y );
break;
}
case QPainterPath::CurveToDataElement:
{
if ( clipRects.size() > 0 )
{
QRectF r = clipRects.last();
r.setCoords(
qwtMinF( r.left(), el.x ),
qwtMinF( r.top(), el.y ),
qwtMaxF( r.right(), el.x ),
qwtMaxF( r.bottom(), el.y )
);
clipRects.last() = r.normalized();
}
break;
}
}
}
}
protected:
virtual QSize sizeMetrics() const QWT_OVERRIDE
{
return m_size;
}
private:
void alignCornerRects( const QRectF& rect )
{
for ( int i = 0; i < clipRects.size(); i++ )
{
QRectF& r = clipRects[i];
if ( r.center().x() < rect.center().x() )
r.setLeft( rect.left() );
else
r.setRight( rect.right() );
if ( r.center().y() < rect.center().y() )
r.setTop( rect.top() );
else
r.setBottom( rect.bottom() );
}
}
public:
QVector< QRectF > clipRects;
struct Border
{
QList< QPainterPath > pathList;
QList< QRectF > rectList;
QRegion clipRegion;
} border;
struct Background
{
QPainterPath path;
QBrush brush;
QPointF origin;
} background;
private:
const QSize m_size;
QPen m_pen;
QBrush m_brush;
QPointF m_origin;
};
}
static void qwtUpdateContentsRect( int fw, QWidget* canvas )
{
canvas->setContentsMargins( fw, fw, fw, fw );
}
static void qwtFillRegion( QPainter* painter, const QRegion& region )
{
#if QT_VERSION >= 0x050800
for ( QRegion::const_iterator it = region.cbegin();
it != region.cend(); ++it )
{
painter->drawRect( *it );
}
#else
painter->drawRects( region.rects() );
#endif
}
static void qwtDrawBackground( QPainter* painter, QWidget* canvas )
{
painter->save();
QPainterPath borderClip;
( void )QMetaObject::invokeMethod(
canvas, "borderPath", Qt::DirectConnection,
Q_RETURN_ARG( QPainterPath, borderClip ), Q_ARG( QRect, canvas->rect() ) );
if ( !borderClip.isEmpty() )
painter->setClipPath( borderClip, Qt::IntersectClip );
const QBrush& brush = canvas->palette().brush( canvas->backgroundRole() );
if ( brush.style() == Qt::TexturePattern )
{
QPixmap pm( canvas->size() );
QwtPainter::fillPixmap( canvas, pm );
painter->drawPixmap( 0, 0, pm );
}
else if ( brush.gradient() )
{
const bool fillClipRegion =
brush.gradient()->coordinateMode() != QGradient::ObjectBoundingMode;
painter->setPen( Qt::NoPen );
painter->setBrush( brush );
if ( fillClipRegion )
qwtFillRegion( painter, painter->clipRegion() );
else
painter->drawRect( canvas->rect() );
}
else
{
painter->setPen( Qt::NoPen );
painter->setBrush( brush );
qwtFillRegion( painter, painter->clipRegion() );
}
painter->restore();
}
static inline void qwtDrawStyledBackground(
QWidget* w, QPainter* painter )
{
QStyleOption opt;
opt.initFrom(w);
w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
}
static QWidget* qwtBackgroundWidget( QWidget* w )
{
if ( w->parentWidget() == NULL )
return w;
if ( w->autoFillBackground() )
{
const QBrush brush = w->palette().brush( w->backgroundRole() );
if ( brush.color().alpha() > 0 )
return w;
}
if ( w->testAttribute( Qt::WA_StyledBackground ) )
{
QImage image( 1, 1, QImage::Format_ARGB32 );
image.fill( Qt::transparent );
QPainter painter( &image );
painter.translate( -w->rect().center() );
qwtDrawStyledBackground( w, &painter );
painter.end();
if ( qAlpha( image.pixel( 0, 0 ) ) != 0 )
return w;
}
return qwtBackgroundWidget( w->parentWidget() );
}
static void qwtFillBackground( QPainter* painter,
QWidget* widget, const QVector< QRectF >& fillRects )
{
if ( fillRects.isEmpty() )
return;
QRegion clipRegion;
if ( painter->hasClipping() )
clipRegion = painter->transform().map( painter->clipRegion() );
else
clipRegion = widget->contentsRect();
// Try to find out which widget fills
// the unfilled areas of the styled background
QWidget* bgWidget = qwtBackgroundWidget( widget->parentWidget() );
for ( int i = 0; i < fillRects.size(); i++ )
{
const QRect rect = fillRects[i].toAlignedRect();
if ( clipRegion.intersects( rect ) )
{
QPixmap pm( rect.size() );
QwtPainter::fillPixmap( bgWidget, pm, widget->mapTo( bgWidget, rect.topLeft() ) );
painter->drawPixmap( rect, pm );
}
}
}
static void qwtFillBackground( QPainter* painter, QWidget* canvas )
{
QVector< QRectF > rects;
if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
{
QwtStyleSheetRecorder recorder( canvas->size() );
QPainter p( &recorder );
qwtDrawStyledBackground( canvas, &p );
p.end();
if ( recorder.background.brush.isOpaque() )
rects = recorder.clipRects;
else
rects += canvas->rect();
}
else
{
const double borderRadius = canvas->property( "borderRadius" ).toDouble();
if ( borderRadius > 0.0 )
{
QSizeF sz( borderRadius, borderRadius );
const QRectF r = canvas->rect();
rects += QRectF( r.topLeft(), sz );
rects += QRectF( r.topRight() - QPointF( borderRadius, 0 ), sz );
rects += QRectF( r.bottomRight() - QPointF( borderRadius, borderRadius ), sz );
rects += QRectF( r.bottomLeft() - QPointF( 0, borderRadius ), sz );
}
}
qwtFillBackground( painter, canvas, rects);
}
static inline void qwtRevertPath( QPainterPath& path )
{
if ( path.elementCount() == 4 )
{
QPainterPath::Element el0 = path.elementAt(0);
QPainterPath::Element el3 = path.elementAt(3);
path.setElementPositionAt( 0, el3.x, el3.y );
path.setElementPositionAt( 3, el0.x, el0.y );
}
}
static QPainterPath qwtCombinePathList( const QRectF& rect,
const QList< QPainterPath >& pathList )
{
if ( pathList.isEmpty() )
return QPainterPath();
QPainterPath ordered[8]; // starting top left
for ( int i = 0; i < pathList.size(); i++ )
{
int index = -1;
QPainterPath subPath = pathList[i];
const QRectF br = pathList[i].controlPointRect();
if ( br.center().x() < rect.center().x() )
{
if ( br.center().y() < rect.center().y() )
{
if ( qAbs( br.top() - rect.top() ) <
qAbs( br.left() - rect.left() ) )
{
index = 1;
}
else
{
index = 0;
}
}
else
{
if ( qAbs( br.bottom() - rect.bottom() ) <
qAbs( br.left() - rect.left() ) )
{
index = 6;
}
else
{
index = 7;
}
}
if ( subPath.currentPosition().y() > br.center().y() )
qwtRevertPath( subPath );
}
else
{
if ( br.center().y() < rect.center().y() )
{
if ( qAbs( br.top() - rect.top() ) <
qAbs( br.right() - rect.right() ) )
{
index = 2;
}
else
{
index = 3;
}
}
else
{
if ( qAbs( br.bottom() - rect.bottom() ) <
qAbs( br.right() - rect.right() ) )
{
index = 5;
}
else
{
index = 4;
}
}
if ( subPath.currentPosition().y() < br.center().y() )
qwtRevertPath( subPath );
}
ordered[index] = subPath;
}
for ( int i = 0; i < 4; i++ )
{
if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() )
{
// we don't accept incomplete rounded borders
return QPainterPath();
}
}
const QPolygonF corners( rect );
QPainterPath path;
//path.moveTo( rect.topLeft() );
for ( int i = 0; i < 4; i++ )
{
if ( ordered[2 * i].isEmpty() )
{
path.lineTo( corners[i] );
}
else
{
path.connectPath( ordered[2 * i] );
path.connectPath( ordered[2 * i + 1] );
}
}
path.closeSubpath();
#if 0
return path.simplified();
#else
return path;
#endif
}
static QPainterPath qwtBorderPath( const QWidget* canvas, const QRect& rect )
{
if ( canvas->testAttribute(Qt::WA_StyledBackground ) )
{
QwtStyleSheetRecorder recorder( rect.size() );
QPainter painter( &recorder );
QStyleOption opt;
opt.initFrom( canvas );
opt.rect = rect;
canvas->style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, canvas );
painter.end();
if ( !recorder.background.path.isEmpty() )
return recorder.background.path;
if ( !recorder.border.rectList.isEmpty() )
return qwtCombinePathList( rect, recorder.border.pathList );
}
else
{
const double borderRadius = canvas->property( "borderRadius" ).toDouble();
if ( borderRadius > 0.0 )
{
double fw2 = canvas->property( "frameWidth" ).toInt() * 0.5;
QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 );
QPainterPath path;
path.addRoundedRect( r, borderRadius, borderRadius );
return path;
}
}
return QPainterPath();
}
class QwtPlotAbstractCanvas::PrivateData
{
public:
PrivateData()
: focusIndicator( NoFocusIndicator )
, borderRadius( 0 )
{
styleSheet.hasBorder = false;
}
FocusIndicator focusIndicator;
double borderRadius;
struct StyleSheet
{
bool hasBorder;
QPainterPath borderPath;
QVector< QRectF > cornerRects;
struct StyleSheetBackground
{
QBrush brush;
QPointF origin;
} background;
} styleSheet;
QWidget* canvasWidget;
};
/*!
\brief Constructor
\param canvasWidget plot canvas widget
*/
QwtPlotAbstractCanvas::QwtPlotAbstractCanvas( QWidget* canvasWidget )
{
m_data = new PrivateData;
m_data->canvasWidget = canvasWidget;
#ifndef QT_NO_CURSOR
canvasWidget->setCursor( Qt::CrossCursor );
#endif
canvasWidget->setAutoFillBackground( true );
}
//! Destructor
QwtPlotAbstractCanvas::~QwtPlotAbstractCanvas()
{
delete m_data;
}
//! Return parent plot widget
QwtPlot* QwtPlotAbstractCanvas::plot()
{
return qobject_cast< QwtPlot* >( m_data->canvasWidget->parent() );
}
//! Return parent plot widget
const QwtPlot* QwtPlotAbstractCanvas::plot() const
{
return qobject_cast< const QwtPlot* >( m_data->canvasWidget->parent() );
}
/*!
Set the focus indicator
\sa FocusIndicator, focusIndicator()
*/
void QwtPlotAbstractCanvas::setFocusIndicator( FocusIndicator focusIndicator )
{
m_data->focusIndicator = focusIndicator;
}
/*!
\return Focus indicator
\sa FocusIndicator, setFocusIndicator()
*/
QwtPlotAbstractCanvas::FocusIndicator QwtPlotAbstractCanvas::focusIndicator() const
{
return m_data->focusIndicator;
}
/*!
Draw the focus indication
\param painter Painter
*/
void QwtPlotAbstractCanvas::drawFocusIndicator( QPainter* painter )
{
const int margin = 1;
QRect focusRect = m_data->canvasWidget->contentsRect();
focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
QwtPainter::drawFocusRect( painter, m_data->canvasWidget, focusRect );
}
/*!
Set the radius for the corners of the border frame
\param radius Radius of a rounded corner
\sa borderRadius()
*/
void QwtPlotAbstractCanvas::setBorderRadius( double radius )
{
m_data->borderRadius = qwtMaxF( 0.0, radius );
}
/*!
\return Radius for the corners of the border frame
\sa setBorderRadius()
*/
double QwtPlotAbstractCanvas::borderRadius() const
{
return m_data->borderRadius;
}
//! \return Path for the canvas border
QPainterPath QwtPlotAbstractCanvas::canvasBorderPath( const QRect& rect ) const
{
return qwtBorderPath( canvasWidget(), rect );
}
/*!
Draw the border of the canvas
\param painter Painter
*/
void QwtPlotAbstractCanvas::drawBorder( QPainter* painter )
{
const QWidget* w = canvasWidget();
if ( m_data->borderRadius > 0 )
{
const int frameWidth = w->property( "frameWidth" ).toInt();
if ( frameWidth > 0 )
{
const int frameShape = w->property( "frameShape" ).toInt();
const int frameShadow = w->property( "frameShadow" ).toInt();
const QRectF frameRect = w->property( "frameRect" ).toRect();
QwtPainter::drawRoundedFrame( painter, frameRect,
m_data->borderRadius, m_data->borderRadius,
w->palette(), frameWidth, frameShape | frameShadow );
}
}
else
{
const int frameShape = w->property( "frameShape" ).toInt();
const int frameShadow = w->property( "frameShadow" ).toInt();
#if QT_VERSION < 0x050000
QStyleOptionFrameV3 opt;
#else
QStyleOptionFrame opt;
#endif
opt.initFrom( w );
opt.frameShape = QFrame::Shape( int( opt.frameShape ) | frameShape );
switch (frameShape)
{
case QFrame::Box:
case QFrame::HLine:
case QFrame::VLine:
case QFrame::StyledPanel:
case QFrame::Panel:
{
opt.lineWidth = w->property( "lineWidth" ).toInt();
opt.midLineWidth = w->property( "midLineWidth" ).toInt();
break;
}
default:
{
opt.lineWidth = w->property( "frameWidth" ).toInt();
break;
}
}
if ( frameShadow == QFrame::Sunken )
opt.state |= QStyle::State_Sunken;
else if ( frameShadow == QFrame::Raised )
opt.state |= QStyle::State_Raised;
w->style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, w );
}
}
//! Helper function for the derived plot canvas
void QwtPlotAbstractCanvas::drawBackground( QPainter* painter )
{
qwtDrawBackground( painter, canvasWidget() );
}
//! Helper function for the derived plot canvas
void QwtPlotAbstractCanvas::fillBackground( QPainter* painter )
{
qwtFillBackground( painter, canvasWidget() );
}
//! Helper function for the derived plot canvas
void QwtPlotAbstractCanvas::drawUnstyled( QPainter* painter )
{
fillBackground( painter );
QWidget* w = canvasWidget();
if ( w->autoFillBackground() )
{
const QRect canvasRect = w->rect();
painter->save();
painter->setPen( Qt::NoPen );
painter->setBrush( w->palette().brush( w->backgroundRole() ) );
const QRect frameRect = w->property( "frameRect" ).toRect();
if ( borderRadius() > 0.0 && ( canvasRect == frameRect ) )
{
const int frameWidth = w->property( "frameWidth" ).toInt();
if ( frameWidth > 0 )
{
painter->setClipPath( canvasBorderPath( canvasRect ) );
painter->drawRect( canvasRect );
}
else
{
painter->setRenderHint( QPainter::Antialiasing, true );
painter->drawPath( canvasBorderPath( canvasRect ) );
}
}
else
{
painter->drawRect( canvasRect );
}
painter->restore();
}
drawCanvas( painter );
}
//! Helper function for the derived plot canvas
void QwtPlotAbstractCanvas::drawStyled( QPainter* painter, bool hackStyledBackground )
{
fillBackground( painter );
if ( hackStyledBackground )
{
// Antialiasing rounded borders is done by
// inserting pixels with colors between the
// border color and the color on the canvas,
// When the border is painted before the plot items
// these colors are interpolated for the canvas
// and the plot items need to be clipped excluding
// the antialiased pixels. In situations, where
// the plot items fill the area at the rounded
// borders this is noticeable.
// The only way to avoid these annoying "artefacts"
// is to paint the border on top of the plot items.
if ( !m_data->styleSheet.hasBorder ||
m_data->styleSheet.borderPath.isEmpty() )
{
// We have no border with at least one rounded corner
hackStyledBackground = false;
}
}
QWidget* w = canvasWidget();
if ( hackStyledBackground )
{
painter->save();
// paint background without border
painter->setPen( Qt::NoPen );
painter->setBrush( m_data->styleSheet.background.brush );
painter->setBrushOrigin( m_data->styleSheet.background.origin );
painter->setClipPath( m_data->styleSheet.borderPath );
painter->drawRect( w->contentsRect() );
painter->restore();
drawCanvas( painter );
// Now paint the border on top
QStyleOptionFrame opt;
opt.initFrom( w );
w->style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, w);
}
else
{
QStyleOption opt;
opt.initFrom( w );
w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w );
drawCanvas( painter );
}
}
//! \brief Draw the plot to the canvas
void QwtPlotAbstractCanvas::drawCanvas( QPainter* painter )
{
QWidget* w = canvasWidget();
painter->save();
if ( !m_data->styleSheet.borderPath.isEmpty() )
{
painter->setClipPath(
m_data->styleSheet.borderPath, Qt::IntersectClip );
}
else
{
if ( borderRadius() > 0.0 )
{
const QRect frameRect = w->property( "frameRect" ).toRect();
painter->setClipPath( canvasBorderPath( frameRect ), Qt::IntersectClip );
}
else
{
painter->setClipRect( w->contentsRect(), Qt::IntersectClip );
}
}
QwtPlot* plot = qobject_cast< QwtPlot* >( w->parent() );
if ( plot )
plot->drawCanvas( painter );
painter->restore();
}
//! Update the cached information about the current style sheet
void QwtPlotAbstractCanvas::updateStyleSheetInfo()
{
QWidget* w = canvasWidget();
if ( !w->testAttribute( Qt::WA_StyledBackground ) )
return;
QwtStyleSheetRecorder recorder( w->size() );
QPainter painter( &recorder );
QStyleOption opt;
opt.initFrom(w);
w->style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, w);
painter.end();
m_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty();
m_data->styleSheet.cornerRects = recorder.clipRects;
if ( recorder.background.path.isEmpty() )
{
if ( !recorder.border.rectList.isEmpty() )
{
m_data->styleSheet.borderPath =
qwtCombinePathList( w->rect(), recorder.border.pathList );
}
}
else
{
m_data->styleSheet.borderPath = recorder.background.path;
m_data->styleSheet.background.brush = recorder.background.brush;
m_data->styleSheet.background.origin = recorder.background.origin;
}
}
//! \return canvas widget
QWidget* QwtPlotAbstractCanvas::canvasWidget()
{
return m_data->canvasWidget;
}
//! \return canvas widget
const QWidget* QwtPlotAbstractCanvas::canvasWidget() const
{
return m_data->canvasWidget;
}
class QwtPlotAbstractGLCanvas::PrivateData
{
public:
PrivateData():
frameStyle( QFrame::Panel | QFrame::Sunken),
lineWidth( 2 ),
midLineWidth( 0 )
{
}
QwtPlotAbstractGLCanvas::PaintAttributes paintAttributes;
int frameStyle;
int lineWidth;
int midLineWidth;
};
/*!
\brief Constructor
\param canvasWidget plot canvas widget
*/
QwtPlotAbstractGLCanvas::QwtPlotAbstractGLCanvas( QWidget* canvasWidget ):
QwtPlotAbstractCanvas( canvasWidget )
{
m_data = new PrivateData;
qwtUpdateContentsRect( frameWidth(), canvasWidget );
m_data->paintAttributes = QwtPlotAbstractGLCanvas::BackingStore;
}
//! Destructor
QwtPlotAbstractGLCanvas::~QwtPlotAbstractGLCanvas()
{
delete m_data;
}
/*!
\brief Changing the paint attributes
\param attribute Paint attribute
\param on On/Off
\sa testPaintAttribute()
*/
void QwtPlotAbstractGLCanvas::setPaintAttribute( PaintAttribute attribute, bool on )
{
if ( bool( m_data->paintAttributes & attribute ) == on )
return;
if ( on )
{
m_data->paintAttributes |= attribute;
}
else
{
m_data->paintAttributes &= ~attribute;
if ( attribute == BackingStore )
clearBackingStore();
}
}
/*!
Test whether a paint attribute is enabled
\param attribute Paint attribute
\return true, when attribute is enabled
\sa setPaintAttribute()
*/
bool QwtPlotAbstractGLCanvas::testPaintAttribute( PaintAttribute attribute ) const
{
return m_data->paintAttributes & attribute;
}
/*!
Set the frame style
\param style The bitwise OR between a shape and a shadow.
\sa frameStyle(), QFrame::setFrameStyle(),
setFrameShadow(), setFrameShape()
*/
void QwtPlotAbstractGLCanvas::setFrameStyle( int style )
{
if ( style != m_data->frameStyle )
{
m_data->frameStyle = style;
qwtUpdateContentsRect( frameWidth(), canvasWidget() );
canvasWidget()->update();
}
}
/*!
\return The bitwise OR between a frameShape() and a frameShadow()
\sa setFrameStyle(), QFrame::frameStyle()
*/
int QwtPlotAbstractGLCanvas::frameStyle() const
{
return m_data->frameStyle;
}
/*!
Set the frame shadow
\param shadow Frame shadow
\sa frameShadow(), setFrameShape(), QFrame::setFrameShadow()
*/
void QwtPlotAbstractGLCanvas::setFrameShadow( QFrame::Shadow shadow )
{
setFrameStyle( ( m_data->frameStyle & QFrame::Shape_Mask ) | shadow );
}
/*!
\return Frame shadow
\sa setFrameShadow(), QFrame::setFrameShadow()
*/
QFrame::Shadow QwtPlotAbstractGLCanvas::frameShadow() const
{
return (QFrame::Shadow) ( m_data->frameStyle & QFrame::Shadow_Mask );
}
/*!
Set the frame shape
\param shape Frame shape
\sa frameShape(), setFrameShadow(), QFrame::frameShape()
*/
void QwtPlotAbstractGLCanvas::setFrameShape( QFrame::Shape shape )
{
setFrameStyle( ( m_data->frameStyle & QFrame::Shadow_Mask ) | shape );
}
/*!
\return Frame shape
\sa setFrameShape(), QFrame::frameShape()
*/
QFrame::Shape QwtPlotAbstractGLCanvas::frameShape() const
{
return (QFrame::Shape) ( m_data->frameStyle & QFrame::Shape_Mask );
}
/*!
Set the frame line width
The default line width is 2 pixels.
\param width Line width of the frame
\sa lineWidth(), setMidLineWidth()
*/
void QwtPlotAbstractGLCanvas::setLineWidth( int width )
{
width = qMax( width, 0 );
if ( width != m_data->lineWidth )
{
m_data->lineWidth = qMax( width, 0 );
qwtUpdateContentsRect( frameWidth(), canvasWidget() );
canvasWidget()->update();
}
}
/*!
\return Line width of the frame
\sa setLineWidth(), midLineWidth()
*/
int QwtPlotAbstractGLCanvas::lineWidth() const
{
return m_data->lineWidth;
}
/*!
Set the frame mid line width
The default midline width is 0 pixels.
\param width Midline width of the frame
\sa midLineWidth(), setLineWidth()
*/
void QwtPlotAbstractGLCanvas::setMidLineWidth( int width )
{
width = qMax( width, 0 );
if ( width != m_data->midLineWidth )
{
m_data->midLineWidth = width;
qwtUpdateContentsRect( frameWidth(), canvasWidget() );
canvasWidget()->update();
}
}
/*!
\return Midline width of the frame
\sa setMidLineWidth(), lineWidth()
*/
int QwtPlotAbstractGLCanvas::midLineWidth() const
{
return m_data->midLineWidth;
}
/*!
\return Frame width depending on the style, line width and midline width.
*/
int QwtPlotAbstractGLCanvas::frameWidth() const
{
return ( frameStyle() != QFrame::NoFrame ) ? m_data->lineWidth : 0;
}
/*!
Invalidate the paint cache and repaint the canvas
\sa invalidatePaintCache()
*/
void QwtPlotAbstractGLCanvas::replot()
{
invalidateBackingStore();
QWidget* w = canvasWidget();
if ( testPaintAttribute( QwtPlotAbstractGLCanvas::ImmediatePaint ) )
w->repaint( w->contentsRect() );
else
w->update( w->contentsRect() );
}
//! \return The rectangle where the frame is drawn in.
QRect QwtPlotAbstractGLCanvas::frameRect() const
{
const int fw = frameWidth();
return canvasWidget()->contentsRect().adjusted( -fw, -fw, fw, fw );
}
//! Helper function for the derived plot canvas
void QwtPlotAbstractGLCanvas::draw( QPainter* painter )
{
#if FIX_GL_TRANSLATION
if ( painter->paintEngine()->type() == QPaintEngine::OpenGL2 )
{
// work around a translation bug of QPaintEngine::OpenGL2
painter->translate( 1, 1 );
}
#endif
if ( canvasWidget()->testAttribute( Qt::WA_StyledBackground ) )
drawStyled( painter, true );
else
drawUnstyled( painter );
if ( frameWidth() > 0 )
drawBorder( painter );
}