KDChartLineDiagram.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2011 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 "KDChartLineDiagram.h"
00024 #include "KDChartLineDiagram_p.h"
00025 
00026 #include "KDChartBarDiagram.h"
00027 #include "KDChartPalette.h"
00028 #include "KDChartPosition.h"
00029 #include "KDChartTextAttributes.h"
00030 #include "KDChartAttributesModel.h"
00031 #include "KDChartAbstractGrid.h"
00032 #include "KDChartDataValueAttributes.h"
00033 
00034 #include <KDABLibFakes>
00035 
00036 #include "KDChartNormalLineDiagram_p.h"
00037 #include "KDChartStackedLineDiagram_p.h"
00038 #include "KDChartPercentLineDiagram_p.h"
00039 
00040 #include <QDebug>
00041 #include <QPainter>
00042 #include <QString>
00043 #include <QPainterPath>
00044 #include <QPen>
00045 #include <QVector>
00046 
00047 using namespace KDChart;
00048 
00049 LineDiagram::Private::Private()
00050 {
00051 }
00052 
00053 LineDiagram::Private::~Private() {}
00054 
00055 
00056 #define d d_func()
00057 
00058 
00059 LineDiagram::LineDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) :
00060     AbstractCartesianDiagram( new Private(), parent, plane )
00061 {
00062     init();
00063 }
00064 
00065 void LineDiagram::init()
00066 {
00067     d->diagram = this;
00068     d->normalDiagram = new NormalLineDiagram( this );
00069     d->stackedDiagram = new StackedLineDiagram( this );
00070     d->percentDiagram = new PercentLineDiagram( this );
00071     d->implementor = d->normalDiagram;
00072     d->centerDataPoints = false;
00073     d->reverseDatasetOrder = false;
00074 }
00075 
00076 LineDiagram::~LineDiagram()
00077 {
00078 }
00079 
00083 LineDiagram * LineDiagram::clone() const
00084 {
00085     LineDiagram* newDiagram = new LineDiagram( new Private( *d ) );
00086     newDiagram->setType( type() );
00087     return newDiagram;
00088 }
00089 
00090 
00091 bool LineDiagram::compare( const LineDiagram* other )const
00092 {
00093     if( other == this ) return true;
00094     if( ! other ){
00095         return false;
00096     }
00097     /*
00098     qDebug() <<"\n             LineDiagram::compare():";
00099             // compare own properties
00100     qDebug() << (type() == other->type());
00101     */
00102     return  // compare the base class
00103             ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
00104             // compare own properties
00105             (type()             == other->type()) &&
00106             (centerDataPoints() == other->centerDataPoints()) &&
00107             (reverseDatasetOrder() == other->reverseDatasetOrder());
00108 }
00109 
00114 void LineDiagram::setType( const LineType type )
00115 {
00116     if ( d->implementor->type() == type ) return;
00117    if ( type != LineDiagram::Normal && datasetDimension() > 1 ) {
00118        Q_ASSERT_X ( false, "setType()",
00119                     "This line chart type can't be used with multi-dimensional data." );
00120        return;
00121    }
00122    switch( type ) {
00123    case Normal:
00124        d->implementor = d->normalDiagram;
00125        break;
00126    case Stacked:
00127        d->implementor = d->stackedDiagram;
00128        break;
00129    case Percent:
00130        d->implementor = d->percentDiagram;
00131        break;
00132    default:
00133        Q_ASSERT_X( false, "LineDiagram::setType", "unknown diagram subtype" );
00134    };
00135 
00136    // d->lineType = type;
00137    Q_ASSERT( d->implementor->type() == type );
00138 
00139    // AbstractAxis settings - see AbstractDiagram and CartesianAxis
00140    setPercentMode( type == LineDiagram::Percent );
00141    setDataBoundariesDirty();
00142    emit layoutChanged( this );
00143    emit propertiesChanged();
00144 }
00145 
00149 LineDiagram::LineType LineDiagram::type() const
00150 {
00151     return d->implementor->type();
00152 }
00153 
00154 void LineDiagram::setCenterDataPoints( bool center )
00155 {
00156         d->centerDataPoints = center;
00157         emit propertiesChanged();
00158 }
00159 
00160 bool LineDiagram::centerDataPoints() const
00161 {
00162         return d->centerDataPoints;
00163 }
00164 
00165 void LineDiagram::setReverseDatasetOrder( bool reverse )
00166 {
00167     d->reverseDatasetOrder = reverse;
00168 }
00169 
00170 bool LineDiagram::reverseDatasetOrder() const
00171 {
00172     return d->reverseDatasetOrder;
00173 }
00174 
00178 void LineDiagram::setLineAttributes( const LineAttributes& la )
00179 {
00180     d->attributesModel->setModelData(
00181         qVariantFromValue( la ),
00182         LineAttributesRole );
00183     emit propertiesChanged();
00184 }
00185 
00189 void LineDiagram::setLineAttributes(
00190         int column,
00191     const LineAttributes& la )
00192 {
00193     d->setDatasetAttrs( column, qVariantFromValue( la ), LineAttributesRole );
00194     emit propertiesChanged();
00195 }
00196 
00200 void LineDiagram::resetLineAttributes( int column )
00201 {
00202     d->resetDatasetAttrs( column, LineAttributesRole );
00203     emit propertiesChanged();
00204 }
00205 
00209 void LineDiagram::setLineAttributes(
00210         const QModelIndex& index,
00211     const LineAttributes& la )
00212 {
00213     d->attributesModel->setData(
00214             d->attributesModel->mapFromSource(index),
00215     qVariantFromValue( la ),
00216     LineAttributesRole );
00217     emit propertiesChanged();
00218 }
00219 
00223 void LineDiagram::resetLineAttributes( const QModelIndex & index )
00224 {
00225     d->attributesModel->resetData(
00226             d->attributesModel->mapFromSource(index), LineAttributesRole );
00227     emit propertiesChanged();
00228 }
00229 
00233 LineAttributes LineDiagram::lineAttributes() const
00234 {
00235     return qVariantValue<LineAttributes>(
00236         d->attributesModel->data( KDChart::LineAttributesRole ) );
00237 }
00238 
00242 LineAttributes LineDiagram::lineAttributes( int column ) const
00243 {
00244     const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
00245     if( attrs.isValid() )
00246         return qVariantValue< LineAttributes >( attrs );
00247     return lineAttributes();
00248 }
00249 
00253 LineAttributes LineDiagram::lineAttributes(
00254     const QModelIndex& index ) const
00255 {
00256     return qVariantValue<LineAttributes>(
00257         d->attributesModel->data(
00258             d->attributesModel->mapFromSource(index),
00259             KDChart::LineAttributesRole ) );
00260 }
00261 
00265 void LineDiagram::setThreeDLineAttributes(
00266     const ThreeDLineAttributes& la )
00267 {
00268     setDataBoundariesDirty();
00269     d->attributesModel->setModelData(
00270         qVariantFromValue( la ),
00271         ThreeDLineAttributesRole );
00272    emit propertiesChanged();
00273 }
00274 
00278 void LineDiagram::setThreeDLineAttributes(
00279     int column,
00280     const ThreeDLineAttributes& la )
00281 {
00282     setDataBoundariesDirty();
00283     d->setDatasetAttrs( column, qVariantFromValue( la ), ThreeDLineAttributesRole );
00284    emit propertiesChanged();
00285 }
00286 
00290 void LineDiagram::setThreeDLineAttributes(
00291     const QModelIndex & index,
00292     const ThreeDLineAttributes& la )
00293 {
00294     setDataBoundariesDirty();
00295     d->attributesModel->setData(
00296         d->attributesModel->mapFromSource(index),
00297         qVariantFromValue( la ),
00298         ThreeDLineAttributesRole );
00299    emit propertiesChanged();
00300 }
00301 
00305 ThreeDLineAttributes LineDiagram::threeDLineAttributes() const
00306 {
00307     return qVariantValue<ThreeDLineAttributes>(
00308         d->attributesModel->data( KDChart::ThreeDLineAttributesRole ) );
00309 }
00310 
00314 ThreeDLineAttributes LineDiagram::threeDLineAttributes( int column ) const
00315 {
00316     const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
00317     if( attrs.isValid() )
00318         return qVariantValue< ThreeDLineAttributes >( attrs );
00319     return threeDLineAttributes();
00320 }
00321 
00325 ThreeDLineAttributes LineDiagram::threeDLineAttributes( const QModelIndex& index ) const
00326 {
00327     return qVariantValue<ThreeDLineAttributes>(
00328         d->attributesModel->data(
00329             d->attributesModel->mapFromSource( index ),
00330             KDChart::ThreeDLineAttributesRole ) );
00331 }
00332 
00333 double LineDiagram::threeDItemDepth( const QModelIndex& index ) const
00334 {
00335     return threeDLineAttributes( index ).validDepth();
00336 }
00337 
00338 double LineDiagram::threeDItemDepth( int column ) const
00339 {
00340     return qVariantValue<ThreeDLineAttributes>(
00341         d->datasetAttrs( column, KDChart::ThreeDLineAttributesRole ) ).validDepth();
00342 }
00343 
00347 void LineDiagram::setValueTrackerAttributes( const QModelIndex & index,
00348                                              const ValueTrackerAttributes & va )
00349 {
00350     d->attributesModel->setData( d->attributesModel->mapFromSource(index),
00351                                  qVariantFromValue( va ),
00352                                  KDChart::ValueTrackerAttributesRole );
00353     emit propertiesChanged();
00354 }
00355 
00359 ValueTrackerAttributes LineDiagram::valueTrackerAttributes(
00360         const QModelIndex & index ) const
00361 {
00362     return qVariantValue<ValueTrackerAttributes>( d->attributesModel->data(
00363             d->attributesModel->mapFromSource( index ),
00364             KDChart::ValueTrackerAttributesRole ) );
00365 }
00366 
00367 void LineDiagram::resizeEvent ( QResizeEvent* )
00368 {
00369 }
00370 
00371 const QPair<QPointF, QPointF> LineDiagram::calculateDataBoundaries() const
00372 {
00373     d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
00374                                  static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
00375 
00376     if ( !checkInvariants( true ) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
00377 
00378     // note: calculateDataBoundaries() is ignoring the hidden flags.
00379     //       That's not a bug but a feature: Hiding data does not mean removing them.
00380     // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
00381 
00382     // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
00383     return d->implementor->calculateDataBoundaries();
00384 }
00385 
00386 
00387 void LineDiagram::paintEvent ( QPaintEvent*)
00388 {
00389 //qDebug() << "starting LineDiagram::paintEvent ( QPaintEvent*)";
00390     QPainter painter ( viewport() );
00391     PaintContext ctx;
00392     ctx.setPainter ( &painter );
00393     ctx.setRectangle ( QRectF ( 0, 0, width(), height() ) );
00394     paint ( &ctx );
00395 //qDebug() << "         LineDiagram::paintEvent ( QPaintEvent*) ended.";
00396 }
00397 
00398 
00399 double LineDiagram::valueForCellTesting( int row, int column,
00400                                          bool& bOK,
00401                                          bool showHiddenCellsAsInvalid ) const
00402 {
00403     double value = 0.0;
00404     if( showHiddenCellsAsInvalid && isHidden( model()->index( row, column, rootIndex() ) ) )
00405         bOK = false;
00406     else
00407         value = d->attributesModel->data(
00408                     d->attributesModel->index( row, column, attributesModelRootIndex() )
00409                 ).toDouble( &bOK );
00410     return bOK ? value : 0.0;
00411 }
00412 
00413 LineAttributes::MissingValuesPolicy LineDiagram::getCellValues(
00414       int row, int column,
00415       bool shiftCountedXValuesByHalfSection,
00416       double& valueX, double& valueY ) const
00417 {
00418     LineAttributes::MissingValuesPolicy policy;
00419 
00420     bool bOK = true;
00421     valueX = ( datasetDimension() > 1 && column > 0 )
00422              ? valueForCellTesting( row, column-1, bOK, true )
00423              : ((shiftCountedXValuesByHalfSection ? 0.5 : 0.0) + row);
00424     if( bOK )
00425         valueY = valueForCellTesting( row, column, bOK, true );
00426     if( bOK ){
00427         policy = LineAttributes::MissingValuesPolicyIgnored;
00428     }else{
00429         // missing value: find out the policy
00430         QModelIndex index = model()->index( row, column, rootIndex() );
00431         LineAttributes la = lineAttributes( index );
00432         policy = la.missingValuesPolicy();
00433     }
00434     return policy;
00435 }
00436 
00437 void LineDiagram::paint( PaintContext* ctx )
00438 {
00439     // note: Not having any data model assigned is no bug
00440     //       but we can not draw a diagram then either.
00441     if ( !checkInvariants( true ) ) return;
00442     if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
00443     const PainterSaver p( ctx->painter() );
00444     if( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
00445         return; // nothing to paint for us
00446 
00447     AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
00448     ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
00449 
00450 
00451     // paint different line types Normal - Stacked - Percent - Default Normal
00452     d->implementor->paint( ctx );
00453 
00454     ctx->setCoordinatePlane( plane );
00455 }
00456 
00457 void LineDiagram::resize ( const QSizeF& size )
00458 {
00459     d->compressor.setResolution( static_cast<int>( size.width() * coordinatePlane()->zoomFactorX() ),
00460                                  static_cast<int>( size.height() * coordinatePlane()->zoomFactorY() ) );
00461     setDataBoundariesDirty();
00462 }
00463 
00464 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00465 const
00466 #endif
00467 int LineDiagram::numberOfAbscissaSegments () const
00468 {
00469     return d->attributesModel->rowCount(attributesModelRootIndex());
00470 }
00471 
00472 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00473 const
00474 #endif
00475 int LineDiagram::numberOfOrdinateSegments () const
00476 {
00477     return d->attributesModel->columnCount(attributesModelRootIndex());
00478 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/