KD Chart 2
[rev.2.5]
|
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 "KDChartBarDiagram.h" 00024 #include "KDChartBarDiagram_p.h" 00025 00026 #include "KDChartThreeDBarAttributes.h" 00027 #include "KDChartPosition.h" 00028 #include "KDChartAttributesModel.h" 00029 #include "KDChartAbstractGrid.h" 00030 #include "KDChartPainterSaver_p.h" 00031 00032 #include <QPainter> 00033 #include <QDebug> 00034 00035 #include <KDABLibFakes> 00036 00037 #include "KDChartNormalBarDiagram_p.h" 00038 #include "KDChartStackedBarDiagram_p.h" 00039 #include "KDChartPercentBarDiagram_p.h" 00040 #include "KDChartNormalLyingBarDiagram_p.h" 00041 #include "KDChartStackedLyingBarDiagram_p.h" 00042 #include "KDChartPercentLyingBarDiagram_p.h" 00043 00044 00045 using namespace KDChart; 00046 00047 BarDiagram::Private::Private() 00048 : orientation( Qt::Vertical ) 00049 , implementor( 0 ) 00050 , normalDiagram( 0 ) 00051 , stackedDiagram( 0 ) 00052 , percentDiagram( 0 ) 00053 , normalLyingDiagram( 0 ) 00054 , stackedLyingDiagram( 0 ) 00055 , percentLyingDiagram( 0 ) 00056 { 00057 } 00058 00059 BarDiagram::Private::~Private() 00060 { 00061 delete normalDiagram; 00062 delete stackedDiagram; 00063 delete percentDiagram; 00064 delete normalLyingDiagram; 00065 delete stackedLyingDiagram; 00066 delete percentLyingDiagram; 00067 } 00068 00069 #define d d_func() 00070 00071 00072 BarDiagram::BarDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) : 00073 AbstractCartesianDiagram( new Private(), parent, plane ) 00074 { 00075 init(); 00076 } 00077 00078 void BarDiagram::init() 00079 { 00080 d->normalDiagram = new NormalBarDiagram( this ); 00081 d->stackedDiagram = new StackedBarDiagram( this ); 00082 d->percentDiagram = new PercentBarDiagram( this ); 00083 d->normalLyingDiagram = new NormalLyingBarDiagram( this ); 00084 d->stackedLyingDiagram = new StackedLyingBarDiagram( this ); 00085 d->percentLyingDiagram = new PercentLyingBarDiagram( this ); 00086 d->implementor = d->normalDiagram; 00087 d->compressor.setModel( attributesModel() ); 00088 } 00089 00090 BarDiagram::~BarDiagram() 00091 { 00092 } 00093 00097 BarDiagram * BarDiagram::clone() const 00098 { 00099 00100 BarDiagram* newDiagram = new BarDiagram( new Private( *d ) ); 00101 newDiagram->setType( type() ); 00102 return newDiagram; 00103 } 00104 00105 bool BarDiagram::compare( const BarDiagram* other ) const 00106 { 00107 if( other == this ) return true; 00108 if( ! other ){ 00109 return false; 00110 } 00111 00112 return // compare the base class 00113 ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) && 00114 // compare own properties 00115 (type() == other->type()); 00116 } 00117 00122 void BarDiagram::setType( const BarType type ) 00123 { 00124 //if ( type == d->barType ) return; 00125 if ( d->implementor->type() == type ) return; 00126 00127 if ( d->orientation == Qt::Vertical ) { 00128 switch( type ) { 00129 case Normal: 00130 d->implementor = d->normalDiagram; 00131 break; 00132 case Stacked: 00133 d->implementor = d->stackedDiagram; 00134 break; 00135 case Percent: 00136 d->implementor = d->percentDiagram; 00137 break; 00138 default: 00139 Q_ASSERT_X( false, "BarDiagram::setType", "unknown diagram subtype" ); 00140 } 00141 } else { 00142 switch( type ) { 00143 case Normal: 00144 d->implementor = d->normalLyingDiagram; 00145 break; 00146 case Stacked: 00147 d->implementor = d->stackedLyingDiagram; 00148 break; 00149 case Percent: 00150 d->implementor = d->percentLyingDiagram; 00151 break; 00152 default: 00153 Q_ASSERT_X( false, "BarDiagram::setType", "unknown diagram subtype" ); 00154 } 00155 } 00156 00157 Q_ASSERT( d->implementor->type() == type ); 00158 00159 //d->barType = type; 00160 // AbstractAxis settings - see AbstractDiagram and CartesianAxis 00161 setPercentMode( type == BarDiagram::Percent ); 00162 setDataBoundariesDirty(); 00163 emit layoutChanged( this ); 00164 emit propertiesChanged(); 00165 } 00166 00170 BarDiagram::BarType BarDiagram::type() const 00171 { 00172 return d->implementor->type(); 00173 } 00174 00178 void BarDiagram::setOrientation( Qt::Orientation orientation ) 00179 { 00180 if ( d->orientation == orientation ) 00181 return; 00182 d->orientation = orientation; 00183 00184 if ( d->orientation == Qt::Vertical ) { 00185 switch( type() ) { 00186 case Normal: 00187 d->implementor = d->normalDiagram; 00188 break; 00189 case Stacked: 00190 d->implementor = d->stackedDiagram; 00191 break; 00192 case Percent: 00193 d->implementor = d->percentDiagram; 00194 break; 00195 default: 00196 Q_ASSERT_X( false, "BarDiagram::setType", "unknown diagram subtype" ); 00197 } 00198 } else { 00199 switch( type() ) { 00200 case Normal: 00201 d->implementor = d->normalLyingDiagram; 00202 break; 00203 case Stacked: 00204 d->implementor = d->stackedLyingDiagram; 00205 break; 00206 case Percent: 00207 d->implementor = d->percentLyingDiagram; 00208 break; 00209 default: 00210 Q_ASSERT_X( false, "BarDiagram::setType", "unknown diagram subtype" ); 00211 } 00212 } 00213 00214 // AbstractAxis settings - see AbstractDiagram and CartesianAxis 00215 setPercentMode( type() == BarDiagram::Percent ); 00216 setDataBoundariesDirty(); 00217 emit layoutChanged( this ); 00218 emit propertiesChanged(); 00219 } 00220 00224 Qt::Orientation BarDiagram::orientation() const 00225 { 00226 return d->orientation; 00227 } 00228 00232 void BarDiagram::setBarAttributes( const BarAttributes& ba ) 00233 { 00234 d->attributesModel->setModelData( qVariantFromValue( ba ), BarAttributesRole ); 00235 emit propertiesChanged(); 00236 } 00237 00241 void BarDiagram::setBarAttributes( int column, const BarAttributes& ba ) 00242 { 00243 d->setDatasetAttrs( column, qVariantFromValue( ba ), BarAttributesRole ); 00244 emit propertiesChanged(); 00245 } 00246 00250 void BarDiagram::setBarAttributes( const QModelIndex& index, const BarAttributes& ba ) 00251 { 00252 attributesModel()->setData( 00253 d->attributesModel->mapFromSource( index ), 00254 qVariantFromValue( ba ), 00255 BarAttributesRole ); 00256 emit propertiesChanged(); 00257 } 00258 00262 BarAttributes BarDiagram::barAttributes() const 00263 { 00264 return qVariantValue<BarAttributes>( 00265 d->attributesModel->data( KDChart::BarAttributesRole ) ); 00266 } 00267 00271 BarAttributes BarDiagram::barAttributes( int column ) const 00272 { 00273 const QVariant attrs( d->datasetAttrs( column, KDChart::BarAttributesRole ) ); 00274 if( attrs.isValid() ) 00275 return qVariantValue< BarAttributes >( attrs ); 00276 return barAttributes(); 00277 } 00278 00282 BarAttributes BarDiagram::barAttributes( const QModelIndex& index ) const 00283 { 00284 return qVariantValue<BarAttributes>( 00285 d->attributesModel->data( 00286 d->attributesModel->mapFromSource( index ), 00287 KDChart::BarAttributesRole ) ); 00288 } 00289 00293 void BarDiagram::setThreeDBarAttributes( const ThreeDBarAttributes& threeDAttrs ) 00294 { 00295 setDataBoundariesDirty(); 00296 d->attributesModel->setModelData( qVariantFromValue( threeDAttrs ), ThreeDBarAttributesRole ); 00297 emit layoutChanged( this ); 00298 emit propertiesChanged(); 00299 } 00300 00304 void BarDiagram::setThreeDBarAttributes( int column, const ThreeDBarAttributes& threeDAttrs ) 00305 { 00306 setDataBoundariesDirty(); 00307 d->setDatasetAttrs( column, qVariantFromValue( threeDAttrs ), ThreeDBarAttributesRole ); 00308 //emit layoutChanged( this ); 00309 emit propertiesChanged(); 00310 00311 } 00312 00316 void BarDiagram::setThreeDBarAttributes( const QModelIndex& index, const ThreeDBarAttributes& threeDAttrs ) 00317 { 00318 setDataBoundariesDirty(); 00319 d->attributesModel->setData( 00320 d->attributesModel->mapFromSource(index), 00321 qVariantFromValue( threeDAttrs ), 00322 ThreeDBarAttributesRole ); 00323 //emit layoutChanged( this ); 00324 emit propertiesChanged(); 00325 } 00326 00330 ThreeDBarAttributes BarDiagram::threeDBarAttributes() const 00331 { 00332 return qVariantValue<ThreeDBarAttributes>( 00333 d->attributesModel->data( KDChart::ThreeDBarAttributesRole ) ); 00334 } 00335 00339 ThreeDBarAttributes BarDiagram::threeDBarAttributes( int column ) const 00340 { 00341 const QVariant attrs( d->datasetAttrs( column, KDChart::ThreeDBarAttributesRole ) ); 00342 if( attrs.isValid() ) 00343 return qVariantValue< ThreeDBarAttributes >( attrs ); 00344 return threeDBarAttributes(); 00345 } 00346 00350 ThreeDBarAttributes BarDiagram::threeDBarAttributes( const QModelIndex& index ) const 00351 { 00352 return qVariantValue<ThreeDBarAttributes>( 00353 d->attributesModel->data( 00354 d->attributesModel->mapFromSource(index), 00355 KDChart::ThreeDBarAttributesRole ) ); 00356 } 00357 00358 qreal BarDiagram::threeDItemDepth( const QModelIndex& index ) const 00359 { 00360 return threeDBarAttributes( index ).validDepth(); 00361 } 00362 00363 qreal BarDiagram::threeDItemDepth( int column ) const 00364 { 00365 return threeDBarAttributes( column ).validDepth(); 00366 } 00367 00368 void BarDiagram::resizeEvent ( QResizeEvent*) 00369 { 00370 00371 } 00372 00373 const QPair<QPointF, QPointF> BarDiagram::calculateDataBoundaries() const 00374 { 00375 d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ), 00376 static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) ); 00377 00378 if ( !checkInvariants( true ) ) { 00379 return QPair< QPointF, QPointF >( QPointF( 0, 0 ), QPointF( 0, 0 ) ); 00380 } 00381 00382 // note: calculateDataBoundaries() is ignoring the hidden flags. 00383 // That's not a bug but a feature: Hiding data does not mean removing them. 00384 // For totally removing data from KD Chart's view people can use e.g. a proxy model 00385 // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal 00386 return d->implementor->calculateDataBoundaries(); 00387 } 00388 00389 void BarDiagram::paintEvent ( QPaintEvent*) 00390 { 00391 QPainter painter ( viewport() ); 00392 PaintContext ctx; 00393 ctx.setPainter ( &painter ); 00394 ctx.setRectangle( QRectF ( 0, 0, width(), height() ) ); 00395 paint ( &ctx ); 00396 } 00397 00398 void BarDiagram::paint( PaintContext* ctx ) 00399 { 00400 if ( !checkInvariants( true ) ) return; 00401 if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return; 00402 const PainterSaver p( ctx->painter() ); 00403 if( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 ) 00404 return; // nothing to paint for us 00405 00406 AbstractCoordinatePlane* const plane = ctx->coordinatePlane(); 00407 ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) ); 00408 00409 // This was intended as a fix for KDCH-515, however it caused KDCH-816 00410 // and the original problem in KDCH-515 had by then been fixed in another way. 00411 // Bottom line is, this code is wrong because the above call to 00412 // plane->sharedAxisMasterPlane() performs a translation of the painter, which 00413 // also translates the clip rect, so if we set the old clip rect again afterwards, 00414 // we get a wrong clipping. 00415 // Also, this code is unnecessary because CartesianCoordinatePlane::paint() 00416 // already sets the clipping properly before calling this method. 00417 // ctx->painter()->setClipping( true ); 00418 // ctx->painter()->setClipRect( ctx->rectangle() ); 00419 00420 // paint different bar types Normal - Stacked - Percent - Default Normal 00421 d->implementor->paint( ctx ); 00422 00423 ctx->setCoordinatePlane( plane ); 00424 } 00425 00426 void BarDiagram::resize( const QSizeF& size ) 00427 { 00428 d->compressor.setResolution( static_cast< int >( size.width() * coordinatePlane()->zoomFactorX() ), 00429 static_cast< int >( size.height() * coordinatePlane()->zoomFactorY() ) ); 00430 setDataBoundariesDirty(); 00431 } 00432 00433 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE) 00434 const 00435 #endif 00436 int BarDiagram::numberOfAbscissaSegments () const 00437 { 00438 return d->attributesModel->rowCount(attributesModelRootIndex()); 00439 } 00440 00441 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE) 00442 const 00443 #endif 00444 int BarDiagram::numberOfOrdinateSegments () const 00445 { 00446 return d->attributesModel->columnCount(attributesModelRootIndex()); 00447 } 00448 00449 //#undef d