KDChartLeveyJenningsDiagram.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2007 Klaralvdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Chart library.
00005  **
00006  ** This file may be distributed and/or modified under the terms of the
00007  ** GNU General Public License version 2 as published by the Free Software
00008  ** Foundtion and appearing in the file LICENSE.GPL included in the
00009  ** packaging of this file.
00010  **
00011  ** Licensees holding valid commercial KD Chart licenses may use this file in
00012  ** accordance with the KD Chart Commercial License Agreement provided with
00013  ** the Software.
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  ** See http://www.kdab.net/kdchart for
00019  **   information about KDChart Commercial License Agreements.
00020  **
00021  ** Contact info@kdab.net if any conditions of this
00022  ** licensing are not clear to you.
00023  **
00024  **********************************************************************/
00025 
00026 #include "KDChartLeveyJenningsDiagram.h"
00027 #include "KDChartLeveyJenningsDiagram_p.h"
00028 
00029 #include <QDateTime>
00030 #include <QFontMetrics>
00031 #include <QPainter>
00032 #include <QSvgRenderer>
00033 #include <QVector>
00034 
00035 #include "KDChartChart.h"
00036 #include "KDChartTextAttributes.h"
00037 #include "KDChartAbstractGrid.h"
00038 
00039 #include <KDABLibFakes>
00040 
00041 using namespace KDChart;
00042 using namespace std;
00043 
00044 LeveyJenningsDiagram::Private::Private()
00045 {
00046 }
00047 
00048 LeveyJenningsDiagram::Private::~Private() {}
00049 
00050 
00051 #define d d_func()
00052 
00053 
00054 LeveyJenningsDiagram::LeveyJenningsDiagram( QWidget* parent, LeveyJenningsCoordinatePlane* plane )
00055     : LineDiagram( new Private(), parent, plane )
00056 {
00057     init();
00058 }
00059 
00060 void LeveyJenningsDiagram::init()
00061 {
00062     d->lotChangedPosition = Qt::AlignTop;
00063     d->fluidicsPackChangedPosition = Qt::AlignBottom;
00064     d->sensorChangedPosition = Qt::AlignBottom;
00065 
00066     d->scanLinePen = QPen( Qt::blue );
00067     setPen( d->scanLinePen );
00068 
00069     d->expectedMeanValue = 0.0;
00070     d->expectedStandardDeviation = 0.0;
00071 
00072     d->diagram = this;
00073 
00074     d->icons[ LotChanged ] = QString::fromLatin1( ":/KDAB/kdchart/LeveyJennings/karo_black.svg" );
00075     d->icons[ SensorChanged ] = QString::fromLatin1( ":/KDAB/kdchart/LeveyJennings/karo_red.svg" );
00076     d->icons[ FluidicsPackChanged ] = QString::fromLatin1( ":/KDAB/kdchart/LeveyJennings/karo_blue.svg" );
00077     d->icons[ OkDataPoint ] = QString::fromLatin1( ":/KDAB/kdchart/LeveyJennings/circle_blue.svg" );
00078     d->icons[ NotOkDataPoint ] = QString::fromLatin1( ":/KDAB/kdchart/LeveyJennings/circle_blue_red.svg" );
00079 
00080     setSelectionMode( QAbstractItemView::SingleSelection );
00081 }
00082 
00083 LeveyJenningsDiagram::~LeveyJenningsDiagram()
00084 {
00085 }
00086 
00090 LineDiagram * LeveyJenningsDiagram::clone() const
00091 {
00092     LeveyJenningsDiagram* newDiagram = new LeveyJenningsDiagram( new Private( *d ) );
00093     return newDiagram;
00094 }
00095 
00096 bool LeveyJenningsDiagram::compare( const LeveyJenningsDiagram* other )const
00097 {
00098     if( other == this ) return true;
00099     if( ! other ){
00100         return false;
00101     }
00102     /*
00103     qDebug() <<"\n             LineDiagram::compare():";
00104             // compare own properties
00105     qDebug() << (type() == other->type());
00106     */
00107     return  // compare the base class
00108             ( static_cast<const LineDiagram*>(this)->compare( other ) );
00109 }
00110 
00115 void LeveyJenningsDiagram::setLotChangedSymbolPosition( Qt::Alignment pos )
00116 {
00117     if( d->lotChangedPosition == pos )
00118         return;
00119 
00120     d->lotChangedPosition = pos;
00121     update();
00122 }
00123 
00127 Qt::Alignment LeveyJenningsDiagram::lotChangedSymbolPosition() const
00128 {
00129     return d->lotChangedPosition;
00130 }
00131 
00136 void LeveyJenningsDiagram::setFluidicsPackChangedSymbolPosition( Qt::Alignment pos )
00137 {
00138     if( d->fluidicsPackChangedPosition == pos )
00139         return;
00140 
00141     d->fluidicsPackChangedPosition = pos;
00142     update();
00143 }
00144 
00148 Qt::Alignment LeveyJenningsDiagram::fluidicsPackChangedSymbolPosition() const
00149 {
00150     return d->fluidicsPackChangedPosition;
00151 }
00152 
00157 void LeveyJenningsDiagram::setSensorChangedSymbolPosition( Qt::Alignment pos )
00158 {
00159     if( d->sensorChangedPosition == pos )
00160         return;
00161 
00162     d->sensorChangedPosition = pos;
00163     update();
00164 }
00165 
00169 Qt::Alignment LeveyJenningsDiagram::sensorChangedSymbolPosition() const
00170 {
00171     return d->sensorChangedPosition;
00172 }
00173 
00177 void LeveyJenningsDiagram::setFluidicsPackChanges( const QVector< QDateTime >& changes )
00178 {
00179     if( d->fluidicsPackChanges == changes )
00180         return;
00181 
00182     d->fluidicsPackChanges = changes;
00183     update();
00184 }
00185 
00189 QVector< QDateTime > LeveyJenningsDiagram::fluidicsPackChanges() const
00190 {
00191     return d->fluidicsPackChanges;
00192 }
00193 
00197 void LeveyJenningsDiagram::setSensorChanges( const QVector< QDateTime >& changes )
00198 {
00199     if( d->sensorChanges == changes )
00200         return;
00201 
00202     d->sensorChanges = changes;
00203     update();
00204 }
00205 
00209 void LeveyJenningsDiagram::setScanLinePen( const QPen& pen )
00210 {
00211     if( d->scanLinePen == pen )
00212         return;
00213 
00214     d->scanLinePen = pen;
00215     update();
00216 }
00217 
00221 QPen LeveyJenningsDiagram::scanLinePen() const
00222 {
00223     return d->scanLinePen;
00224 }
00225 
00229 QString LeveyJenningsDiagram::symbol( Symbol symbol ) const
00230 {
00231     return d->icons[ symbol ];
00232 }
00233 
00237 void LeveyJenningsDiagram::setSymbol( Symbol symbol, const QString& filename )
00238 {
00239     if( d->icons[ symbol ] == filename )
00240         return;
00241 
00242     delete d->iconRenderer[ symbol ];
00243     d->iconRenderer[ symbol ] = 0;
00244 
00245     d->icons[ symbol ] = filename;
00246 
00247     update();
00248 }
00249 
00253 QVector< QDateTime > LeveyJenningsDiagram::sensorChanges() const
00254 {
00255     return d->sensorChanges;
00256 }
00257 
00261 void LeveyJenningsDiagram::setExpectedMeanValue( float meanValue )
00262 {
00263     if( d->expectedMeanValue == meanValue )
00264         return;
00265 
00266     d->expectedMeanValue = meanValue;
00267     d->setYAxisRange();
00268     update();
00269 }
00270 
00274 float LeveyJenningsDiagram::expectedMeanValue() const
00275 {
00276     return d->expectedMeanValue;
00277 }
00278 
00282 void LeveyJenningsDiagram::setExpectedStandardDeviation( float sd )
00283 {
00284     if( d->expectedStandardDeviation == sd )
00285         return;
00286 
00287     d->expectedStandardDeviation = sd;
00288     d->setYAxisRange();
00289     update();
00290 }
00291 
00295 float LeveyJenningsDiagram::expectedStandardDeviation() const
00296 {
00297     return d->expectedStandardDeviation;
00298 }
00299 
00303 float LeveyJenningsDiagram::calculatedMeanValue() const
00304 {
00305     return d->calculatedMeanValue;
00306 }
00307 
00311 float LeveyJenningsDiagram::calculatedStandardDeviation() const
00312 {
00313     return d->calculatedStandardDeviation;
00314 }
00315 
00316 void LeveyJenningsDiagram::setModel( QAbstractItemModel* model )
00317 {
00318     if( this->model() != 0 )
00319     {
00320         disconnect( this->model(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
00321                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00322         disconnect( this->model(), SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00323                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00324         disconnect( this->model(), SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
00325                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00326         disconnect( this->model(), SIGNAL( columnsInserted( const QModelIndex&, int, int ) ),
00327                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00328         disconnect( this->model(), SIGNAL( columnsRemoved( const QModelIndex&, int, int ) ),
00329                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00330         disconnect( this->model(), SIGNAL( modelReset() ),
00331                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00332         disconnect( this->model(), SIGNAL( layoutChanged() ),
00333                                    this, SLOT( calculateMeanAndStandardDeviation() ) );
00334     }
00335     LineDiagram::setModel( model );
00336     if( this->model() != 0 )
00337     {
00338         connect( this->model(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
00339                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00340         connect( this->model(), SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00341                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00342         connect( this->model(), SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
00343                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00344         connect( this->model(), SIGNAL( columnsInserted( const QModelIndex&, int, int ) ),
00345                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00346         connect( this->model(), SIGNAL( columnsRemoved( const QModelIndex&, int, int ) ),
00347                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00348         connect( this->model(), SIGNAL( modelReset() ),
00349                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00350         connect( this->model(), SIGNAL( layoutChanged() ),
00351                                 this, SLOT( calculateMeanAndStandardDeviation() ) );
00352 
00353         calculateMeanAndStandardDeviation();
00354     }
00355 }
00356 
00357 // TODO: This is the 'easy' solution
00358 // evaluate whether this is enough or we need some better one or even boost here
00359 void LeveyJenningsDiagram::calculateMeanAndStandardDeviation() const
00360 {
00361     QVector< double > values;
00362     // first fetch all values
00363     const QAbstractItemModel& m = *model();
00364     const int rowCount = m.rowCount( rootIndex() );
00365 
00366     for( int row = 0; row < rowCount; ++row )
00367     {
00368         const QVariant var = m.data( m.index( row, 1, rootIndex() ) );
00369         if( !var.isValid() )
00370             continue;
00371         const double value = var.toDouble();
00372         if( ISNAN( value ) )
00373             continue;
00374         values << value;
00375     }
00376 
00377     double sum = 0.0;
00378     double sumSquares = 0.0;
00379     KDAB_FOREACH( double value, values )
00380     {
00381         sum += value;
00382         sumSquares += value * value;
00383     }
00384 
00385     const int N = values.count();
00386 
00387     d->calculatedMeanValue = sum / N;
00388     d->calculatedStandardDeviation = sqrt( ( static_cast< double >( N ) * sumSquares - sum * sum ) / ( N * ( N - 1 ) ) );
00389 }
00390 
00391 // calculates the largest QDate not greater than \a dt.
00392 static QDate floorDay( const QDateTime& dt )
00393 {
00394     return dt.date();
00395 }
00396 
00397 // calculates the smallest QDate not less than \a dt.
00398 static QDate ceilDay( const QDateTime& dt )
00399 {
00400     QDate result = dt.date();
00401 
00402     if( QDateTime( result, QTime() ) < dt )
00403         result = result.addDays( 1 );
00404 
00405     return result;
00406 }
00407 
00408 // calculates the largest QDateTime like xx:00 not greater than \a dt.
00409 static QDateTime floorHour( const QDateTime& dt )
00410 {
00411     return QDateTime( dt.date(), QTime( dt.time().hour(), 0 ) );
00412 }
00413 
00414 // calculates the smallest QDateTime like xx:00 not less than \a dt.
00415 static QDateTime ceilHour( const QDateTime& dt )
00416 {
00417     QDateTime result( dt.date(), QTime( dt.time().hour(), 0 ) );
00418 
00419     if( result < dt )
00420         result = result.addSecs( 3600 );
00421 
00422     return result;
00423 }
00424 
00426 const QPair<QPointF, QPointF> LeveyJenningsDiagram::calculateDataBoundaries() const
00427 {
00428     const double yMin = d->expectedMeanValue - 4 * d->expectedStandardDeviation;
00429     const double yMax = d->expectedMeanValue + 4 * d->expectedStandardDeviation;
00430 
00431     d->setYAxisRange();
00432 
00433     // rounded down/up to the prev/next midnight (at least that's the default)
00434     const QPair< QDateTime, QDateTime > range = timeRange();
00435     const unsigned int minTime = range.first.toTime_t();
00436     const unsigned int maxTime = range.second.toTime_t();
00437 
00438     const double xMin = minTime / static_cast< double >( 24 * 60 * 60 );
00439     const double xMax = maxTime / static_cast< double >( 24 * 60 * 60 ) - xMin;
00440 
00441     const QPointF bottomLeft( QPointF( 0, yMin ) );
00442     const QPointF topRight( QPointF( xMax, yMax ) );
00443 
00444     return QPair< QPointF, QPointF >( bottomLeft, topRight );
00445 }
00446 
00450 QPair< QDateTime, QDateTime > LeveyJenningsDiagram::timeRange() const
00451 {
00452     if( d->timeRange != QPair< QDateTime, QDateTime >() )
00453         return d->timeRange;
00454 
00455     const QAbstractItemModel& m = *model();
00456     const int rowCount = m.rowCount( rootIndex() );
00457 
00458     const QDateTime begin = m.data( m.index( 0, 3, rootIndex() ) ).toDateTime();
00459     const QDateTime end = m.data( m.index( rowCount - 1, 3, rootIndex() ) ).toDateTime();
00460 
00461     if( begin.secsTo( end ) > 86400 )
00462     {
00463         // if begin to end is more than 24h
00464         // round down/up to the prev/next midnight
00465         const QDate min = floorDay( begin );
00466         const QDate max = ceilDay( end );
00467         return QPair< QDateTime, QDateTime >( QDateTime( min ), QDateTime( max ) );
00468     }
00469     else if( begin.secsTo( end ) > 3600 )
00470     {
00471         // more than 1h: rond down up to the prex/next hour
00472         // if begin to end is more than 24h
00473         const QDateTime min = floorHour( begin );
00474         const QDateTime max = ceilHour( end );
00475         return QPair< QDateTime, QDateTime >( min, max );
00476     }
00477     return QPair< QDateTime, QDateTime >( begin, end );
00478 }
00479 
00484 void LeveyJenningsDiagram::setTimeRange( const QPair< QDateTime, QDateTime >& timeRange )
00485 {
00486     if( d->timeRange == timeRange )
00487         return;
00488 
00489     d->timeRange = timeRange;
00490     update();
00491 }
00492 
00496 void LeveyJenningsDiagram::drawChanges( PaintContext* ctx )
00497 {
00498     const unsigned int minTime = timeRange().first.toTime_t();
00499 
00500     KDAB_FOREACH( const QDateTime& dt, d->fluidicsPackChanges )
00501     {
00502         const double xValue = ( dt.toTime_t() - minTime ) / static_cast< double >( 24 * 60 * 60 );
00503         const QPointF point( xValue, 0.0 );
00504         drawFluidicsPackChangedSymbol( ctx, point );
00505     }
00506 
00507     KDAB_FOREACH( const QDateTime& dt, d->sensorChanges )
00508     {
00509         const double xValue = ( dt.toTime_t() - minTime ) / static_cast< double >( 24 * 60 * 60 );
00510         const QPointF point( xValue, 0.0 );
00511         drawSensorChangedSymbol( ctx, point );
00512     }
00513 }
00514 
00516 void LeveyJenningsDiagram::paint( PaintContext* ctx )
00517 {
00518     d->reverseMapper.clear();
00519 
00520     // note: Not having any data model assigned is no bug
00521     //       but we can not draw a diagram then either.
00522     if ( !checkInvariants( true ) ) return;
00523     if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
00524 
00525     QPainter* const painter = ctx->painter();
00526     const PainterSaver p( painter );
00527     if( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) < 4 )
00528         return; // nothing to paint for us
00529 
00530     AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
00531     ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( painter ) );
00532 
00533     const QAbstractItemModel& m = *model();
00534     const int rowCount = m.rowCount( rootIndex() );
00535 
00536     const unsigned int minTime = timeRange().first.toTime_t();
00537 
00538     painter->setRenderHint( QPainter::Antialiasing, true );
00539 
00540     int prevLot = -1;
00541     QPointF prevPoint;
00542     bool hadMissingValue = false;
00543 
00544     for( int row = 0; row < rowCount; ++row )
00545     {
00546         const QModelIndex lotIndex = m.index( row, 0, rootIndex() );
00547         const QModelIndex valueIndex = m.index( row, 1, rootIndex() );
00548         const QModelIndex okIndex = m.index( row, 2, rootIndex() );
00549         const QModelIndex timeIndex = m.index( row, 3, rootIndex() );
00550         const QModelIndex expectedMeanIndex = m.index( row, 4, rootIndex() );
00551         const QModelIndex expectedSDIndex = m.index( row, 5, rootIndex() );
00552 
00553         painter->setPen( pen( lotIndex ) );
00554 
00555         const int lot = m.data( lotIndex ).toInt();
00556         double value = m.data( valueIndex ).toDouble();
00557         const bool ok = m.data( okIndex ).toBool();
00558         const QDateTime time = m.data( timeIndex ).toDateTime();
00559         const double xValue = ( time.toTime_t() - minTime ) / static_cast< double >( 24 * 60 * 60 );
00560 
00561         const double expectedMean = m.data( expectedMeanIndex ).toDouble();
00562         const double expectedSD = m.data( expectedSDIndex ).toDouble();
00563 
00564         QPointF point = ctx->coordinatePlane()->translate( QPointF( xValue, value ) );
00565 
00566         if( static_cast< int >( value ) == 0 )
00567         {
00568             hadMissingValue = true;
00569         }
00570         else
00571         {
00572             if( static_cast< int >( expectedMean ) != 0 && static_cast< int >( expectedSD ) != 0 )
00573             {
00574                 // this calculates the 'logical' value relative to the expected mean and SD of this point
00575                 value -= expectedMean;
00576                 value /= expectedSD;
00577                 value *= d->expectedStandardDeviation;
00578                 value += d->expectedMeanValue;
00579                 point = ctx->coordinatePlane()->translate( QPointF( xValue, value ) );
00580             }
00581 
00582             if( prevLot == lot )
00583             {
00584                 const QPen pen = painter->pen();
00585                 QPen newPen = pen;
00586 
00587                 if( hadMissingValue )
00588                 {
00589                     newPen.setDashPattern( QVector< qreal >() << 4.0 << 4.0 );
00590                 }
00591 
00592                 painter->setPen( newPen );
00593                 painter->drawLine( prevPoint, point );
00594                 painter->setPen( pen );
00595                 // d->reverseMapper.addLine( valueIndex.row(), valueIndex.column(), prevPoint, point );
00596             }
00597             else if( row > 0 )
00598             {
00599                 drawLotChangeSymbol( ctx, QPointF( xValue, value ) );
00600             }
00601 
00602             if( value <= d->expectedMeanValue + 4 * d->expectedStandardDeviation &&
00603                 value >= d->expectedMeanValue - 4 * d->expectedStandardDeviation )
00604             {
00605                 const QPointF location( xValue, value );
00606                 drawDataPointSymbol( ctx, location, ok );
00607                 d->reverseMapper.addCircle( valueIndex.row(),
00608                                             valueIndex.column(),
00609                                             ctx->coordinatePlane()->translate( location ),
00610                                             iconRect().size() );
00611             }
00612             prevLot = lot;
00613             prevPoint = point;
00614             hadMissingValue = false;
00615         }
00616 
00617         const QModelIndex current = selectionModel()->currentIndex();
00618         if( selectionModel()->rowIntersectsSelection( lotIndex.row(), lotIndex.parent() ) || current.sibling( current.row(), 0 ) == lotIndex )
00619         {
00620             const QPen pen = ctx->painter()->pen();
00621             painter->setPen( d->scanLinePen );
00622             painter->drawLine( ctx->coordinatePlane()->translate( QPointF( xValue, d->expectedMeanValue - 4 *
00623                                                                                    d->expectedStandardDeviation ) ),
00624                                ctx->coordinatePlane()->translate( QPointF( xValue, d->expectedMeanValue + 4 *
00625                                                                                    d->expectedStandardDeviation ) ) );
00626             painter->setPen( pen );
00627         }
00628     }
00629 
00630     drawChanges( ctx );
00631 
00632     ctx->setCoordinatePlane( plane );
00633 }
00634 
00640 void LeveyJenningsDiagram::drawDataPointSymbol( PaintContext* ctx, const QPointF& pos, bool ok )
00641 {
00642     const Symbol type = ok ? OkDataPoint : NotOkDataPoint;
00643 
00644     QPainter* const painter = ctx->painter();
00645     const PainterSaver ps( painter );
00646     const QPointF transPos = ctx->coordinatePlane()->translate( pos ).toPoint();
00647     painter->translate( transPos );
00648 
00649     painter->setClipping( false );
00650     iconRenderer( type )->render( painter, iconRect() );
00651 }
00652 
00658 void LeveyJenningsDiagram::drawLotChangeSymbol( PaintContext* ctx, const QPointF& pos )
00659 {
00660     const QPointF transPos = ctx->coordinatePlane()->translate(
00661         QPointF( pos.x(), d->lotChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
00662                                                                  4 * d->expectedStandardDeviation
00663                                                                : d->expectedMeanValue -
00664                                                                  4 * d->expectedStandardDeviation ) );
00665 
00666 
00667     QPainter* const painter = ctx->painter();
00668     const PainterSaver ps( painter );
00669     painter->setClipping( false );
00670     painter->translate( transPos );
00671     iconRenderer( LotChanged )->render( painter, iconRect() );
00672 }
00673 
00679 void LeveyJenningsDiagram::drawSensorChangedSymbol( PaintContext* ctx, const QPointF& pos )
00680 {
00681     const QPointF transPos = ctx->coordinatePlane()->translate(
00682         QPointF( pos.x(), d->sensorChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
00683                                                                     4 * d->expectedStandardDeviation
00684                                                                   : d->expectedMeanValue -
00685                                                                     4 * d->expectedStandardDeviation ) );
00686 
00687     QPainter* const painter = ctx->painter();
00688     const PainterSaver ps( painter );
00689     painter->setClipping( false );
00690     painter->translate( transPos );
00691     iconRenderer( SensorChanged )->render( painter, iconRect() );
00692 }
00693 
00699 void LeveyJenningsDiagram::drawFluidicsPackChangedSymbol( PaintContext* ctx, const QPointF& pos )
00700 {
00701     const QPointF transPos = ctx->coordinatePlane()->translate(
00702         QPointF( pos.x(), d->fluidicsPackChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
00703                                                                           4 * d->expectedStandardDeviation
00704                                                                         : d->expectedMeanValue -
00705                                                                           4 * d->expectedStandardDeviation ) );
00706 
00707     QPainter* const painter = ctx->painter();
00708     const PainterSaver ps( painter );
00709     painter->setClipping( false );
00710     painter->translate( transPos );
00711     iconRenderer( FluidicsPackChanged )->render( painter, iconRect() );
00712 }
00713 
00717 QRectF LeveyJenningsDiagram::iconRect() const
00718 {
00719     const Measure m( 12.5, KDChartEnums::MeasureCalculationModeAuto, KDChartEnums::MeasureOrientationAuto );
00720     TextAttributes test;
00721     test.setFontSize( m );
00722     const QFontMetrics fm( test.calculatedFont( coordinatePlane()->parent(), KDChartEnums::MeasureOrientationAuto ) );
00723     const qreal height = fm.height() / 1.2;
00724     return QRectF( -height / 2.0, -height / 2.0, height, height );
00725 }
00726 
00730 QSvgRenderer* LeveyJenningsDiagram::iconRenderer( Symbol symbol )
00731 {
00732     if( d->iconRenderer[ symbol ] == 0 )
00733         d->iconRenderer[ symbol ] = new QSvgRenderer( d->icons[ symbol ], this );
00734 
00735     return d->iconRenderer[ symbol ];
00736 }

Generated on Thu Mar 4 23:19:11 2010 for KD Chart 2 by  doxygen 1.5.4