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