KDChartPolarDiagram.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2007 Klar�vdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Chart library.
00005  **
00006  ** This file may be distributed and/or modified under the terms of the
00007  ** GNU General Public License version 2 as published by the Free Software
00008  ** Foundation and appearing in the file LICENSE.GPL included in the
00009  ** packaging of this file.
00010  **
00011  ** Licensees holding valid commercial KD Chart licenses may use this file in
00012  ** accordance with the KD Chart Commercial License Agreement provided with
00013  ** the Software.
00014  **
00015  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017  **
00018  ** See http://www.kdab.net/kdchart for
00019  **   information about KDChart Commercial License Agreements.
00020  **
00021  ** Contact info@kdab.net if any conditions of this
00022  ** licensing are not clear to you.
00023  **
00024  **********************************************************************/
00025 
00026 #include "KDChartPolarDiagram.h"
00027 #include "KDChartPolarDiagram_p.h"
00028 
00029 #include <QPainter>
00030 #include "KDChartAttributesModel.h"
00031 #include "KDChartPaintContext.h"
00032 #include "KDChartPainterSaver_p.h"
00033 #include "KDChartDataValueAttributes.h"
00034 
00035 #include <KDABLibFakes>
00036 
00037 using namespace KDChart;
00038 
00039 PolarDiagram::Private::Private() :
00040     rotateCircularLabels( false ),
00041     closeDatasets( false )
00042 {
00043 }
00044 
00045 PolarDiagram::Private::~Private() {}
00046 
00047 #define d d_func()
00048 
00049 PolarDiagram::PolarDiagram( QWidget* parent, PolarCoordinatePlane* plane ) :
00050     AbstractPolarDiagram( new Private( ), parent, plane )
00051 {
00052     //init();
00053 }
00054 
00055 PolarDiagram::~PolarDiagram()
00056 {
00057 }
00058 
00059 
00060 void PolarDiagram::init()
00061 {
00062     setShowDelimitersAtPosition( Position::Unknown, false );
00063     setShowDelimitersAtPosition( Position::Center, false );
00064     setShowDelimitersAtPosition( Position::NorthWest, false );
00065     setShowDelimitersAtPosition( Position::North, true );
00066     setShowDelimitersAtPosition( Position::NorthEast, false );
00067     setShowDelimitersAtPosition( Position::West, false );
00068     setShowDelimitersAtPosition( Position::East, false );
00069     setShowDelimitersAtPosition( Position::SouthWest, false );
00070     setShowDelimitersAtPosition( Position::South, true );
00071     setShowDelimitersAtPosition( Position::SouthEast, false );
00072     setShowDelimitersAtPosition( Position::Floating, false );
00073 
00074     setShowLabelsAtPosition( Position::Unknown, false );
00075     setShowLabelsAtPosition( Position::Center, false );
00076     setShowLabelsAtPosition( Position::NorthWest, false );
00077     setShowLabelsAtPosition( Position::North, true );
00078     setShowLabelsAtPosition( Position::NorthEast, false );
00079     setShowLabelsAtPosition( Position::West, false );
00080     setShowLabelsAtPosition( Position::East, false );
00081     setShowLabelsAtPosition( Position::SouthWest, false );
00082     setShowLabelsAtPosition( Position::South, true );
00083     setShowLabelsAtPosition( Position::SouthEast, false );
00084     setShowLabelsAtPosition( Position::Floating, false );
00085 }
00086 
00090 PolarDiagram * PolarDiagram::clone() const
00091 {
00092     PolarDiagram* newDiagram = new PolarDiagram( new Private( *d ) );
00093     // This needs to be copied after the fact
00094     newDiagram->d->showDelimitersAtPosition = d->showDelimitersAtPosition;
00095     newDiagram->d->showLabelsAtPosition = d->showLabelsAtPosition;
00096     newDiagram->d->rotateCircularLabels = d->rotateCircularLabels;
00097     newDiagram->d->closeDatasets = d->closeDatasets;
00098     return newDiagram;
00099 }
00100 
00101 const QPair<QPointF, QPointF> PolarDiagram::calculateDataBoundaries () const
00102 {
00103     if ( !checkInvariants(true) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
00104     const int rowCount = model()->rowCount(rootIndex());
00105     const int colCount = model()->columnCount(rootIndex());
00106     double xMin = 0.0;
00107     double xMax = colCount;
00108     double yMin = 0, yMax = 0;
00109     for ( int iCol=0; iCol<colCount; ++iCol ) {
00110         for ( int iRow=0; iRow< rowCount; ++iRow ) {
00111             double value = model()->data( model()->index( iRow, iCol, rootIndex() ) ).toDouble();
00112             yMax = qMax( yMax, value );
00113             yMin = qMin( yMin, value );
00114         }
00115     }
00116     QPointF bottomLeft ( QPointF( xMin, yMin ) );
00117     QPointF topRight ( QPointF( xMax, yMax ) );
00118     return QPair<QPointF, QPointF> ( bottomLeft,  topRight );
00119 }
00120 
00121 
00122 
00123 void PolarDiagram::paintEvent ( QPaintEvent*)
00124 {
00125     QPainter painter ( viewport() );
00126     PaintContext ctx;
00127     ctx.setPainter ( &painter );
00128     ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
00129     paint ( &ctx );
00130 }
00131 
00132 void PolarDiagram::resizeEvent ( QResizeEvent*)
00133 {
00134 }
00135 
00136 void PolarDiagram::paintPolarMarkers( PaintContext* ctx, const QPolygonF& polygon )
00137 {
00138     Q_UNUSED(ctx);
00139     Q_UNUSED(polygon);
00140     // obsolete, since we are using real markers now!
00141 }
00142 
00143 void PolarDiagram::paint( PaintContext* ctx )
00144 {
00145     qreal dummy1, dummy2;
00146     paint( ctx, true,  dummy1, dummy2 );
00147     paint( ctx, false, dummy1, dummy2 );
00148 }
00149 
00150 void PolarDiagram::paint( PaintContext* ctx,
00151                           bool calculateListAndReturnScale,
00152                           qreal& newZoomX, qreal& newZoomY )
00153 {
00154     // note: Not having any data model assigned is no bug
00155     //       but we can not draw a diagram then either.
00156     if ( !checkInvariants(true) )
00157         return;
00158     d->reverseMapper.clear();
00159 
00160     const int rowCount = model()->rowCount( rootIndex() );
00161     const int colCount = model()->columnCount( rootIndex() );
00162 
00163     int iRow, iCol;
00164 
00165     if( calculateListAndReturnScale ){
00166 
00167         // Check if all of the data value texts / data comments will fit
00168         // into the available space:
00169         d->dataValueInfoList.clear();
00170         for ( iCol=0; iCol < colCount; ++iCol ) {
00171             for ( iRow=0; iRow < rowCount; ++iRow ) {
00172                 QModelIndex index = model()->index( iRow, iCol, rootIndex() );
00173                 const double value = model()->data( index ).toDouble();
00174                 QPointF point = coordinatePlane()->translate(
00175                         QPointF( value, iRow ) ) + ctx->rectangle().topLeft();
00176                 //qDebug() << point;
00177                 d->appendDataValueTextInfoToList(
00178                         this, d->dataValueInfoList, index, 0,
00179                         PositionPoints( point ), Position::Center, Position::Center,
00180                         value );
00181             }
00182         }
00183         const qreal oldZoomX = coordinatePlane()->zoomFactorX();
00184         const qreal oldZoomY = coordinatePlane()->zoomFactorY();
00185         newZoomX = oldZoomX;
00186         newZoomY = oldZoomY;
00187         if( d->dataValueInfoList.count() ){
00188             QRectF txtRectF;
00189             d->paintDataValueTextsAndMarkers( this, ctx, d->dataValueInfoList, true, true, &txtRectF );
00190             const QRect txtRect = txtRectF.toRect();
00191             const QRect curRect = coordinatePlane()->geometry();
00192             const qreal gapX = qMin( txtRect.left() - curRect.left(), curRect.right()  - txtRect.right() );
00193             const qreal gapY = qMin( txtRect.top()  - curRect.top(),  curRect.bottom() - txtRect.bottom() );
00194             newZoomX = oldZoomX;
00195             newZoomY = oldZoomY;
00196             if( gapX < 0.0 )
00197                 newZoomX *= 1.0 + (gapX-1.0) / curRect.width();
00198             if( gapY < 0.0 )
00199                 newZoomY *= 1.0 + (gapY-1.0) / curRect.height();
00200         }
00201 
00202     }else{
00203 
00204         for ( iCol=0; iCol < colCount; ++iCol ) {
00205             //TODO(khz): As of yet PolarDiagram can not show per-segment line attributes
00206             //           but it draws every polyline in one go - using one color.
00207             //           This needs to be enhanced to allow for cell-specific settings
00208             //           in the same way as LineDiagram does it.
00209             QBrush brush = qVariantValue<QBrush>( attributesModel()->headerData( iCol, Qt::Vertical, KDChart::DatasetBrushRole ) );
00210             QPolygonF polygon;
00211             QPointF point0;
00212             for ( iRow=0; iRow < rowCount; ++iRow ) {
00213                 QModelIndex index = model()->index( iRow, iCol, rootIndex() );
00214                 const double value = model()->data( index ).toDouble();
00215                 QPointF point = coordinatePlane()->translate(
00216                         QPointF( value, iRow ) ) + ctx->rectangle().topLeft();
00217                 polygon.append( point );
00218                 //qDebug() << point;
00219                 if( ! iRow )
00220                     point0= point;
00221             }
00222             if( closeDatasets() && rowCount )
00223                 polygon.append( point0 );
00224 
00225             PainterSaver painterSaver( ctx->painter() );
00226             ctx->painter()->setRenderHint ( QPainter::Antialiasing );
00227             ctx->painter()->setBrush( brush );
00228             QPen p( ctx->painter()->pen() );
00229             p.setColor( brush.color() ); // FIXME use DatasetPenRole
00230             p.setWidth( 2 );// FIXME properties
00231             ctx->painter()->setPen( PrintingParameters::scalePen( p ) );
00232             ctx->painter()->drawPolyline( polygon );
00233         }
00234         d->paintDataValueTextsAndMarkers( this, ctx, d->dataValueInfoList, true );
00235     }
00236 }
00237 
00238 void PolarDiagram::resize ( const QSizeF& )
00239 {
00240 }
00241 
00242 /*virtual*/
00243 double PolarDiagram::valueTotals () const
00244 {
00245     return model()->rowCount(rootIndex());
00246 }
00247 
00248 /*virtual*/
00249 double PolarDiagram::numberOfValuesPerDataset() const
00250 {
00251     return model() ? model()->rowCount(rootIndex()) : 0.0;
00252 }
00253 
00254 /*virtual*/
00255 double PolarDiagram::numberOfGridRings() const
00256 {
00257     return 5; // FIXME
00258 }
00259 
00260 void PolarDiagram::setZeroDegreePosition( int degrees )
00261 {
00262     Q_UNUSED( degrees );
00263     qWarning() << "Deprecated PolarDiagram::setZeroDegreePosition() called, setting ignored.";
00264 }
00265 
00266 int PolarDiagram::zeroDegreePosition() const
00267 {
00268     qWarning() << "Deprecated PolarDiagram::zeroDegreePosition() called.";
00269     return 0;
00270 }
00271 
00272 void PolarDiagram::setRotateCircularLabels( bool rotateCircularLabels )
00273 {
00274     d->rotateCircularLabels = rotateCircularLabels;
00275 }
00276 
00277 bool PolarDiagram::rotateCircularLabels() const
00278 {
00279     return d->rotateCircularLabels;
00280 }
00281 
00282 void PolarDiagram::setCloseDatasets( bool closeDatasets )
00283 {
00284     d->closeDatasets = closeDatasets;
00285 }
00286 
00287 bool PolarDiagram::closeDatasets() const
00288 {
00289     return d->closeDatasets;
00290 }
00291 
00292 void PolarDiagram::setShowDelimitersAtPosition( Position position,
00293                                                        bool showDelimiters )
00294 {
00295     d->showDelimitersAtPosition[position.value()] = showDelimiters;
00296 }
00297 
00298 void PolarDiagram::setShowLabelsAtPosition( Position position,
00299                                                    bool showLabels )
00300 {
00301     d->showLabelsAtPosition[position.value()] = showLabels;
00302 }
00303 
00304 bool PolarDiagram::showDelimitersAtPosition( Position position ) const
00305 {
00306     return d->showDelimitersAtPosition[position.value()];
00307 }
00308 
00309 bool PolarDiagram::showLabelsAtPosition( Position position ) const
00310 {
00311     return d->showLabelsAtPosition[position.value()];
00312 }
00313 
00314 
00315 

Generated on Thu Mar 4 23:19:12 2010 for KD Chart 2 by  doxygen 1.5.4