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


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