diff --git a/src/KChart/Cartesian/KChartLeveyJenningsDiagram.cpp b/src/KChart/Cartesian/KChartLeveyJenningsDiagram.cpp
index e7ceba5..f6e4eaf 100644
--- a/src/KChart/Cartesian/KChartLeveyJenningsDiagram.cpp
+++ b/src/KChart/Cartesian/KChartLeveyJenningsDiagram.cpp
@@ -1,732 +1,737 @@
/*
* Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
*
* This file is part of the KD Chart library.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "KChartLeveyJenningsDiagram.h"
#include "KChartLeveyJenningsDiagram_p.h"
#include "KChartChart.h"
#include "KChartTextAttributes.h"
#include "KChartAbstractGrid.h"
#include "KChartPainterSaver_p.h"
#include
#include
#include
#include
#include
using namespace KChart;
using namespace std;
LeveyJenningsDiagram::Private::Private()
{
}
LeveyJenningsDiagram::Private::~Private() {}
#define d d_func()
LeveyJenningsDiagram::LeveyJenningsDiagram( QWidget* parent, LeveyJenningsCoordinatePlane* plane )
: LineDiagram( new Private(), parent, plane )
{
init();
}
void LeveyJenningsDiagram::init()
{
d->lotChangedPosition = Qt::AlignTop;
d->fluidicsPackChangedPosition = Qt::AlignBottom;
d->sensorChangedPosition = Qt::AlignBottom;
d->scanLinePen = QPen( Qt::blue );
setPen( d->scanLinePen );
d->expectedMeanValue = 0.0;
d->expectedStandardDeviation = 0.0;
d->diagram = this;
d->icons[ LotChanged ] = QString::fromLatin1( ":/KDE/kchart/LeveyJennings/karo_black.svg" );
d->icons[ SensorChanged ] = QString::fromLatin1( ":/KDE/kchart/LeveyJennings/karo_red.svg" );
d->icons[ FluidicsPackChanged ] = QString::fromLatin1( ":/KDE/kchart/LeveyJennings/karo_blue.svg" );
d->icons[ OkDataPoint ] = QString::fromLatin1( ":/KDE/kchart/LeveyJennings/circle_blue.svg" );
d->icons[ NotOkDataPoint ] = QString::fromLatin1( ":/KDE/kchart/LeveyJennings/circle_blue_red.svg" );
setSelectionMode( QAbstractItemView::SingleSelection );
}
LeveyJenningsDiagram::~LeveyJenningsDiagram()
{
}
/**
* Creates an exact copy of this diagram.
*/
LineDiagram * LeveyJenningsDiagram::clone() const
{
LeveyJenningsDiagram* newDiagram = new LeveyJenningsDiagram( new Private( *d ) );
return newDiagram;
}
bool LeveyJenningsDiagram::compare( const LeveyJenningsDiagram* other ) const
{
if ( other == this ) return true;
if ( ! other ) {
return false;
}
/*
qDebug() <<"\n LineDiagram::compare():";
// compare own properties
qDebug() << (type() == other->type());
*/
return // compare the base class
( static_cast(this)->compare( other ) );
}
/**
* Sets the position of the lot change symbol to \a pos.
* Valid values are: Qt::AlignTop (default), Qt::AlignBottom.
*/
void LeveyJenningsDiagram::setLotChangedSymbolPosition( Qt::Alignment pos )
{
if ( d->lotChangedPosition == pos )
return;
d->lotChangedPosition = pos;
update();
}
/**
* Returns the position of the lot change symbol.
*/
Qt::Alignment LeveyJenningsDiagram::lotChangedSymbolPosition() const
{
return d->lotChangedPosition;
}
/**
* Sets the position of the fluidics pack changed symbol to \a pos.
* Valid values are: Qt::AlignBottom (default), Qt::AlignTop.
*/
void LeveyJenningsDiagram::setFluidicsPackChangedSymbolPosition( Qt::Alignment pos )
{
if ( d->fluidicsPackChangedPosition == pos )
return;
d->fluidicsPackChangedPosition = pos;
update();
}
/**
* Returns the position of the fluidics pack changed symbol.
*/
Qt::Alignment LeveyJenningsDiagram::fluidicsPackChangedSymbolPosition() const
{
return d->fluidicsPackChangedPosition;
}
/**
* Sets the position of the sensor changed symbol to \a pos.
* Valid values are: Qt::AlignBottom (default), Qt::AlignTop.
*/
void LeveyJenningsDiagram::setSensorChangedSymbolPosition( Qt::Alignment pos )
{
if ( d->sensorChangedPosition == pos )
return;
d->sensorChangedPosition = pos;
update();
}
/**
* Returns the position of the sensor changed symbol.
*/
Qt::Alignment LeveyJenningsDiagram::sensorChangedSymbolPosition() const
{
return d->sensorChangedPosition;
}
/**
* Sets the date/time of all fluidics pack changes to \a changes.
*/
void LeveyJenningsDiagram::setFluidicsPackChanges( const QVector< QDateTime >& changes )
{
if ( d->fluidicsPackChanges == changes )
return;
d->fluidicsPackChanges = changes;
update();
}
/**
* Returns the list of all fluidics pack changes.
*/
QVector< QDateTime > LeveyJenningsDiagram::fluidicsPackChanges() const
{
return d->fluidicsPackChanges;
}
/**
* Sets the date/time of all sensor changes to \a changes.
*/
void LeveyJenningsDiagram::setSensorChanges( const QVector< QDateTime >& changes )
{
if ( d->sensorChanges == changes )
return;
d->sensorChanges = changes;
update();
}
/**
* Sets the pen used for drawing the scan line to \a pen
*/
void LeveyJenningsDiagram::setScanLinePen( const QPen& pen )
{
if ( d->scanLinePen == pen )
return;
d->scanLinePen = pen;
update();
}
/**
* Returns the pen being used for drawing the scan line.
*/
QPen LeveyJenningsDiagram::scanLinePen() const
{
return d->scanLinePen;
}
/**
* Returns the SVG file name usef for \a symbol
*/
QString LeveyJenningsDiagram::symbol( Symbol symbol ) const
{
return d->icons[ symbol ];
}
/**
* Sets the symbol being used for \a symbol to a SVG file \a filename.
*/
void LeveyJenningsDiagram::setSymbol( Symbol symbol, const QString& filename )
{
if ( d->icons[ symbol ] == filename )
return;
delete d->iconRenderer[ symbol ];
d->iconRenderer[ symbol ] = nullptr;
d->icons[ symbol ] = filename;
update();
}
/**
* Returns the list of all sensor changes.
*/
QVector< QDateTime > LeveyJenningsDiagram::sensorChanges() const
{
return d->sensorChanges;
}
/**
* Sets the expected mean value over all QC values to \a meanValue.
*/
void LeveyJenningsDiagram::setExpectedMeanValue( float meanValue )
{
if ( d->expectedMeanValue == meanValue )
return;
d->expectedMeanValue = meanValue;
d->setYAxisRange();
update();
}
/**
* Returns the expected mean values over all QC values.
*/
float LeveyJenningsDiagram::expectedMeanValue() const
{
return d->expectedMeanValue;
}
/**
* Sets the expected standard deviaction over all QC values to \a sd.
*/
void LeveyJenningsDiagram::setExpectedStandardDeviation( float sd )
{
if ( d->expectedStandardDeviation == sd )
return;
d->expectedStandardDeviation = sd;
d->setYAxisRange();
update();
}
/**
* Returns the expected standard deviation over all QC values.
*/
float LeveyJenningsDiagram::expectedStandardDeviation() const
{
return d->expectedStandardDeviation;
}
/**
* Returns the calculated mean values over all QC values.
*/
float LeveyJenningsDiagram::calculatedMeanValue() const
{
return d->calculatedMeanValue;
}
/**
* Returns the calculated standard deviation over all QC values.
*/
float LeveyJenningsDiagram::calculatedStandardDeviation() const
{
return d->calculatedStandardDeviation;
}
void LeveyJenningsDiagram::setModel( QAbstractItemModel* model )
{
if ( this->model() != nullptr )
{
disconnect( this->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(calculateMeanAndStandardDeviation()) );
disconnect( this->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
disconnect( this->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
disconnect( this->model(), SIGNAL(columnsInserted(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
disconnect( this->model(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
disconnect( this->model(), SIGNAL(modelReset()),
this, SLOT(calculateMeanAndStandardDeviation()) );
disconnect( this->model(), SIGNAL(layoutChanged()),
this, SLOT(calculateMeanAndStandardDeviation()) );
}
LineDiagram::setModel( model );
if ( this->model() != nullptr )
{
connect( this->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(calculateMeanAndStandardDeviation()) );
connect( this->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
connect( this->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
connect( this->model(), SIGNAL(columnsInserted(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
connect( this->model(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
this, SLOT(calculateMeanAndStandardDeviation()) );
connect( this->model(), SIGNAL(modelReset()),
this, SLOT(calculateMeanAndStandardDeviation()) );
connect( this->model(), SIGNAL(layoutChanged()),
this, SLOT(calculateMeanAndStandardDeviation()) );
calculateMeanAndStandardDeviation();
}
}
// TODO: This is the 'easy' solution
// evaluate whether this is enough or we need some better one or even boost here
void LeveyJenningsDiagram::calculateMeanAndStandardDeviation() const
{
QVector< qreal > values;
// first fetch all values
const QAbstractItemModel& m = *model();
const int rowCount = m.rowCount( rootIndex() );
for ( int row = 0; row < rowCount; ++row )
{
const QVariant var = m.data( m.index( row, 1, rootIndex() ) );
if ( !var.isValid() )
continue;
const qreal value = var.toReal();
if ( ISNAN( value ) )
continue;
values << value;
}
qreal sum = 0.0;
qreal sumSquares = 0.0;
Q_FOREACH( qreal value, values )
{
sum += value;
sumSquares += value * value;
}
const int N = values.count();
d->calculatedMeanValue = sum / N;
d->calculatedStandardDeviation = sqrt( ( static_cast< qreal >( N ) * sumSquares - sum * sum ) / ( N * ( N - 1 ) ) );
}
// calculates the largest QDate not greater than \a dt.
static QDate floorDay( const QDateTime& dt )
{
return dt.date();
}
// calculates the smallest QDate not less than \a dt.
static QDate ceilDay( const QDateTime& dt )
{
QDate result = dt.date();
if ( QDateTime( result, QTime() ) < dt )
result = result.addDays( 1 );
return result;
}
// calculates the largest QDateTime like xx:00 not greater than \a dt.
static QDateTime floorHour( const QDateTime& dt )
{
return QDateTime( dt.date(), QTime( dt.time().hour(), 0 ) );
}
// calculates the smallest QDateTime like xx:00 not less than \a dt.
static QDateTime ceilHour( const QDateTime& dt )
{
QDateTime result( dt.date(), QTime( dt.time().hour(), 0 ) );
if ( result < dt )
result = result.addSecs( 3600 );
return result;
}
/** \reimpl */
const QPair LeveyJenningsDiagram::calculateDataBoundaries() const
{
const qreal yMin = d->expectedMeanValue - 4 * d->expectedStandardDeviation;
const qreal yMax = d->expectedMeanValue + 4 * d->expectedStandardDeviation;
d->setYAxisRange();
// rounded down/up to the prev/next midnight (at least that's the default)
const QPair< QDateTime, QDateTime > range = timeRange();
const unsigned int minTime = range.first.toSecsSinceEpoch();
const unsigned int maxTime = range.second.toSecsSinceEpoch();
const qreal xMin = minTime / static_cast< qreal >( 24 * 60 * 60 );
const qreal xMax = maxTime / static_cast< qreal >( 24 * 60 * 60 ) - xMin;
const QPointF bottomLeft( QPointF( 0, yMin ) );
const QPointF topRight( QPointF( xMax, yMax ) );
return QPair< QPointF, QPointF >( bottomLeft, topRight );
}
/**
* Returns the timerange of the diagram's data.
*/
QPair< QDateTime, QDateTime > LeveyJenningsDiagram::timeRange() const
{
if ( d->timeRange != QPair< QDateTime, QDateTime >() )
return d->timeRange;
const QAbstractItemModel& m = *model();
const int rowCount = m.rowCount( rootIndex() );
const QDateTime begin = m.data( m.index( 0, 3, rootIndex() ) ).toDateTime();
const QDateTime end = m.data( m.index( rowCount - 1, 3, rootIndex() ) ).toDateTime();
if ( begin.secsTo( end ) > 86400 )
{
// if begin to end is more than 24h
// round down/up to the prev/next midnight
const QDate min = floorDay( begin );
const QDate max = ceilDay( end );
return QPair< QDateTime, QDateTime >( QDateTime( min ), QDateTime( max ) );
}
else if ( begin.secsTo( end ) > 3600 )
{
// more than 1h: rond down up to the prex/next hour
// if begin to end is more than 24h
const QDateTime min = floorHour( begin );
const QDateTime max = ceilHour( end );
return QPair< QDateTime, QDateTime >( min, max );
}
return QPair< QDateTime, QDateTime >( begin, end );
}
/**
* Sets the \a timeRange visible on the x axis. Set it to QPair< QDateTime, QDateTime >()
* to use the default auto calculation.
*/
void LeveyJenningsDiagram::setTimeRange( const QPair< QDateTime, QDateTime >& timeRange )
{
if ( d->timeRange == timeRange )
return;
d->timeRange = timeRange;
update();
}
/**
* Draws the fluidics pack and sensor changed symbols.
*/
void LeveyJenningsDiagram::drawChanges( PaintContext* ctx )
{
const unsigned int minTime = timeRange().first.toSecsSinceEpoch();
Q_FOREACH( const QDateTime& dt, d->fluidicsPackChanges )
{
const qreal xValue = ( dt.toSecsSinceEpoch() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
const QPointF point( xValue, 0.0 );
drawFluidicsPackChangedSymbol( ctx, point );
}
Q_FOREACH( const QDateTime& dt, d->sensorChanges )
{
const qreal xValue = ( dt.toSecsSinceEpoch() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
const QPointF point( xValue, 0.0 );
drawSensorChangedSymbol( ctx, point );
}
}
/** \reimpl */
void LeveyJenningsDiagram::paint( PaintContext* ctx )
{
d->reverseMapper.clear();
// note: Not having any data model assigned is no bug
// but we can not draw a diagram then either.
if ( !checkInvariants( true ) ) return;
if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
QPainter* const painter = ctx->painter();
const PainterSaver p( painter );
if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) < 4 )
return; // nothing to paint for us
AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( painter ) );
const QAbstractItemModel& m = *model();
const int rowCount = m.rowCount( rootIndex() );
const unsigned int minTime = timeRange().first.toSecsSinceEpoch();
painter->setRenderHint( QPainter::Antialiasing, true );
int prevLot = -1;
QPointF prevPoint;
bool hadMissingValue = false;
for ( int row = 0; row < rowCount; ++row )
{
const QModelIndex lotIndex = m.index( row, 0, rootIndex() );
const QModelIndex valueIndex = m.index( row, 1, rootIndex() );
const QModelIndex okIndex = m.index( row, 2, rootIndex() );
const QModelIndex timeIndex = m.index( row, 3, rootIndex() );
const QModelIndex expectedMeanIndex = m.index( row, 4, rootIndex() );
const QModelIndex expectedSDIndex = m.index( row, 5, rootIndex() );
painter->setPen( pen( lotIndex ) );
QVariant vValue = m.data( valueIndex );
qreal value = vValue.toReal();
const int lot = m.data( lotIndex ).toInt();
const bool ok = m.data( okIndex ).toBool();
const QDateTime time = m.data( timeIndex ).toDateTime();
const qreal xValue = ( time.toSecsSinceEpoch() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
QVariant vExpectedMean = m.data( expectedMeanIndex );
const qreal expectedMean = vExpectedMean.toReal();
QVariant vExpectedSD = m.data( expectedSDIndex );
const qreal expectedSD = vExpectedSD.toReal();
QPointF point = ctx->coordinatePlane()->translate( QPointF( xValue, value ) );
if ( vValue.isNull() )
{
hadMissingValue = true;
}
else
{
if ( !vExpectedMean.isNull() && !vExpectedSD.isNull() )
{
// this calculates the 'logical' value relative to the expected mean and SD of this point
value -= expectedMean;
value /= expectedSD;
value *= d->expectedStandardDeviation;
value += d->expectedMeanValue;
point = ctx->coordinatePlane()->translate( QPointF( xValue, value ) );
}
if ( prevLot == lot )
{
const QPen pen = painter->pen();
QPen newPen = pen;
if ( hadMissingValue )
{
newPen.setDashPattern( QVector< qreal >() << 4.0 << 4.0 );
}
painter->setPen( newPen );
painter->drawLine( prevPoint, point );
painter->setPen( pen );
// d->reverseMapper.addLine( valueIndex.row(), valueIndex.column(), prevPoint, point );
}
else if ( row > 0 )
{
drawLotChangeSymbol( ctx, QPointF( xValue, value ) );
}
if ( value <= d->expectedMeanValue + 4 * d->expectedStandardDeviation &&
value >= d->expectedMeanValue - 4 * d->expectedStandardDeviation )
{
const QPointF location( xValue, value );
drawDataPointSymbol( ctx, location, ok );
d->reverseMapper.addCircle( valueIndex.row(),
valueIndex.column(),
ctx->coordinatePlane()->translate( location ),
iconRect().size() );
}
prevLot = lot;
prevPoint = point;
hadMissingValue = false;
}
const QModelIndex current = selectionModel()->currentIndex();
if ( selectionModel()->rowIntersectsSelection( lotIndex.row(), lotIndex.parent() ) || current.sibling( current.row(), 0 ) == lotIndex )
{
const QPen pen = ctx->painter()->pen();
painter->setPen( d->scanLinePen );
painter->drawLine( ctx->coordinatePlane()->translate( QPointF( xValue, d->expectedMeanValue - 4 *
d->expectedStandardDeviation ) ),
ctx->coordinatePlane()->translate( QPointF( xValue, d->expectedMeanValue + 4 *
d->expectedStandardDeviation ) ) );
painter->setPen( pen );
}
}
drawChanges( ctx );
ctx->setCoordinatePlane( plane );
}
/**
* Draws a data point symbol for the data point at \a pos.
* @param ok True, when the data point is ok, false otherwise (different symbol)
* @param ctx The PaintContext being used
+ * @param pos Position
+ * @param ok Draw as Ok or notOK data point
*/
void LeveyJenningsDiagram::drawDataPointSymbol( PaintContext* ctx, const QPointF& pos, bool ok )
{
const Symbol type = ok ? OkDataPoint : NotOkDataPoint;
QPainter* const painter = ctx->painter();
const PainterSaver ps( painter );
const QPointF transPos = ctx->coordinatePlane()->translate( pos ).toPoint();
painter->translate( transPos );
painter->setClipping( false );
iconRenderer( type )->render( painter, iconRect() );
}
/**
* Draws a lot changed symbol for the data point at \a pos.
* @param ctx The PaintContext being used
+ * @param pos Position
* \sa lotChangedSymbolPosition
*/
void LeveyJenningsDiagram::drawLotChangeSymbol( PaintContext* ctx, const QPointF& pos )
{
const QPointF transPos = ctx->coordinatePlane()->translate(
QPointF( pos.x(), d->lotChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
4 * d->expectedStandardDeviation
: d->expectedMeanValue -
4 * d->expectedStandardDeviation ) );
QPainter* const painter = ctx->painter();
const PainterSaver ps( painter );
painter->setClipping( false );
painter->translate( transPos );
iconRenderer( LotChanged )->render( painter, iconRect() );
}
/**
* Draws a sensor changed symbol for the data point at \a pos.
* @param ctx The PaintContext being used
+ * @param pos Position
* \sa sensorChangedSymbolPosition
*/
void LeveyJenningsDiagram::drawSensorChangedSymbol( PaintContext* ctx, const QPointF& pos )
{
const QPointF transPos = ctx->coordinatePlane()->translate(
QPointF( pos.x(), d->sensorChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
4 * d->expectedStandardDeviation
: d->expectedMeanValue -
4 * d->expectedStandardDeviation ) );
QPainter* const painter = ctx->painter();
const PainterSaver ps( painter );
painter->setClipping( false );
painter->translate( transPos );
iconRenderer( SensorChanged )->render( painter, iconRect() );
}
/**
* Draws a fluidics pack changed symbol for the data point at \a pos.
* @param ctx The PaintContext being used
+ * @param pos Position
* \sa fluidicsPackChangedSymbolPosition
*/
void LeveyJenningsDiagram::drawFluidicsPackChangedSymbol( PaintContext* ctx, const QPointF& pos )
{
const QPointF transPos = ctx->coordinatePlane()->translate(
QPointF( pos.x(), d->fluidicsPackChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
4 * d->expectedStandardDeviation
: d->expectedMeanValue -
4 * d->expectedStandardDeviation ) );
QPainter* const painter = ctx->painter();
const PainterSaver ps( painter );
painter->setClipping( false );
painter->translate( transPos );
iconRenderer( FluidicsPackChanged )->render( painter, iconRect() );
}
/**
* Returns the rectangle being used for drawing the icons
*/
QRectF LeveyJenningsDiagram::iconRect() const
{
const Measure m( 12.5, KChartEnums::MeasureCalculationModeAuto, KChartEnums::MeasureOrientationAuto );
TextAttributes test;
test.setFontSize( m );
const QFontMetrics fm( test.calculatedFont( coordinatePlane()->parent(), KChartEnums::MeasureOrientationAuto ) );
const qreal height = fm.height() / 1.2;
return QRectF( -height / 2.0, -height / 2.0, height, height );
}
/**
* Returns the SVG icon renderer for \a symbol
*/
QSvgRenderer* LeveyJenningsDiagram::iconRenderer( Symbol symbol )
{
if ( d->iconRenderer[ symbol ] == nullptr )
d->iconRenderer[ symbol ] = new QSvgRenderer( d->icons[ symbol ], this );
return d->iconRenderer[ symbol ];
}
diff --git a/src/KChart/Cartesian/KChartLeveyJenningsDiagram.h b/src/KChart/Cartesian/KChartLeveyJenningsDiagram.h
index 4fa3e80..e9ee3ea 100644
--- a/src/KChart/Cartesian/KChartLeveyJenningsDiagram.h
+++ b/src/KChart/Cartesian/KChartLeveyJenningsDiagram.h
@@ -1,129 +1,129 @@
/*
* Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
*
* This file is part of the KD Chart library.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef KCHARTLEVEYJENNINGSDIAGRAM_H
#define KCHARTLEVEYJENNINGSDIAGRAM_H
#include "KChartLineDiagram.h"
#include "KChartLeveyJenningsCoordinatePlane.h"
QT_BEGIN_NAMESPACE
class QPainter;
class QPolygonF;
class QSvgRenderer;
QT_END_NAMESPACE
namespace KChart {
class ThreeDLineAttributes;
/**
* @brief LeveyDiagram defines a Levey Jennings chart.
*
* It provides different subtypes which are set using \a setType.
*/
class KCHART_EXPORT LeveyJenningsDiagram : public LineDiagram
{
Q_OBJECT
Q_DISABLE_COPY( LeveyJenningsDiagram )
// KCHART_DECLARE_PRIVATE_DERIVED_PARENT( LineDiagram, CartesianCoordinatePlane * )
KCHART_DECLARE_DERIVED_DIAGRAM( LeveyJenningsDiagram, LeveyJenningsCoordinatePlane )
public:
explicit LeveyJenningsDiagram( QWidget* parent = nullptr, LeveyJenningsCoordinatePlane* plane = nullptr );
virtual ~LeveyJenningsDiagram();
LineDiagram * clone() const override;
enum Symbol
{
OkDataPoint,
NotOkDataPoint,
LotChanged,
SensorChanged,
FluidicsPackChanged
};
/**
* Returns true if both diagrams have the same settings.
*/
bool compare( const LeveyJenningsDiagram* other ) const;
void setLotChangedSymbolPosition( Qt::Alignment pos );
Qt::Alignment lotChangedSymbolPosition() const;
void setFluidicsPackChangedSymbolPosition( Qt::Alignment pos );
Qt::Alignment fluidicsPackChangedSymbolPosition() const;
void setSensorChangedSymbolPosition( Qt::Alignment pos );
Qt::Alignment sensorChangedSymbolPosition() const;
void setExpectedMeanValue( float meanValue );
float expectedMeanValue() const;
void setExpectedStandardDeviation( float sd );
float expectedStandardDeviation() const;
float calculatedMeanValue() const;
float calculatedStandardDeviation() const;
void setFluidicsPackChanges( const QVector< QDateTime >& changes );
QVector< QDateTime > fluidicsPackChanges() const;
void setSensorChanges( const QVector< QDateTime >& changes );
QVector< QDateTime > sensorChanges() const;
void setScanLinePen( const QPen& pen );
QPen scanLinePen() const;
void setSymbol( Symbol symbol, const QString& filename );
QString symbol( Symbol symbol ) const;
/* \reimpl */
void setModel( QAbstractItemModel* model ) override;
QPair< QDateTime, QDateTime > timeRange() const;
void setTimeRange( const QPair< QDateTime, QDateTime >& timeRange );
protected:
void paint( PaintContext* paintContext ) override;
void drawChanges( PaintContext* paintContext );
virtual void drawDataPointSymbol( PaintContext* paintContext, const QPointF& pos, bool ok );
virtual void drawLotChangeSymbol( PaintContext* paintContext, const QPointF& pos );
virtual void drawSensorChangedSymbol( PaintContext* paintContext, const QPointF& pos );
virtual void drawFluidicsPackChangedSymbol( PaintContext* paintContext, const QPointF& pos );
virtual QRectF iconRect() const;
QSvgRenderer* iconRenderer( Symbol symbol );
- /** \reimpl */
+ /* \reimpl */
const QPair calculateDataBoundaries() const override;
protected Q_SLOTS:
void calculateMeanAndStandardDeviation() const;
}; // End of class KChartLineDiagram
}
#endif // KCHARTLINEDIAGRAM_H