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