KD Chart 2  [rev.2.5]
KDChartLineDiagram.cpp
Go to the documentation of this file.
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 "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 #include "KDChartPainterSaver_p.h"
00034 
00035 #include <KDABLibFakes>
00036 
00037 #include "KDChartNormalLineDiagram_p.h"
00038 #include "KDChartStackedLineDiagram_p.h"
00039 #include "KDChartPercentLineDiagram_p.h"
00040 
00041 #include <QDebug>
00042 #include <QPainter>
00043 #include <QString>
00044 #include <QPainterPath>
00045 #include <QPen>
00046 #include <QVector>
00047 
00048 using namespace KDChart;
00049 
00050 LineDiagram::Private::Private()
00051 {
00052 }
00053 
00054 LineDiagram::Private::~Private() {}
00055 
00056 
00057 #define d d_func()
00058 
00059 
00060 LineDiagram::LineDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) :
00061     AbstractCartesianDiagram( new Private(), parent, plane )
00062 {
00063     init();
00064 }
00065 
00066 void LineDiagram::init()
00067 {
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     delete d->normalDiagram;
00079     delete d->stackedDiagram;
00080     delete d->percentDiagram;
00081 }
00082 
00086 LineDiagram * LineDiagram::clone() const
00087 {
00088     LineDiagram* newDiagram = new LineDiagram( new Private( *d ) );
00089     newDiagram->setType( type() );
00090     return newDiagram;
00091 }
00092 
00093 
00094 bool LineDiagram::compare( const LineDiagram* other ) const
00095 {
00096     if( other == this ) return true;
00097     if( ! other ){
00098         return false;
00099     }
00100     return  // compare the base class
00101             ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
00102             // compare own properties
00103             (type()             == other->type()) &&
00104             (centerDataPoints() == other->centerDataPoints()) &&
00105             (reverseDatasetOrder() == other->reverseDatasetOrder());
00106 }
00107 
00112 void LineDiagram::setType( const LineType type )
00113 {
00114     if ( d->implementor->type() == type ) return;
00115    if ( type != LineDiagram::Normal && datasetDimension() > 1 ) {
00116        Q_ASSERT_X ( false, "setType()",
00117                     "This line chart type can't be used with multi-dimensional data." );
00118        return;
00119    }
00120    switch( type ) {
00121    case Normal:
00122        d->implementor = d->normalDiagram;
00123        break;
00124    case Stacked:
00125        d->implementor = d->stackedDiagram;
00126        break;
00127    case Percent:
00128        d->implementor = d->percentDiagram;
00129        break;
00130    default:
00131        Q_ASSERT_X( false, "LineDiagram::setType", "unknown diagram subtype" );
00132    };
00133 
00134    // d->lineType = type;
00135    Q_ASSERT( d->implementor->type() == type );
00136 
00137    // AbstractAxis settings - see AbstractDiagram and CartesianAxis
00138    setPercentMode( type == LineDiagram::Percent );
00139    setDataBoundariesDirty();
00140    emit layoutChanged( this );
00141    emit propertiesChanged();
00142 }
00143 
00147 LineDiagram::LineType LineDiagram::type() const
00148 {
00149     return d->implementor->type();
00150 }
00151 
00152 void LineDiagram::setCenterDataPoints( bool center )
00153 {
00154     d->centerDataPoints = center;
00155     emit propertiesChanged();
00156 }
00157 
00158 bool LineDiagram::centerDataPoints() const
00159 {
00160     return d->centerDataPoints;
00161 }
00162 
00163 void LineDiagram::setReverseDatasetOrder( bool reverse )
00164 {
00165     d->reverseDatasetOrder = reverse;
00166 }
00167 
00168 bool LineDiagram::reverseDatasetOrder() const
00169 {
00170     return d->reverseDatasetOrder;
00171 }
00172 
00176 void LineDiagram::setLineAttributes( const LineAttributes& la )
00177 {
00178     d->attributesModel->setModelData(
00179         qVariantFromValue( la ),
00180         LineAttributesRole );
00181     emit propertiesChanged();
00182 }
00183 
00187 void LineDiagram::setLineAttributes(
00188         int column,
00189     const LineAttributes& la )
00190 {
00191     d->setDatasetAttrs( column, qVariantFromValue( la ), LineAttributesRole );
00192     emit propertiesChanged();
00193 }
00194 
00198 void LineDiagram::resetLineAttributes( int column )
00199 {
00200     d->resetDatasetAttrs( column, LineAttributesRole );
00201     emit propertiesChanged();
00202 }
00203 
00207 void LineDiagram::setLineAttributes(
00208         const QModelIndex& index,
00209     const LineAttributes& la )
00210 {
00211     d->attributesModel->setData(
00212             d->attributesModel->mapFromSource(index),
00213     qVariantFromValue( la ),
00214     LineAttributesRole );
00215     emit propertiesChanged();
00216 }
00217 
00221 void LineDiagram::resetLineAttributes( const QModelIndex & index )
00222 {
00223     d->attributesModel->resetData(
00224             d->attributesModel->mapFromSource(index), LineAttributesRole );
00225     emit propertiesChanged();
00226 }
00227 
00231 LineAttributes LineDiagram::lineAttributes() const
00232 {
00233     return qVariantValue<LineAttributes>(
00234         d->attributesModel->data( KDChart::LineAttributesRole ) );
00235 }
00236 
00240 LineAttributes LineDiagram::lineAttributes( int column ) const
00241 {
00242     const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
00243     if( attrs.isValid() )
00244         return qVariantValue< LineAttributes >( attrs );
00245     return lineAttributes();
00246 }
00247 
00251 LineAttributes LineDiagram::lineAttributes(
00252     const QModelIndex& index ) const
00253 {
00254     return qVariantValue<LineAttributes>(
00255         d->attributesModel->data(
00256             d->attributesModel->mapFromSource(index),
00257             KDChart::LineAttributesRole ) );
00258 }
00259 
00263 void LineDiagram::setThreeDLineAttributes(
00264     const ThreeDLineAttributes& la )
00265 {
00266     setDataBoundariesDirty();
00267     d->attributesModel->setModelData(
00268         qVariantFromValue( la ),
00269         ThreeDLineAttributesRole );
00270    emit propertiesChanged();
00271 }
00272 
00276 void LineDiagram::setThreeDLineAttributes(
00277     int column,
00278     const ThreeDLineAttributes& la )
00279 {
00280     setDataBoundariesDirty();
00281     d->setDatasetAttrs( column, qVariantFromValue( la ), ThreeDLineAttributesRole );
00282    emit propertiesChanged();
00283 }
00284 
00288 void LineDiagram::setThreeDLineAttributes(
00289     const QModelIndex & index,
00290     const ThreeDLineAttributes& la )
00291 {
00292     setDataBoundariesDirty();
00293     d->attributesModel->setData(
00294         d->attributesModel->mapFromSource(index),
00295         qVariantFromValue( la ),
00296         ThreeDLineAttributesRole );
00297    emit propertiesChanged();
00298 }
00299 
00303 ThreeDLineAttributes LineDiagram::threeDLineAttributes() const
00304 {
00305     return qVariantValue<ThreeDLineAttributes>(
00306         d->attributesModel->data( KDChart::ThreeDLineAttributesRole ) );
00307 }
00308 
00312 ThreeDLineAttributes LineDiagram::threeDLineAttributes( int column ) const
00313 {
00314     const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
00315     if( attrs.isValid() )
00316         return qVariantValue< ThreeDLineAttributes >( attrs );
00317     return threeDLineAttributes();
00318 }
00319 
00323 ThreeDLineAttributes LineDiagram::threeDLineAttributes( const QModelIndex& index ) const
00324 {
00325     return qVariantValue<ThreeDLineAttributes>(
00326         d->attributesModel->data(
00327             d->attributesModel->mapFromSource( index ),
00328             KDChart::ThreeDLineAttributesRole ) );
00329 }
00330 
00331 qreal LineDiagram::threeDItemDepth( const QModelIndex& index ) const
00332 {
00333     return threeDLineAttributes( index ).validDepth();
00334 }
00335 
00336 qreal LineDiagram::threeDItemDepth( int column ) const
00337 {
00338     return threeDLineAttributes( column ).validDepth();
00339 }
00340 
00344 void LineDiagram::setValueTrackerAttributes( const QModelIndex & index,
00345                                              const ValueTrackerAttributes & va )
00346 {
00347     d->attributesModel->setData( d->attributesModel->mapFromSource(index),
00348                                  qVariantFromValue( va ),
00349                                  KDChart::ValueTrackerAttributesRole );
00350     emit propertiesChanged();
00351 }
00352 
00356 ValueTrackerAttributes LineDiagram::valueTrackerAttributes(
00357         const QModelIndex & index ) const
00358 {
00359     return qVariantValue<ValueTrackerAttributes>( d->attributesModel->data(
00360             d->attributesModel->mapFromSource( index ),
00361             KDChart::ValueTrackerAttributesRole ) );
00362 }
00363 
00364 void LineDiagram::resizeEvent ( QResizeEvent* )
00365 {
00366 }
00367 
00368 const QPair<QPointF, QPointF> LineDiagram::calculateDataBoundaries() const
00369 {
00370     d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
00371                                  static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
00372 
00373     if ( !checkInvariants( true ) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
00374 
00375     // note: calculateDataBoundaries() is ignoring the hidden flags.
00376     //       That's not a bug but a feature: Hiding data does not mean removing them.
00377     // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
00378 
00379     // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
00380     return d->implementor->calculateDataBoundaries();
00381 }
00382 
00383 
00384 void LineDiagram::paintEvent ( QPaintEvent*)
00385 {
00386     QPainter painter ( viewport() );
00387     PaintContext ctx;
00388     ctx.setPainter ( &painter );
00389     ctx.setRectangle ( QRectF ( 0, 0, width(), height() ) );
00390     paint ( &ctx );
00391 }
00392 
00393 
00394 qreal LineDiagram::valueForCellTesting( int row, int column,
00395                                          bool& bOK,
00396                                          bool showHiddenCellsAsInvalid ) const
00397 {
00398     if ( !model()->hasIndex( row, column, rootIndex() ) ) {
00399         bOK = false;
00400         return 0.0;
00401     }
00402     qreal value;
00403     if( showHiddenCellsAsInvalid && isHidden( model()->index( row, column, rootIndex() ) ) ) // checked
00404         bOK = false;
00405     else
00406         value = d->attributesModel->data(
00407                     d->attributesModel->index( row, column, attributesModelRootIndex() ) // checked
00408                 ).toReal( &bOK );
00409     return bOK ? value : 0.0;
00410 }
00411 
00412 LineAttributes::MissingValuesPolicy LineDiagram::getCellValues(
00413       int row, int column,
00414       bool shiftCountedXValuesByHalfSection,
00415       qreal& valueX, qreal& valueY ) const
00416 {
00417     LineAttributes::MissingValuesPolicy policy = LineAttributes::MissingValuesPolicyIgnored;
00418 
00419     bool bOK = true;
00420     valueX = ( datasetDimension() > 1 && column > 0 )
00421              ? valueForCellTesting( row, column-1, bOK, true )
00422              : ((shiftCountedXValuesByHalfSection ? 0.5 : 0.0) + row);
00423     if( bOK )
00424         valueY = valueForCellTesting( row, column, bOK, true );
00425     else if ( model()->hasIndex( row, column, rootIndex() ) ) {
00426         // missing value: find out the policy
00427         QModelIndex index = model()->index( row, column, rootIndex() ); // checked
00428         LineAttributes la = lineAttributes( index );
00429         policy = la.missingValuesPolicy();
00430     }
00431     return policy;
00432 }
00433 
00434 void LineDiagram::paint( PaintContext* ctx )
00435 {
00436     // note: Not having any data model assigned is no bug
00437     //       but we can not draw a diagram then either.
00438     if ( !checkInvariants( true ) ) return;
00439     if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
00440     const PainterSaver p( ctx->painter() );
00441     if( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
00442         return; // nothing to paint for us
00443 
00444     AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
00445     ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
00446 
00447 
00448     // paint different line types Normal - Stacked - Percent - Default Normal
00449     d->implementor->paint( ctx );
00450 
00451     ctx->setCoordinatePlane( plane );
00452 }
00453 
00454 void LineDiagram::resize ( const QSizeF& size )
00455 {
00456     d->compressor.setResolution( static_cast<int>( size.width() * coordinatePlane()->zoomFactorX() ),
00457                                  static_cast<int>( size.height() * coordinatePlane()->zoomFactorY() ) );
00458     setDataBoundariesDirty();
00459 }
00460 
00461 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00462 const
00463 #endif
00464 int LineDiagram::numberOfAbscissaSegments () const
00465 {
00466     return d->attributesModel->rowCount(attributesModelRootIndex());
00467 }
00468 
00469 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00470 const
00471 #endif
00472 int LineDiagram::numberOfOrdinateSegments () const
00473 {
00474     return d->attributesModel->columnCount(attributesModelRootIndex());
00475 }
 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/