地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1105 lines
28 KiB

15 years ago
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* 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_canvas.h"
#include "qwt_painter.h"
#include "qwt_null_paintdevice.h"
#include "qwt_math.h"
#include "qwt_plot.h"
15 years ago
#include <qpainter.h>
#include <qstyle.h>
#include <qstyleoption.h>
#include <qpaintengine.h>
#include <qevent.h>
class QwtStyleSheetRecorder: public QwtNullPaintDevice
{
public:
QwtStyleSheetRecorder( const QSize &size ):
d_size( size )
{
}
virtual void updateState( const QPaintEngineState &state )
{
if ( state.state() & QPaintEngine::DirtyPen )
{
d_pen = state.pen();
}
if ( state.state() & QPaintEngine::DirtyBrush )
{
d_brush = state.brush();
}
if ( state.state() & QPaintEngine::DirtyBrushOrigin )
{
d_origin = state.brushOrigin();
}
}
virtual void drawRects(const QRectF *rects, int count )
{
for ( int i = 0; i < count; i++ )
border.rectList += rects[i];
}
virtual void drawPath( const QPainterPath &path )
{
const QRectF rect( QPointF( 0.0, 0.0 ), d_size );
if ( path.controlPointRect().contains( rect.center() ) )
{
setCornerRects( path );
alignCornerRects( rect );
background.path = path;
background.brush = d_brush;
background.origin = d_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(
qMin( r.left(), el.x ),
qMin( r.top(), el.y ),
qMax( r.right(), el.x ),
qMax( r.bottom(), el.y )
);
clipRects.last() = r.normalized();
}
break;
}
}
}
}
protected:
virtual QSize sizeMetrics() const
{
return d_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 d_size;
QPen d_pen;
QBrush d_brush;
QPointF d_origin;
};
static void qwtDrawBackground( QPainter *painter, QwtPlotCanvas *canvas )
{
painter->save();
const QPainterPath borderClip = canvas->borderPath( 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() )
{
QVector<QRect> rects;
if ( brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode )
{
rects += canvas->rect();
}
else
{
rects = painter->clipRegion().rects();
}
#if 1
bool useRaster = false;
if ( painter->paintEngine()->type() == QPaintEngine::X11 )
{
// Qt 4.7.1: gradients on X11 are broken ( subrects +
// QGradient::StretchToDeviceMode ) and horrible slow.
// As workaround we have to use the raster paintengine.
// Even if the QImage -> QPixmap translation is slow
// it is three times faster, than using X11 directly
useRaster = true;
}
15 years ago
#endif
if ( useRaster )
{
QImage::Format format = QImage::Format_RGB32;
const QGradientStops stops = brush.gradient()->stops();
for ( int i = 0; i < stops.size(); i++ )
{
if ( stops[i].second.alpha() != 255 )
{
// don't use Format_ARGB32_Premultiplied. It's
// recommended by the Qt docs, but QPainter::drawImage()
// is horrible slow on X11.
format = QImage::Format_ARGB32;
break;
}
}
QImage image( canvas->size(), format );
QPainter p( &image );
p.setPen( Qt::NoPen );
p.setBrush( brush );
p.drawRects( rects );
p.end();
painter->drawImage( 0, 0, image );
}
else
{
painter->setPen( Qt::NoPen );
painter->setBrush( brush );
painter->drawRects( rects );
}
}
else
{
painter->setPen( Qt::NoPen );
painter->setBrush( brush );
painter->drawRects( painter->clipRegion().rects() );
}
painter->restore();
}
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;
15 years ago
#endif
}
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, QwtPlotCanvas *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 QRectF r = canvas->rect();
const double radius = canvas->borderRadius();
if ( radius > 0.0 )
{
QSizeF sz( radius, radius );
rects += QRectF( r.topLeft(), sz );
rects += QRectF( r.topRight() - QPointF( radius, 0 ), sz );
rects += QRectF( r.bottomRight() - QPointF( radius, radius ), sz );
rects += QRectF( r.bottomLeft() - QPointF( 0, radius ), sz );
}
}
qwtFillBackground( painter, canvas, rects);
}
15 years ago
class QwtPlotCanvas::PrivateData
{
public:
PrivateData():
focusIndicator( NoFocusIndicator ),
borderRadius( 0 ),
paintAttributes( 0 ),
backingStore( NULL )
{
styleSheet.hasBorder = false;
15 years ago
}
~PrivateData()
{
delete backingStore;
15 years ago
}
FocusIndicator focusIndicator;
double borderRadius;
QwtPlotCanvas::PaintAttributes paintAttributes;
QPixmap *backingStore;
struct StyleSheet
{
bool hasBorder;
QPainterPath borderPath;
QVector<QRectF> cornerRects;
struct StyleSheetBackground
{
QBrush brush;
QPointF origin;
} background;
} styleSheet;
15 years ago
};
/*!
\brief Constructor
15 years ago
\param plot Parent plot widget
\sa QwtPlot::setCanvas()
*/
QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ):
QFrame( plot )
15 years ago
{
setFrameStyle( QFrame::Panel | QFrame::Sunken );
setLineWidth( 2 );
15 years ago
d_data = new PrivateData;
15 years ago
#ifndef QT_NO_CURSOR
setCursor( Qt::CrossCursor );
15 years ago
#endif
setAutoFillBackground( true );
setPaintAttribute( QwtPlotCanvas::BackingStore, true );
setPaintAttribute( QwtPlotCanvas::Opaque, true );
setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true );
15 years ago
}
//! Destructor
QwtPlotCanvas::~QwtPlotCanvas()
{
delete d_data;
}
//! Return parent plot widget
QwtPlot *QwtPlotCanvas::plot()
{
return qobject_cast<QwtPlot *>( parent() );
15 years ago
}
//! Return parent plot widget
const QwtPlot *QwtPlotCanvas::plot() const
{
return qobject_cast<const QwtPlot *>( parent() );
15 years ago
}
/*!
\brief Changing the paint attributes
\param attribute Paint attribute
\param on On/Off
\sa testPaintAttribute(), backingStore()
15 years ago
*/
void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on )
15 years ago
{
if ( bool( d_data->paintAttributes & attribute ) == on )
15 years ago
return;
if ( on )
d_data->paintAttributes |= attribute;
else
d_data->paintAttributes &= ~attribute;
switch ( attribute )
{
case BackingStore:
{
if ( on )
{
if ( d_data->backingStore == NULL )
d_data->backingStore = new QPixmap();
if ( isVisible() )
{
#if QT_VERSION >= 0x050000
*d_data->backingStore = grab( rect() );
#else
*d_data->backingStore =
QPixmap::grabWidget( this, rect() );
#endif
}
}
else
{
delete d_data->backingStore;
d_data->backingStore = NULL;
}
break;
15 years ago
}
case Opaque:
{
if ( on )
setAttribute( Qt::WA_OpaquePaintEvent, true );
break;
}
case HackStyledBackground:
case ImmediatePaint:
{
break;
}
15 years ago
}
}
/*!
Test whether a paint attribute is enabled
15 years ago
\param attribute Paint attribute
\return true, when attribute is enabled
15 years ago
\sa setPaintAttribute()
*/
bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const
15 years ago
{
return d_data->paintAttributes & attribute;
15 years ago
}
//! \return Backing store, might be null
const QPixmap *QwtPlotCanvas::backingStore() const
15 years ago
{
return d_data->backingStore;
15 years ago
}
//! Invalidate the internal backing store
void QwtPlotCanvas::invalidateBackingStore()
15 years ago
{
if ( d_data->backingStore )
*d_data->backingStore = QPixmap();
15 years ago
}
/*!
Set the focus indicator
\sa FocusIndicator, focusIndicator()
15 years ago
*/
void QwtPlotCanvas::setFocusIndicator( FocusIndicator focusIndicator )
15 years ago
{
d_data->focusIndicator = focusIndicator;
}
/*!
\return Focus indicator
\sa FocusIndicator, setFocusIndicator()
15 years ago
*/
QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const
{
return d_data->focusIndicator;
}
/*!
Set the radius for the corners of the border frame
\param radius Radius of a rounded corner
\sa borderRadius()
*/
void QwtPlotCanvas::setBorderRadius( double radius )
15 years ago
{
d_data->borderRadius = qMax( 0.0, radius );
}
/*!
\return Radius for the corners of the border frame
\sa setBorderRadius()
*/
double QwtPlotCanvas::borderRadius() const
{
return d_data->borderRadius;
}
15 years ago
/*!
Qt event handler for QEvent::PolishRequest and QEvent::StyleChange
15 years ago
\param event Qt Event
\return See QFrame::event()
*/
bool QwtPlotCanvas::event( QEvent *event )
{
if ( event->type() == QEvent::PolishRequest )
{
if ( testPaintAttribute( QwtPlotCanvas::Opaque ) )
{
// Setting a style sheet changes the
// Qt::WA_OpaquePaintEvent attribute, but we insist
// on painting the background.
setAttribute( Qt::WA_OpaquePaintEvent, true );
}
15 years ago
}
if ( event->type() == QEvent::PolishRequest ||
event->type() == QEvent::StyleChange )
{
updateStyleSheetInfo();
}
return QFrame::event( event );
15 years ago
}
/*!
Paint event
\param event Paint event
*/
void QwtPlotCanvas::paintEvent( QPaintEvent *event )
15 years ago
{
QPainter painter( this );
painter.setClipRegion( event->region() );
if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) &&
d_data->backingStore != NULL )
{
QPixmap &bs = *d_data->backingStore;
if ( bs.size() != size() )
{
bs = QwtPainter::backingStore( this, size() );
if ( testAttribute(Qt::WA_StyledBackground) )
{
QPainter p( &bs );
qwtFillBackground( &p, this );
drawCanvas( &p, true );
}
else
{
QPainter p;
if ( d_data->borderRadius <= 0.0 )
{
QwtPainter::fillPixmap( this, bs );
p.begin( &bs );
drawCanvas( &p, false );
}
else
{
p.begin( &bs );
qwtFillBackground( &p, this );
drawCanvas( &p, true );
}
if ( frameWidth() > 0 )
drawBorder( &p );
}
}
painter.drawPixmap( 0, 0, *d_data->backingStore );
15 years ago
}
else
{
if ( testAttribute(Qt::WA_StyledBackground ) )
{
if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
{
qwtFillBackground( &painter, this );
drawCanvas( &painter, true );
}
else
{
drawCanvas( &painter, false );
}
}
else
{
if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
{
if ( autoFillBackground() )
{
qwtFillBackground( &painter, this );
qwtDrawBackground( &painter, this );
}
}
else
{
if ( borderRadius() > 0.0 )
{
QPainterPath clipPath;
clipPath.addRect( rect() );
clipPath = clipPath.subtracted( borderPath( rect() ) );
painter.save();
painter.setClipPath( clipPath, Qt::IntersectClip );
qwtFillBackground( &painter, this );
qwtDrawBackground( &painter, this );
painter.restore();
}
}
15 years ago
drawCanvas( &painter, false );
15 years ago
if ( frameWidth() > 0 )
drawBorder( &painter );
}
}
15 years ago
if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
drawFocusIndicator( &painter );
15 years ago
}
void QwtPlotCanvas::drawCanvas( QPainter *painter, bool withBackground )
15 years ago
{
bool hackStyledBackground = false;
if ( withBackground && testAttribute( Qt::WA_StyledBackground )
&& testPaintAttribute( 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 anialiased 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 ( d_data->styleSheet.hasBorder &&
!d_data->styleSheet.borderPath.isEmpty() )
{
// We have a border with at least one rounded corner
hackStyledBackground = true;
}
}
15 years ago
if ( withBackground )
{
painter->save();
15 years ago
if ( testAttribute( Qt::WA_StyledBackground ) )
{
if ( hackStyledBackground )
{
// paint background without border
painter->setPen( Qt::NoPen );
painter->setBrush( d_data->styleSheet.background.brush );
painter->setBrushOrigin( d_data->styleSheet.background.origin );
painter->setClipPath( d_data->styleSheet.borderPath );
painter->drawRect( contentsRect() );
}
else
{
qwtDrawStyledBackground( this, painter );
}
}
else if ( autoFillBackground() )
{
painter->setPen( Qt::NoPen );
painter->setBrush( palette().brush( backgroundRole() ) );
if ( d_data->borderRadius > 0.0 && ( rect() == frameRect() ) )
{
if ( frameWidth() > 0 )
{
painter->setClipPath( borderPath( rect() ) );
painter->drawRect( rect() );
}
else
{
painter->setRenderHint( QPainter::Antialiasing, true );
painter->drawPath( borderPath( rect() ) );
}
}
else
{
painter->drawRect( rect() );
}
}
painter->restore();
15 years ago
}
painter->save();
if ( !d_data->styleSheet.borderPath.isEmpty() )
{
painter->setClipPath(
d_data->styleSheet.borderPath, Qt::IntersectClip );
}
else
{
if ( d_data->borderRadius > 0.0 )
painter->setClipPath( borderPath( frameRect() ), Qt::IntersectClip );
else
painter->setClipRect( contentsRect(), Qt::IntersectClip );
}
plot()->drawCanvas( painter );
painter->restore();
if ( withBackground && hackStyledBackground )
{
// Now paint the border on top
QStyleOptionFrame opt;
opt.initFrom(this);
style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, this);
}
15 years ago
}
/*!
Draw the border of the plot canvas
15 years ago
\param painter Painter
\sa setBorderRadius()
15 years ago
*/
void QwtPlotCanvas::drawBorder( QPainter *painter )
15 years ago
{
if ( d_data->borderRadius > 0 )
{
if ( frameWidth() > 0 )
{
QwtPainter::drawRoundedFrame( painter, QRectF( frameRect() ),
d_data->borderRadius, d_data->borderRadius,
palette(), frameWidth(), frameStyle() );
}
}
else
{
#if QT_VERSION >= 0x040500
8 years ago
#if !defined(_MSC_VER)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
QStyleOptionFrameV3 opt;
8 years ago
#if !defined(_MSC_VER)
#pragma GCC diagnostic pop
#endif
opt.init(this);
15 years ago
int frameShape = frameStyle() & QFrame::Shape_Mask;
int frameShadow = frameStyle() & QFrame::Shadow_Mask;
opt.frameShape = QFrame::Shape( int( opt.frameShape ) | frameShape );
#if 0
opt.rect = frameRect();
15 years ago
#endif
switch (frameShape)
{
case QFrame::Box:
case QFrame::HLine:
case QFrame::VLine:
case QFrame::StyledPanel:
case QFrame::Panel:
{
opt.lineWidth = lineWidth();
opt.midLineWidth = midLineWidth();
break;
}
default:
{
opt.lineWidth = frameWidth();
break;
}
}
if ( frameShadow == Sunken )
opt.state |= QStyle::State_Sunken;
else if ( frameShadow == Raised )
opt.state |= QStyle::State_Raised;
15 years ago
style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, this);
15 years ago
#else
drawFrame( painter );
15 years ago
#endif
}
}
15 years ago
/*!
Resize event
\param event Resize event
*/
void QwtPlotCanvas::resizeEvent( QResizeEvent *event )
{
QFrame::resizeEvent( event );
updateStyleSheetInfo();
}
15 years ago
/*!
Draw the focus indication
\param painter Painter
*/
void QwtPlotCanvas::drawFocusIndicator( QPainter *painter )
{
const int margin = 1;
15 years ago
QRect focusRect = contentsRect();
focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
15 years ago
QwtPainter::drawFocusRect( painter, this, focusRect );
}
15 years ago
/*!
Invalidate the paint cache and repaint the canvas
\sa invalidatePaintCache()
*/
void QwtPlotCanvas::replot()
{
invalidateBackingStore();
15 years ago
if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) )
repaint( contentsRect() );
else
update( contentsRect() );
}
15 years ago
//! Update the cached information about the current style sheet
void QwtPlotCanvas::updateStyleSheetInfo()
{
if ( !testAttribute(Qt::WA_StyledBackground ) )
return;
15 years ago
QwtStyleSheetRecorder recorder( size() );
QPainter painter( &recorder );
QStyleOption opt;
opt.initFrom(this);
style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this);
painter.end();
d_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty();
d_data->styleSheet.cornerRects = recorder.clipRects;
if ( recorder.background.path.isEmpty() )
{
if ( !recorder.border.rectList.isEmpty() )
{
d_data->styleSheet.borderPath =
qwtCombinePathList( rect(), recorder.border.pathList );
15 years ago
}
}
else
{
d_data->styleSheet.borderPath = recorder.background.path;
d_data->styleSheet.background.brush = recorder.background.brush;
d_data->styleSheet.background.origin = recorder.background.origin;
15 years ago
}
}
/*!
Calculate the painter path for a styled or rounded border
When the canvas has no styled background or rounded borders
the painter path is empty.
\param rect Bounding rectangle of the canvas
\return Painter path, that can be used for clipping
*/
QPainterPath QwtPlotCanvas::borderPath( const QRect &rect ) const
15 years ago
{
if ( testAttribute(Qt::WA_StyledBackground ) )
{
QwtStyleSheetRecorder recorder( rect.size() );
15 years ago
QPainter painter( &recorder );
15 years ago
QStyleOption opt;
opt.initFrom(this);
opt.rect = rect;
style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this);
15 years ago
painter.end();
if ( !recorder.background.path.isEmpty() )
return recorder.background.path;
if ( !recorder.border.rectList.isEmpty() )
return qwtCombinePathList( rect, recorder.border.pathList );
15 years ago
}
else if ( d_data->borderRadius > 0.0 )
{
double fw2 = frameWidth() * 0.5;
QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 );
QPainterPath path;
path.addRoundedRect( r, d_data->borderRadius, d_data->borderRadius );
return path;
}
return QPainterPath();
15 years ago
}