24 #include "KDChartLeveyJenningsDiagram_p.h" 28 #include "KDChartAbstractGrid.h" 29 #include "KDChartPainterSaver_p.h" 32 #include <QFontMetrics> 34 #include <QSvgRenderer> 37 #include <KDABLibFakes> 42 LeveyJenningsDiagram::Private::Private()
46 LeveyJenningsDiagram::Private::~Private() {}
58 void LeveyJenningsDiagram::init()
60 d->lotChangedPosition = Qt::AlignTop;
61 d->fluidicsPackChangedPosition = Qt::AlignBottom;
62 d->sensorChangedPosition = Qt::AlignBottom;
64 d->scanLinePen = QPen( Qt::blue );
67 d->expectedMeanValue = 0.0;
68 d->expectedStandardDeviation = 0.0;
72 d->icons[
LotChanged ] = QString::fromLatin1(
":/KDAB/kdchart/LeveyJennings/karo_black.svg" );
73 d->icons[
SensorChanged ] = QString::fromLatin1(
":/KDAB/kdchart/LeveyJennings/karo_red.svg" );
74 d->icons[
FluidicsPackChanged ] = QString::fromLatin1(
":/KDAB/kdchart/LeveyJennings/karo_blue.svg" );
75 d->icons[
OkDataPoint ] = QString::fromLatin1(
":/KDAB/kdchart/LeveyJennings/circle_blue.svg" );
76 d->icons[
NotOkDataPoint ] = QString::fromLatin1(
":/KDAB/kdchart/LeveyJennings/circle_blue_red.svg" );
78 setSelectionMode( QAbstractItemView::SingleSelection );
96 if ( other ==
this )
return true;
115 if (
d->lotChangedPosition == pos )
118 d->lotChangedPosition = pos;
127 return d->lotChangedPosition;
136 if (
d->fluidicsPackChangedPosition == pos )
139 d->fluidicsPackChangedPosition = pos;
148 return d->fluidicsPackChangedPosition;
157 if (
d->sensorChangedPosition == pos )
160 d->sensorChangedPosition = pos;
169 return d->sensorChangedPosition;
177 if (
d->fluidicsPackChanges == changes )
180 d->fluidicsPackChanges = changes;
189 return d->fluidicsPackChanges;
197 if (
d->sensorChanges == changes )
200 d->sensorChanges = changes;
209 if (
d->scanLinePen == pen )
212 d->scanLinePen =
pen;
221 return d->scanLinePen;
237 if (
d->icons[ symbol ] == filename )
240 delete d->iconRenderer[
symbol ];
253 return d->sensorChanges;
261 if (
d->expectedMeanValue == meanValue )
264 d->expectedMeanValue = meanValue;
274 return d->expectedMeanValue;
282 if (
d->expectedStandardDeviation == sd )
285 d->expectedStandardDeviation = sd;
295 return d->expectedStandardDeviation;
303 return d->calculatedMeanValue;
311 return d->calculatedStandardDeviation;
316 if ( this->model() != 0 )
318 disconnect( this->model(), SIGNAL(
dataChanged(
const QModelIndex&,
const QModelIndex& ) ),
320 disconnect( this->model(), SIGNAL( rowsInserted(
const QModelIndex&,
int,
int ) ),
322 disconnect( this->model(), SIGNAL( rowsRemoved(
const QModelIndex&,
int,
int ) ),
324 disconnect( this->model(), SIGNAL( columnsInserted(
const QModelIndex&,
int,
int ) ),
326 disconnect( this->model(), SIGNAL( columnsRemoved(
const QModelIndex&,
int,
int ) ),
328 disconnect( this->model(), SIGNAL( modelReset() ),
334 if ( this->model() != 0 )
336 connect( this->model(), SIGNAL(
dataChanged(
const QModelIndex&,
const QModelIndex& ) ),
338 connect( this->model(), SIGNAL( rowsInserted(
const QModelIndex&,
int,
int ) ),
340 connect( this->model(), SIGNAL( rowsRemoved(
const QModelIndex&,
int,
int ) ),
342 connect( this->model(), SIGNAL( columnsInserted(
const QModelIndex&,
int,
int ) ),
344 connect( this->model(), SIGNAL( columnsRemoved(
const QModelIndex&,
int,
int ) ),
346 connect( this->model(), SIGNAL( modelReset() ),
361 const QAbstractItemModel& m = *model();
362 const int rowCount = m.rowCount( rootIndex() );
364 for (
int row = 0; row < rowCount; ++row )
366 const QVariant var = m.data( m.index( row, 1, rootIndex() ) );
367 if ( !var.isValid() )
369 const qreal value = var.toReal();
370 if ( ISNAN( value ) )
376 qreal sumSquares = 0.0;
377 KDAB_FOREACH( qreal value, values )
380 sumSquares += value * value;
383 const int N = values.count();
385 d->calculatedMeanValue = sum / N;
386 d->calculatedStandardDeviation = sqrt( ( static_cast< qreal >( N ) * sumSquares - sum * sum ) / ( N * ( N - 1 ) ) );
398 QDate result = dt.date();
400 if ( QDateTime( result, QTime() ) < dt )
401 result = result.addDays( 1 );
409 return QDateTime( dt.date(), QTime( dt.time().hour(), 0 ) );
415 QDateTime result( dt.date(), QTime( dt.time().hour(), 0 ) );
418 result = result.addSecs( 3600 );
426 const qreal yMin =
d->expectedMeanValue - 4 *
d->expectedStandardDeviation;
427 const qreal yMax =
d->expectedMeanValue + 4 *
d->expectedStandardDeviation;
433 const unsigned int minTime = range.first.toTime_t();
434 const unsigned int maxTime = range.second.toTime_t();
436 const qreal xMin = minTime /
static_cast< qreal
>( 24 * 60 * 60 );
437 const qreal xMax = maxTime /
static_cast< qreal
>( 24 * 60 * 60 ) - xMin;
439 const QPointF bottomLeft( QPointF( 0, yMin ) );
440 const QPointF topRight( QPointF( xMax, yMax ) );
453 const QAbstractItemModel& m = *model();
454 const int rowCount = m.rowCount( rootIndex() );
456 const QDateTime begin = m.data( m.index( 0, 3, rootIndex() ) ).toDateTime();
457 const QDateTime end = m.data( m.index( rowCount - 1, 3, rootIndex() ) ).toDateTime();
459 if ( begin.secsTo( end ) > 86400 )
463 const QDate min =
floorDay( begin );
464 const QDate max =
ceilDay( end );
467 else if ( begin.secsTo( end ) > 3600 )
471 const QDateTime min =
floorHour( begin );
472 const QDateTime max =
ceilHour( end );
484 if (
d->timeRange == timeRange )
496 const unsigned int minTime =
timeRange().first.toTime_t();
498 KDAB_FOREACH(
const QDateTime& dt,
d->fluidicsPackChanges )
500 const qreal xValue = ( dt.toTime_t() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
501 const QPointF point( xValue, 0.0 );
505 KDAB_FOREACH(
const QDateTime& dt,
d->sensorChanges )
507 const qreal xValue = ( dt.toTime_t() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
508 const QPointF point( xValue, 0.0 );
516 d->reverseMapper.clear();
523 QPainter*
const painter = ctx->
painter();
524 const PainterSaver p( painter );
525 if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) < 4 )
531 const QAbstractItemModel& m = *model();
532 const int rowCount = m.rowCount( rootIndex() );
534 const unsigned int minTime =
timeRange().first.toTime_t();
536 painter->setRenderHint( QPainter::Antialiasing,
true );
540 bool hadMissingValue =
false;
542 for (
int row = 0; row < rowCount; ++row )
544 const QModelIndex lotIndex = m.index( row, 0, rootIndex() );
545 const QModelIndex valueIndex = m.index( row, 1, rootIndex() );
546 const QModelIndex okIndex = m.index( row, 2, rootIndex() );
547 const QModelIndex timeIndex = m.index( row, 3, rootIndex() );
548 const QModelIndex expectedMeanIndex = m.index( row, 4, rootIndex() );
549 const QModelIndex expectedSDIndex = m.index( row, 5, rootIndex() );
551 painter->setPen(
pen( lotIndex ) );
553 QVariant vValue = m.data( valueIndex );
554 qreal value = vValue.toReal();
555 const int lot = m.data( lotIndex ).toInt();
556 const bool ok = m.data( okIndex ).toBool();
557 const QDateTime time = m.data( timeIndex ).toDateTime();
558 const qreal xValue = ( time.toTime_t() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
560 QVariant vExpectedMean = m.data( expectedMeanIndex );
561 const qreal expectedMean = vExpectedMean.toReal();
562 QVariant vExpectedSD = m.data( expectedSDIndex );
563 const qreal expectedSD = vExpectedSD.toReal();
567 if ( vValue.isNull() )
569 hadMissingValue =
true;
573 if ( !vExpectedMean.isNull() && !vExpectedSD.isNull() )
576 value -= expectedMean;
578 value *=
d->expectedStandardDeviation;
579 value +=
d->expectedMeanValue;
583 if ( prevLot == lot )
585 const QPen
pen = painter->pen();
588 if ( hadMissingValue )
593 painter->setPen( newPen );
594 painter->drawLine( prevPoint, point );
595 painter->setPen( pen );
604 value >=
d->expectedMeanValue - 4 *
d->expectedStandardDeviation )
606 const QPointF location( xValue, value );
608 d->reverseMapper.addCircle( valueIndex.row(),
615 hadMissingValue =
false;
618 const QModelIndex current = selectionModel()->currentIndex();
619 if ( selectionModel()->rowIntersectsSelection( lotIndex.row(), lotIndex.parent() ) || current.sibling( current.row(), 0 ) == lotIndex )
622 painter->setPen(
d->scanLinePen );
624 d->expectedStandardDeviation ) ),
626 d->expectedStandardDeviation ) ) );
627 painter->setPen( pen );
645 QPainter*
const painter = ctx->
painter();
646 const PainterSaver ps( painter );
648 painter->translate( transPos );
650 painter->setClipping(
false );
662 QPointF( pos.x(),
d->lotChangedPosition & Qt::AlignTop ?
d->expectedMeanValue +
663 4 *
d->expectedStandardDeviation
664 :
d->expectedMeanValue -
665 4 *
d->expectedStandardDeviation ) );
668 QPainter*
const painter = ctx->
painter();
669 const PainterSaver ps( painter );
670 painter->setClipping(
false );
671 painter->translate( transPos );
683 QPointF( pos.x(),
d->sensorChangedPosition & Qt::AlignTop ?
d->expectedMeanValue +
684 4 *
d->expectedStandardDeviation
685 :
d->expectedMeanValue -
686 4 *
d->expectedStandardDeviation ) );
688 QPainter*
const painter = ctx->
painter();
689 const PainterSaver ps( painter );
690 painter->setClipping(
false );
691 painter->translate( transPos );
703 QPointF( pos.x(),
d->fluidicsPackChangedPosition & Qt::AlignTop ?
d->expectedMeanValue +
704 4 *
d->expectedStandardDeviation
705 :
d->expectedMeanValue -
706 4 *
d->expectedStandardDeviation ) );
708 QPainter*
const painter = ctx->
painter();
709 const PainterSaver ps( painter );
710 painter->setClipping(
false );
711 painter->translate( transPos );
724 const qreal height = fm.height() / 1.2;
725 return QRectF( -height / 2.0, -height / 2.0, height, height );
733 if (
d->iconRenderer[ symbol ] == 0 )
734 d->iconRenderer[
symbol ] =
new QSvgRenderer(
d->icons[ symbol ],
this );
736 return d->iconRenderer[
symbol ];
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane, TernaryCoordinatePlane.
void setExpectedStandardDeviation(float sd)
Sets the expected standard deviaction over all QC values to sd.
virtual AbstractCoordinatePlane * sharedAxisMasterPlane(QPainter *p=0)
QPair< QDateTime, QDateTime > timeRange() const
Returns the timerange of the diagram's data.
LeveyJenningsDiagram(QWidget *parent=0, LeveyJenningsCoordinatePlane *plane=0)
virtual bool checkInvariants(bool justReturnTheStatus=false) const
Qt::Alignment fluidicsPackChangedSymbolPosition() const
Returns the position of the fluidics pack changed symbol.
virtual const QPointF translate(const QPointF &diagramPoint) const =0
Translate the given point in value space coordinates to a position in pixel space.
AbstractCoordinatePlane * coordinatePlane() const
void drawChanges(PaintContext *paintContext)
Draws the fluidics pack and sensor changed symbols.
QVector< QDateTime > fluidicsPackChanges() const
Returns the list of all fluidics pack changes.
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
[reimplemented]
void setExpectedMeanValue(float meanValue)
Sets the expected mean value over all QC values to meanValue.
Qt::Alignment lotChangedSymbolPosition() const
Returns the position of the lot change symbol.
QPainter * painter() const
static QDateTime floorHour(const QDateTime &dt)
void setLotChangedSymbolPosition(Qt::Alignment pos)
Sets the position of the lot change symbol to pos.
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
void paint(PaintContext *paintContext) override
[reimplemented]
void setSymbol(Symbol symbol, const QString &filename)
Sets the symbol being used for symbol to a SVG file filename.
Levey Jennings coordinate plane This is actually nothing real more than a plain cartesian coordinate ...
QVector< QDateTime > sensorChanges() const
Returns the list of all sensor changes.
void setFluidicsPackChanges(const QVector< QDateTime > &changes)
Sets the date/time of all fluidics pack changes to changes.
LineDiagram * clone() const override
Creates an exact copy of this diagram.
void setPen(const QModelIndex &index, const QPen &pen)
Set the pen to be used, for painting the datapoint at the given index.
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
QPen scanLinePen() const
Returns the pen being used for drawing the scan line.
void setFluidicsPackChangedSymbolPosition(Qt::Alignment pos)
Sets the position of the fluidics pack changed symbol to pos.
LeveyDiagram defines a Levey Jennings chart.
virtual void drawFluidicsPackChangedSymbol(PaintContext *paintContext, const QPointF &pos)
Draws a fluidics pack changed symbol for the data point at pos.
static QDate ceilDay(const QDateTime &dt)
void setModel(QAbstractItemModel *model) override
~LeveyJenningsDiagram() override
void setFontSize(const Measure &measure)
Set the size of the font used for rendering text.
float calculatedStandardDeviation() const
Returns the calculated standard deviation over all QC values.
void setScanLinePen(const QPen &pen)
Sets the pen used for drawing the scan line to pen.
void setSensorChanges(const QVector< QDateTime > &changes)
Sets the date/time of all sensor changes to changes.
const QFont calculatedFont(const QObject *autoReferenceArea, KDChartEnums::MeasureOrientation autoReferenceOrientation) const
Returns the font in the size that is used at drawing time.
LineDiagram defines a common line diagram.
float expectedStandardDeviation() const
Returns the expected standard deviation over all QC values.
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
[reimplemented]
QString symbol(Symbol symbol) const
Returns the SVG file name usef for symbol.
void setModel(QAbstractItemModel *model) override
bool compare(const LeveyJenningsDiagram *other) const
Returns true if both diagrams have the same settings.
Stores information about painting diagrams.
void setTimeRange(const QPair< QDateTime, QDateTime > &timeRange)
Sets the timeRange visible on the x axis.
virtual QRectF iconRect() const
Returns the rectangle being used for drawing the icons.
QPen pen() const
Retrieve the pen to be used for painting datapoints globally.
Qt::Alignment sensorChangedSymbolPosition() const
Returns the position of the sensor changed symbol.
void layoutChanged(AbstractDiagram *)
Diagrams are supposed to emit this signal, when the layout of one of their element changes...
virtual void drawDataPointSymbol(PaintContext *paintContext, const QPointF &pos, bool ok)
Draws a data point symbol for the data point at pos.
Measure is used to specify relative and absolute sizes in KDChart, e.g.
static QDate floorDay(const QDateTime &dt)
void calculateMeanAndStandardDeviation() const
virtual void drawSensorChangedSymbol(PaintContext *paintContext, const QPointF &pos)
Draws a sensor changed symbol for the data point at pos.
void setCoordinatePlane(AbstractCoordinatePlane *plane)
void setSensorChangedSymbolPosition(Qt::Alignment pos)
Sets the position of the sensor changed symbol to pos.
virtual void drawLotChangeSymbol(PaintContext *paintContext, const QPointF &pos)
Draws a lot changed symbol for the data point at pos.
float expectedMeanValue() const
Returns the expected mean values over all QC values.
QSvgRenderer * iconRenderer(Symbol symbol)
Returns the SVG icon renderer for symbol.
float calculatedMeanValue() const
Returns the calculated mean values over all QC values.
A set of text attributes.
static QDateTime ceilHour(const QDateTime &dt)