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