qwt_plot_canvas.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_plot_canvas.h"
00011 #include "qwt_painter.h"
00012 #include "qwt_null_paintdevice.h"
00013 #include "qwt_math.h"
00014 #include "qwt_plot.h"
00015 #include <qpainter.h>
00016 #include <qstyle.h>
00017 #include <qstyleoption.h>
00018 #include <qpaintengine.h>
00019 #include <qevent.h>
00020 
00021 class QwtStyleSheetRecorder: public QwtNullPaintDevice
00022 {
00023 public:
00024     QwtStyleSheetRecorder( const QSize &size ):
00025         d_size( size )
00026     {
00027     }
00028 
00029     virtual void updateState( const QPaintEngineState &state )
00030     {
00031         if ( state.state() & QPaintEngine::DirtyPen )
00032         {
00033             d_pen = state.pen();
00034         }
00035         if ( state.state() & QPaintEngine::DirtyBrush )
00036         {
00037             d_brush = state.brush();
00038         }
00039         if ( state.state() & QPaintEngine::DirtyBrushOrigin )
00040         {
00041             d_origin = state.brushOrigin();
00042         }
00043     }
00044 
00045     virtual void drawRects(const QRectF *rects, int count )
00046     {
00047         for ( int i = 0; i < count; i++ )
00048             border.rectList += rects[i];
00049     }
00050 
00051     virtual void drawPath( const QPainterPath &path )
00052     {
00053         const QRectF rect( QPointF( 0.0, 0.0 ), d_size );
00054         if ( path.controlPointRect().contains( rect.center() ) )
00055         {
00056             setCornerRects( path );
00057             alignCornerRects( rect );
00058 
00059             background.path = path;
00060             background.brush = d_brush;
00061             background.origin = d_origin;
00062         }
00063         else
00064         {
00065             border.pathList += path;
00066         }
00067     }
00068 
00069     void setCornerRects( const QPainterPath &path )
00070     {
00071         QPointF pos( 0.0, 0.0 );
00072 
00073         for ( int i = 0; i < path.elementCount(); i++ )
00074         {
00075             QPainterPath::Element el = path.elementAt(i); 
00076             switch( el.type )
00077             {
00078                 case QPainterPath::MoveToElement:
00079                 case QPainterPath::LineToElement:
00080                 {
00081                     pos.setX( el.x );
00082                     pos.setY( el.y );
00083                     break;
00084                 }
00085                 case QPainterPath::CurveToElement:
00086                 {
00087                     QRectF r( pos, QPointF( el.x, el.y ) );
00088                     clipRects += r.normalized();
00089 
00090                     pos.setX( el.x );
00091                     pos.setY( el.y );
00092 
00093                     break;
00094                 }
00095                 case QPainterPath::CurveToDataElement:
00096                 {
00097                     if ( clipRects.size() > 0 )
00098                     {
00099                         QRectF r = clipRects.last();
00100                         r.setCoords( 
00101                             qMin( r.left(), el.x ),
00102                             qMin( r.top(), el.y ),
00103                             qMax( r.right(), el.x ),
00104                             qMax( r.bottom(), el.y )
00105                         );
00106                         clipRects.last() = r.normalized();
00107                     }
00108                     break;
00109                 }
00110             }
00111         }
00112     }
00113 
00114 protected:
00115     virtual QSize sizeMetrics() const
00116     {
00117         return d_size;
00118     }
00119 
00120 private:
00121     void alignCornerRects( const QRectF &rect )
00122     {
00123         for ( int i = 0; i < clipRects.size(); i++ )
00124         {
00125             QRectF &r = clipRects[i];
00126             if ( r.center().x() < rect.center().x() )
00127                 r.setLeft( rect.left() );
00128             else
00129                 r.setRight( rect.right() );
00130 
00131             if ( r.center().y() < rect.center().y() )
00132                 r.setTop( rect.top() );
00133             else
00134                 r.setBottom( rect.bottom() );
00135         }
00136     }
00137 
00138 
00139 public:
00140     QVector<QRectF> clipRects;
00141 
00142     struct Border
00143     {
00144         QList<QPainterPath> pathList;
00145         QList<QRectF> rectList;
00146         QRegion clipRegion;
00147     } border;
00148 
00149     struct Background
00150     {
00151         QPainterPath path;
00152         QBrush brush;
00153         QPointF origin;
00154     } background;
00155 
00156 private:
00157     const QSize d_size;
00158 
00159     QPen d_pen;
00160     QBrush d_brush;
00161     QPointF d_origin;
00162 };
00163 
00164 static void qwtDrawBackground( QPainter *painter, QwtPlotCanvas *canvas )
00165 {
00166     painter->save();
00167 
00168     const QPainterPath borderClip = canvas->borderPath( canvas->rect() );
00169     if ( !borderClip.isEmpty() )
00170         painter->setClipPath( borderClip, Qt::IntersectClip );
00171 
00172     const QBrush &brush = 
00173         canvas->palette().brush( canvas->backgroundRole() );
00174 
00175     if ( brush.style() == Qt::TexturePattern )
00176     {
00177         QPixmap pm( canvas->size() );
00178         QwtPainter::fillPixmap( canvas, pm );
00179         painter->drawPixmap( 0, 0, pm );
00180     }
00181     else if ( brush.gradient() )
00182     {
00183         QVector<QRect> rects;
00184 
00185         if ( brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode )
00186         {
00187             rects += canvas->rect();
00188         } 
00189         else 
00190         {
00191             rects = painter->clipRegion().rects();
00192         }
00193 
00194 #if 1
00195         bool useRaster = false;
00196 
00197         if ( painter->paintEngine()->type() == QPaintEngine::X11 )
00198         {
00199             // Qt 4.7.1: gradients on X11 are broken ( subrects + 
00200             // QGradient::StretchToDeviceMode ) and horrible slow.
00201             // As workaround we have to use the raster paintengine.
00202             // Even if the QImage -> QPixmap translation is slow
00203             // it is three times faster, than using X11 directly
00204 
00205             useRaster = true;
00206         }
00207 #endif
00208         if ( useRaster )
00209         {
00210             QImage::Format format = QImage::Format_RGB32;
00211 
00212             const QGradientStops stops = brush.gradient()->stops();
00213             for ( int i = 0; i < stops.size(); i++ )
00214             {
00215                 if ( stops[i].second.alpha() != 255 )
00216                 {
00217                     // don't use Format_ARGB32_Premultiplied. It's
00218                     // recommended by the Qt docs, but QPainter::drawImage()
00219                     // is horrible slow on X11.
00220 
00221                     format = QImage::Format_ARGB32;
00222                     break;
00223                 }
00224             }
00225             
00226             QImage image( canvas->size(), format );
00227 
00228             QPainter p( &image );
00229             p.setPen( Qt::NoPen );
00230             p.setBrush( brush );
00231 
00232             p.drawRects( rects );
00233 
00234             p.end();
00235 
00236             painter->drawImage( 0, 0, image );
00237         }
00238         else
00239         {
00240             painter->setPen( Qt::NoPen );
00241             painter->setBrush( brush );
00242 
00243             painter->drawRects( rects );
00244         }
00245     }
00246     else
00247     {
00248         painter->setPen( Qt::NoPen );
00249         painter->setBrush( brush );
00250 
00251         painter->drawRects( painter->clipRegion().rects() );
00252 
00253     }
00254 
00255     painter->restore();
00256 }
00257 
00258 static inline void qwtRevertPath( QPainterPath &path )
00259 {
00260     if ( path.elementCount() == 4 )
00261     {
00262         QPainterPath::Element el0 = path.elementAt(0);
00263         QPainterPath::Element el3 = path.elementAt(3);
00264 
00265         path.setElementPositionAt( 0, el3.x, el3.y );
00266         path.setElementPositionAt( 3, el0.x, el0.y );
00267     }
00268 }
00269 
00270 static QPainterPath qwtCombinePathList( const QRectF &rect, 
00271     const QList<QPainterPath> &pathList )
00272 {
00273     if ( pathList.isEmpty() )
00274         return QPainterPath();
00275 
00276     QPainterPath ordered[8]; // starting top left
00277 
00278     for ( int i = 0; i < pathList.size(); i++ )
00279     {
00280         int index = -1;
00281         QPainterPath subPath = pathList[i];
00282 
00283         const QRectF br = pathList[i].controlPointRect();
00284         if ( br.center().x() < rect.center().x() )
00285         {
00286             if ( br.center().y() < rect.center().y() )
00287             {
00288                 if ( qAbs( br.top() - rect.top() ) < 
00289                     qAbs( br.left() - rect.left() ) )
00290                 {
00291                     index = 1;
00292                 }
00293                 else
00294                 {
00295                     index = 0;
00296                 }
00297             }
00298             else
00299             {
00300                 if ( qAbs( br.bottom() - rect.bottom() ) < 
00301                     qAbs( br.left() - rect.left() ) )
00302                 {
00303                     index = 6;
00304                 }
00305                 else
00306                 {
00307                     index = 7;
00308                 }
00309             }
00310 
00311             if ( subPath.currentPosition().y() > br.center().y() )
00312                 qwtRevertPath( subPath );
00313         }
00314         else
00315         {
00316             if ( br.center().y() < rect.center().y() )
00317             {
00318                 if ( qAbs( br.top() - rect.top() ) < 
00319                     qAbs( br.right() - rect.right() ) )
00320                 {
00321                     index = 2;
00322                 }
00323                 else
00324                 {
00325                     index = 3;
00326                 }
00327             }
00328             else
00329             {
00330                 if ( qAbs( br.bottom() - rect.bottom() ) < 
00331                     qAbs( br.right() - rect.right() ) )
00332                 {
00333                     index = 5;
00334                 }
00335                 else
00336                 {
00337                     index = 4;
00338                 }
00339             }
00340             if ( subPath.currentPosition().y() < br.center().y() )
00341                 qwtRevertPath( subPath );
00342         }   
00343         ordered[index] = subPath;
00344     }
00345 
00346     for ( int i = 0; i < 4; i++ )
00347     {
00348         if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() )
00349         {
00350             // we don't accept incomplete rounded borders
00351             return QPainterPath();
00352         }
00353     }
00354 
00355 
00356     const QPolygonF corners( rect );
00357 
00358     QPainterPath path;
00359     //path.moveTo( rect.topLeft() );
00360 
00361     for ( int i = 0; i < 4; i++ )
00362     {
00363         if ( ordered[2 * i].isEmpty() )
00364         {
00365             path.lineTo( corners[i] );
00366         }
00367         else
00368         {
00369             path.connectPath( ordered[2 * i] );
00370             path.connectPath( ordered[2 * i + 1] );
00371         }
00372     }
00373 
00374     path.closeSubpath();
00375 
00376 #if 0
00377     return path.simplified();
00378 #else
00379     return path;
00380 #endif
00381 }
00382 
00383 static inline void qwtDrawStyledBackground( 
00384     QWidget *w, QPainter *painter )
00385 {
00386     QStyleOption opt;
00387     opt.initFrom(w);
00388     w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
00389 }
00390 
00391 static QWidget *qwtBackgroundWidget( QWidget *w )
00392 {
00393     if ( w->parentWidget() == NULL )
00394         return w;
00395 
00396     if ( w->autoFillBackground() )
00397     {
00398         const QBrush brush = w->palette().brush( w->backgroundRole() );
00399         if ( brush.color().alpha() > 0 )
00400             return w;
00401     }
00402 
00403     if ( w->testAttribute( Qt::WA_StyledBackground ) )
00404     {
00405         QImage image( 1, 1, QImage::Format_ARGB32 );
00406         image.fill( Qt::transparent );
00407 
00408         QPainter painter( &image );
00409         painter.translate( -w->rect().center() );
00410         qwtDrawStyledBackground( w, &painter );
00411         painter.end();
00412 
00413         if ( qAlpha( image.pixel( 0, 0 ) ) != 0 )
00414             return w;
00415     }
00416 
00417     return qwtBackgroundWidget( w->parentWidget() );
00418 }
00419 
00420 static void qwtFillBackground( QPainter *painter, 
00421     QWidget *widget, const QVector<QRectF> &fillRects )
00422 {
00423     if ( fillRects.isEmpty() )
00424         return;
00425 
00426     QRegion clipRegion;
00427     if ( painter->hasClipping() )
00428         clipRegion = painter->transform().map( painter->clipRegion() );
00429     else
00430         clipRegion = widget->contentsRect();
00431 
00432     // Try to find out which widget fills
00433     // the unfilled areas of the styled background
00434 
00435     QWidget *bgWidget = qwtBackgroundWidget( widget->parentWidget() );
00436 
00437     for ( int i = 0; i < fillRects.size(); i++ )
00438     {
00439         const QRect rect = fillRects[i].toAlignedRect();
00440         if ( clipRegion.intersects( rect ) )
00441         {
00442             QPixmap pm( rect.size() );
00443             QwtPainter::fillPixmap( bgWidget, pm, widget->mapTo( bgWidget, rect.topLeft() ) );
00444             painter->drawPixmap( rect, pm );
00445         }
00446     }
00447 }
00448 
00449 static void qwtFillBackground( QPainter *painter, QwtPlotCanvas *canvas )
00450 {
00451     QVector<QRectF> rects;
00452 
00453     if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
00454     {
00455         QwtStyleSheetRecorder recorder( canvas->size() );
00456 
00457         QPainter p( &recorder );
00458         qwtDrawStyledBackground( canvas, &p );
00459         p.end();
00460 
00461         if ( recorder.background.brush.isOpaque() )
00462             rects = recorder.clipRects;
00463         else
00464             rects += canvas->rect();
00465     }
00466     else
00467     {
00468         const QRectF r = canvas->rect();
00469         const double radius = canvas->borderRadius();
00470         if ( radius > 0.0 )
00471         {
00472             QSizeF sz( radius, radius );
00473 
00474             rects += QRectF( r.topLeft(), sz );
00475             rects += QRectF( r.topRight() - QPointF( radius, 0 ), sz );
00476             rects += QRectF( r.bottomRight() - QPointF( radius, radius ), sz );
00477             rects += QRectF( r.bottomLeft() - QPointF( 0, radius ), sz );
00478         }
00479     }
00480 
00481     qwtFillBackground( painter, canvas, rects);
00482 }
00483 
00484 
00485 class QwtPlotCanvas::PrivateData
00486 {
00487 public:
00488     PrivateData():
00489         focusIndicator( NoFocusIndicator ),
00490         borderRadius( 0 ),
00491         paintAttributes( 0 ),
00492         backingStore( NULL )
00493     {
00494         styleSheet.hasBorder = false;
00495     }
00496 
00497     ~PrivateData()
00498     {
00499         delete backingStore;
00500     }
00501 
00502     FocusIndicator focusIndicator;
00503     double borderRadius;
00504     QwtPlotCanvas::PaintAttributes paintAttributes;
00505     QPixmap *backingStore;
00506 
00507     struct StyleSheet
00508     {
00509         bool hasBorder;
00510         QPainterPath borderPath;
00511         QVector<QRectF> cornerRects;
00512 
00513         struct StyleSheetBackground
00514         {
00515             QBrush brush;
00516             QPointF origin;
00517         } background;
00518 
00519     } styleSheet;
00520 
00521 };
00522 
00529 QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ):
00530     QFrame( plot )
00531 {
00532     setFrameStyle( QFrame::Panel | QFrame::Sunken );
00533     setLineWidth( 2 );
00534 
00535     d_data = new PrivateData;
00536 
00537 #ifndef QT_NO_CURSOR
00538     setCursor( Qt::CrossCursor );
00539 #endif
00540 
00541     setAutoFillBackground( true );
00542     setPaintAttribute( QwtPlotCanvas::BackingStore, true );
00543     setPaintAttribute( QwtPlotCanvas::Opaque, true );
00544     setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true );
00545 }
00546 
00548 QwtPlotCanvas::~QwtPlotCanvas()
00549 {
00550     delete d_data;
00551 }
00552 
00554 QwtPlot *QwtPlotCanvas::plot()
00555 {
00556     return qobject_cast<QwtPlot *>( parent() );
00557 }
00558 
00560 const QwtPlot *QwtPlotCanvas::plot() const
00561 {
00562     return qobject_cast<const QwtPlot *>( parent() );
00563 }
00564 
00573 void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on )
00574 {
00575     if ( bool( d_data->paintAttributes & attribute ) == on )
00576         return;
00577 
00578     if ( on )
00579         d_data->paintAttributes |= attribute;
00580     else
00581         d_data->paintAttributes &= ~attribute;
00582 
00583     switch ( attribute )
00584     {
00585         case BackingStore:
00586         {
00587             if ( on )
00588             {
00589                 if ( d_data->backingStore == NULL )
00590                     d_data->backingStore = new QPixmap();
00591 
00592                 if ( isVisible() )
00593                 {
00594 #if QT_VERSION >= 0x050000
00595                     *d_data->backingStore = grab( rect() );
00596 #else
00597                     *d_data->backingStore = 
00598                         QPixmap::grabWidget( this, rect() );
00599 #endif
00600                 }
00601             }
00602             else
00603             {
00604                 delete d_data->backingStore;
00605                 d_data->backingStore = NULL;
00606             }
00607             break;
00608         }
00609         case Opaque:
00610         {
00611             if ( on )
00612                 setAttribute( Qt::WA_OpaquePaintEvent, true );
00613 
00614             break;
00615         }
00616         case HackStyledBackground:
00617         case ImmediatePaint:
00618         {
00619             break;
00620         }
00621     }
00622 }
00623 
00631 bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const
00632 {
00633     return d_data->paintAttributes & attribute;
00634 }
00635 
00637 const QPixmap *QwtPlotCanvas::backingStore() const
00638 {
00639     return d_data->backingStore;
00640 }
00641 
00643 void QwtPlotCanvas::invalidateBackingStore()
00644 {
00645     if ( d_data->backingStore )
00646         *d_data->backingStore = QPixmap();
00647 }
00648 
00654 void QwtPlotCanvas::setFocusIndicator( FocusIndicator focusIndicator )
00655 {
00656     d_data->focusIndicator = focusIndicator;
00657 }
00658 
00664 QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const
00665 {
00666     return d_data->focusIndicator;
00667 }
00668 
00675 void QwtPlotCanvas::setBorderRadius( double radius )
00676 {
00677     d_data->borderRadius = qMax( 0.0, radius );
00678 }
00679 
00684 double QwtPlotCanvas::borderRadius() const
00685 {
00686     return d_data->borderRadius;
00687 }
00688 
00695 bool QwtPlotCanvas::event( QEvent *event )
00696 {
00697     if ( event->type() == QEvent::PolishRequest ) 
00698     {
00699         if ( testPaintAttribute( QwtPlotCanvas::Opaque ) )
00700         {
00701             // Setting a style sheet changes the 
00702             // Qt::WA_OpaquePaintEvent attribute, but we insist
00703             // on painting the background.
00704             
00705             setAttribute( Qt::WA_OpaquePaintEvent, true );
00706         }
00707     }
00708 
00709     if ( event->type() == QEvent::PolishRequest || 
00710         event->type() == QEvent::StyleChange )
00711     {
00712         updateStyleSheetInfo();
00713     }
00714 
00715     return QFrame::event( event );
00716 }
00717 
00722 void QwtPlotCanvas::paintEvent( QPaintEvent *event )
00723 {
00724     QPainter painter( this );
00725     painter.setClipRegion( event->region() );
00726 
00727     if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) &&
00728         d_data->backingStore != NULL )
00729     {
00730         QPixmap &bs = *d_data->backingStore;
00731         if ( bs.size() != size() )
00732         {
00733             bs = QwtPainter::backingStore( this, size() );
00734 
00735             if ( testAttribute(Qt::WA_StyledBackground) )
00736             {
00737                 QPainter p( &bs );
00738                 qwtFillBackground( &p, this );
00739                 drawCanvas( &p, true );
00740             }
00741             else
00742             {
00743                 QPainter p;
00744                 if ( d_data->borderRadius <= 0.0 )
00745                 {
00746                     QwtPainter::fillPixmap( this, bs );
00747                     p.begin( &bs );
00748                     drawCanvas( &p, false );
00749                 }
00750                 else
00751                 {
00752                     p.begin( &bs );
00753                     qwtFillBackground( &p, this );
00754                     drawCanvas( &p, true );
00755                 }
00756 
00757                 if ( frameWidth() > 0 )
00758                     drawBorder( &p );
00759             }
00760         }
00761 
00762         painter.drawPixmap( 0, 0, *d_data->backingStore );
00763     }
00764     else
00765     {
00766         if ( testAttribute(Qt::WA_StyledBackground ) )
00767         {
00768             if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
00769             {
00770                 qwtFillBackground( &painter, this );
00771                 drawCanvas( &painter, true );
00772             }
00773             else
00774             {
00775                 drawCanvas( &painter, false );
00776             }
00777         }
00778         else
00779         {
00780             if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
00781             {
00782                 if ( autoFillBackground() )
00783                 {
00784                     qwtFillBackground( &painter, this );
00785                     qwtDrawBackground( &painter, this );
00786                 }
00787             }
00788             else
00789             {
00790                 if ( borderRadius() > 0.0 )
00791                 {
00792                     QPainterPath clipPath;
00793                     clipPath.addRect( rect() );
00794                     clipPath = clipPath.subtracted( borderPath( rect() ) );
00795 
00796                     painter.save();
00797 
00798                     painter.setClipPath( clipPath, Qt::IntersectClip );
00799                     qwtFillBackground( &painter, this );
00800                     qwtDrawBackground( &painter, this );
00801 
00802                     painter.restore();
00803                 }
00804             }
00805 
00806             drawCanvas( &painter, false );
00807 
00808             if ( frameWidth() > 0 ) 
00809                 drawBorder( &painter );
00810         }
00811     }
00812 
00813     if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
00814         drawFocusIndicator( &painter );
00815 }
00816 
00817 void QwtPlotCanvas::drawCanvas( QPainter *painter, bool withBackground ) 
00818 {
00819     bool hackStyledBackground = false;
00820 
00821     if ( withBackground && testAttribute( Qt::WA_StyledBackground ) 
00822         && testPaintAttribute( HackStyledBackground ) )
00823     {
00824         // Antialiasing rounded borders is done by
00825         // inserting pixels with colors between the 
00826         // border color and the color on the canvas,
00827         // When the border is painted before the plot items
00828         // these colors are interpolated for the canvas
00829         // and the plot items need to be clipped excluding
00830         // the anialiased pixels. In situations, where
00831         // the plot items fill the area at the rounded
00832         // borders this is noticeable.
00833         // The only way to avoid these annoying "artefacts"
00834         // is to paint the border on top of the plot items.
00835 
00836         if ( d_data->styleSheet.hasBorder &&
00837             !d_data->styleSheet.borderPath.isEmpty() )
00838         {
00839             // We have a border with at least one rounded corner
00840             hackStyledBackground = true;
00841         }
00842     }
00843 
00844     if ( withBackground )
00845     {
00846         painter->save();
00847 
00848         if ( testAttribute( Qt::WA_StyledBackground ) )
00849         {
00850             if ( hackStyledBackground )
00851             {
00852                 // paint background without border
00853 
00854                 painter->setPen( Qt::NoPen );
00855                 painter->setBrush( d_data->styleSheet.background.brush ); 
00856                 painter->setBrushOrigin( d_data->styleSheet.background.origin );
00857                 painter->setClipPath( d_data->styleSheet.borderPath );
00858                 painter->drawRect( contentsRect() );
00859             }
00860             else
00861             {
00862                 qwtDrawStyledBackground( this, painter );
00863             }
00864         }
00865         else if ( autoFillBackground() )
00866         {
00867             painter->setPen( Qt::NoPen );
00868             painter->setBrush( palette().brush( backgroundRole() ) );
00869 
00870             if ( d_data->borderRadius > 0.0 && ( rect() == frameRect() ) )
00871             {
00872                 if ( frameWidth() > 0 )
00873                 {
00874                     painter->setClipPath( borderPath( rect() ) );
00875                     painter->drawRect( rect() );
00876                 }
00877                 else
00878                 {
00879                     painter->setRenderHint( QPainter::Antialiasing, true );
00880                     painter->drawPath( borderPath( rect() ) );
00881                 }
00882             }
00883             else
00884             {
00885                 painter->drawRect( rect() );
00886             }
00887         }
00888 
00889         painter->restore();
00890     }
00891 
00892     painter->save();
00893 
00894     if ( !d_data->styleSheet.borderPath.isEmpty() )
00895     {
00896         painter->setClipPath( 
00897             d_data->styleSheet.borderPath, Qt::IntersectClip );
00898     }
00899     else
00900     {
00901         if ( d_data->borderRadius > 0.0 )
00902             painter->setClipPath( borderPath( frameRect() ), Qt::IntersectClip );
00903         else
00904             painter->setClipRect( contentsRect(), Qt::IntersectClip );
00905     }
00906 
00907     plot()->drawCanvas( painter );
00908 
00909     painter->restore();
00910 
00911     if ( withBackground && hackStyledBackground )
00912     {
00913         // Now paint the border on top
00914         QStyleOptionFrame opt;
00915         opt.initFrom(this);
00916         style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, this);
00917     }
00918 }
00919 
00926 void QwtPlotCanvas::drawBorder( QPainter *painter )
00927 {
00928     if ( d_data->borderRadius > 0 )
00929     {
00930         if ( frameWidth() > 0 )
00931         {
00932             QwtPainter::drawRoundedFrame( painter, QRectF( frameRect() ), 
00933                 d_data->borderRadius, d_data->borderRadius,
00934                 palette(), frameWidth(), frameStyle() );
00935         }
00936     }
00937     else
00938     {
00939 #if QT_VERSION >= 0x040500
00940 #if QT_VERSION < 0x050000
00941         QStyleOptionFrameV3 opt;
00942 #else
00943         QStyleOptionFrame opt;
00944 #endif
00945         opt.init(this);
00946 
00947         int frameShape  = frameStyle() & QFrame::Shape_Mask;
00948         int frameShadow = frameStyle() & QFrame::Shadow_Mask;
00949 
00950         opt.frameShape = QFrame::Shape( int( opt.frameShape ) | frameShape );
00951 #if 0
00952         opt.rect = frameRect();
00953 #endif
00954 
00955         switch (frameShape) 
00956         {
00957             case QFrame::Box:
00958             case QFrame::HLine:
00959             case QFrame::VLine:
00960             case QFrame::StyledPanel:
00961             case QFrame::Panel:
00962             {
00963                 opt.lineWidth = lineWidth();
00964                 opt.midLineWidth = midLineWidth();
00965                 break; 
00966             }
00967             default: 
00968             {
00969                 opt.lineWidth = frameWidth();
00970                 break;
00971             }
00972         }
00973     
00974         if ( frameShadow == Sunken )
00975             opt.state |= QStyle::State_Sunken;
00976         else if ( frameShadow == Raised )
00977             opt.state |= QStyle::State_Raised;
00978 
00979         style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, this);
00980 #else
00981         drawFrame( painter );
00982 #endif
00983     }
00984 }
00985 
00990 void QwtPlotCanvas::resizeEvent( QResizeEvent *event )
00991 {
00992     QFrame::resizeEvent( event );
00993     updateStyleSheetInfo();
00994 }
00995 
01000 void QwtPlotCanvas::drawFocusIndicator( QPainter *painter )
01001 {
01002     const int margin = 1;
01003 
01004     QRect focusRect = contentsRect();
01005     focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
01006         focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
01007 
01008     QwtPainter::drawFocusRect( painter, this, focusRect );
01009 }
01010 
01015 void QwtPlotCanvas::replot()
01016 {
01017     invalidateBackingStore();
01018 
01019     if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) )
01020         repaint( contentsRect() );
01021     else
01022         update( contentsRect() );
01023 }
01024 
01026 void QwtPlotCanvas::updateStyleSheetInfo()
01027 {
01028     if ( !testAttribute(Qt::WA_StyledBackground ) )
01029         return;
01030 
01031     QwtStyleSheetRecorder recorder( size() );
01032     
01033     QPainter painter( &recorder );
01034     
01035     QStyleOption opt;
01036     opt.initFrom(this);
01037     style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this);
01038     
01039     painter.end();
01040 
01041     d_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty();
01042     d_data->styleSheet.cornerRects = recorder.clipRects;
01043 
01044     if ( recorder.background.path.isEmpty() )
01045     {
01046         if ( !recorder.border.rectList.isEmpty() )
01047         {
01048             d_data->styleSheet.borderPath = 
01049                 qwtCombinePathList( rect(), recorder.border.pathList );
01050         }
01051     }
01052     else
01053     {
01054         d_data->styleSheet.borderPath = recorder.background.path;
01055         d_data->styleSheet.background.brush = recorder.background.brush;
01056         d_data->styleSheet.background.origin = recorder.background.origin;
01057     }
01058 }
01059 
01069 QPainterPath QwtPlotCanvas::borderPath( const QRect &rect ) const
01070 {
01071     if ( testAttribute(Qt::WA_StyledBackground ) )
01072     {
01073         QwtStyleSheetRecorder recorder( rect.size() );
01074 
01075         QPainter painter( &recorder );
01076 
01077         QStyleOption opt;
01078         opt.initFrom(this);
01079         opt.rect = rect;
01080         style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this);
01081 
01082         painter.end();
01083 
01084         if ( !recorder.background.path.isEmpty() )
01085             return recorder.background.path;
01086 
01087         if ( !recorder.border.rectList.isEmpty() )
01088             return qwtCombinePathList( rect, recorder.border.pathList );
01089     }
01090     else if ( d_data->borderRadius > 0.0 )
01091     {
01092         double fw2 = frameWidth() * 0.5;
01093         QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 );
01094 
01095         QPainterPath path;
01096         path.addRoundedRect( r, d_data->borderRadius, d_data->borderRadius );
01097         return path;
01098     }
01099     
01100     return QPainterPath();
01101 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56