KDChartBarDiagram.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2010 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 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     if ( !checkInvariants(true) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
00362 
00363     // note: calculateDataBoundaries() is ignoring the hidden flags.
00364     // That's not a bug but a feature: Hiding data does not mean removing them.
00365     // For totally removing data from KD Chart's view people can use e.g. a proxy model
00366     // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
00367     return d->implementor->calculateDataBoundaries();
00368 }
00369 
00370 void BarDiagram::paintEvent ( QPaintEvent*)
00371 {
00372     QPainter painter ( viewport() );
00373     PaintContext ctx;
00374     ctx.setPainter ( &painter );
00375     ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
00376     paint ( &ctx );
00377 }
00378 
00379 void BarDiagram::paint( PaintContext* ctx )
00380 {
00381     if ( !checkInvariants( true ) ) return;
00382     if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
00383     const PainterSaver p( ctx->painter() );
00384     if( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
00385         return; // nothing to paint for us
00386 
00387     AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
00388     ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
00389 
00390     // Only paint elements that are in the paint context's rectangle
00391     // (in this case boundaries of the diagram, see paintEvent())
00392     ctx->painter()->setClipping( true );
00393     ctx->painter()->setClipRect( ctx->rectangle() );
00394 
00395     // paint different bar types Normal - Stacked - Percent - Default Normal
00396     d->implementor->paint( ctx );
00397 
00398     ctx->setCoordinatePlane( plane );
00399 }
00400 
00401 void BarDiagram::resize( const QSizeF& size )
00402 {
00403     d->compressor.setResolution( static_cast< int >( size.width() * coordinatePlane()->zoomFactorX() ),
00404                                  static_cast< int >( size.height() * coordinatePlane()->zoomFactorY() ) );
00405     setDataBoundariesDirty();
00406 }
00407 
00408 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00409 const
00410 #endif
00411 int BarDiagram::numberOfAbscissaSegments () const
00412 {
00413     return d->attributesModel->rowCount(attributesModelRootIndex());
00414 }
00415 
00416 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00417 const
00418 #endif
00419 int BarDiagram::numberOfOrdinateSegments () const
00420 {
00421     return d->attributesModel->columnCount(attributesModelRootIndex());
00422 }
00423 
00424 //#undef d