KD Chart 2  [rev.2.7]
KDChartLeveyJenningsDiagram.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
24 #include "KDChartLeveyJenningsDiagram_p.h"
25 
26 #include "KDChartChart.h"
27 #include "KDChartTextAttributes.h"
28 #include "KDChartAbstractGrid.h"
29 #include "KDChartPainterSaver_p.h"
30 
31 #include <QDateTime>
32 #include <QFontMetrics>
33 #include <QPainter>
34 #include <QSvgRenderer>
35 #include <QVector>
36 
37 #include <KDABLibFakes>
38 
39 using namespace KDChart;
40 using namespace std;
41 
42 LeveyJenningsDiagram::Private::Private()
43 {
44 }
45 
46 LeveyJenningsDiagram::Private::~Private() {}
47 
48 
49 #define d d_func()
50 
51 
53  : LineDiagram( new Private(), parent, plane )
54 {
55  init();
56 }
57 
58 void LeveyJenningsDiagram::init()
59 {
60  d->lotChangedPosition = Qt::AlignTop;
61  d->fluidicsPackChangedPosition = Qt::AlignBottom;
62  d->sensorChangedPosition = Qt::AlignBottom;
63 
64  d->scanLinePen = QPen( Qt::blue );
65  setPen( d->scanLinePen );
66 
67  d->expectedMeanValue = 0.0;
68  d->expectedStandardDeviation = 0.0;
69 
70  d->diagram = this;
71 
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" );
77 
78  setSelectionMode( QAbstractItemView::SingleSelection );
79 }
80 
82 {
83 }
84 
89 {
90  LeveyJenningsDiagram* newDiagram = new LeveyJenningsDiagram( new Private( *d ) );
91  return newDiagram;
92 }
93 
95 {
96  if ( other == this ) return true;
97  if ( ! other ) {
98  return false;
99  }
100  /*
101  qDebug() <<"\n LineDiagram::compare():";
102  // compare own properties
103  qDebug() << (type() == other->type());
104  */
105  return // compare the base class
106  ( static_cast<const LineDiagram*>(this)->compare( other ) );
107 }
108 
114 {
115  if ( d->lotChangedPosition == pos )
116  return;
117 
118  d->lotChangedPosition = pos;
119  update();
120 }
121 
126 {
127  return d->lotChangedPosition;
128 }
129 
135 {
136  if ( d->fluidicsPackChangedPosition == pos )
137  return;
138 
139  d->fluidicsPackChangedPosition = pos;
140  update();
141 }
142 
147 {
148  return d->fluidicsPackChangedPosition;
149 }
150 
156 {
157  if ( d->sensorChangedPosition == pos )
158  return;
159 
160  d->sensorChangedPosition = pos;
161  update();
162 }
163 
168 {
169  return d->sensorChangedPosition;
170 }
171 
176 {
177  if ( d->fluidicsPackChanges == changes )
178  return;
179 
180  d->fluidicsPackChanges = changes;
181  update();
182 }
183 
188 {
189  return d->fluidicsPackChanges;
190 }
191 
196 {
197  if ( d->sensorChanges == changes )
198  return;
199 
200  d->sensorChanges = changes;
201  update();
202 }
203 
208 {
209  if ( d->scanLinePen == pen )
210  return;
211 
212  d->scanLinePen = pen;
213  update();
214 }
215 
220 {
221  return d->scanLinePen;
222 }
223 
228 {
229  return d->icons[ symbol ];
230 }
231 
235 void LeveyJenningsDiagram::setSymbol( Symbol symbol, const QString& filename )
236 {
237  if ( d->icons[ symbol ] == filename )
238  return;
239 
240  delete d->iconRenderer[ symbol ];
241  d->iconRenderer[ symbol ] = 0;
242 
243  d->icons[ symbol ] = filename;
244 
245  update();
246 }
247 
252 {
253  return d->sensorChanges;
254 }
255 
260 {
261  if ( d->expectedMeanValue == meanValue )
262  return;
263 
264  d->expectedMeanValue = meanValue;
265  d->setYAxisRange();
266  update();
267 }
268 
273 {
274  return d->expectedMeanValue;
275 }
276 
281 {
282  if ( d->expectedStandardDeviation == sd )
283  return;
284 
285  d->expectedStandardDeviation = sd;
286  d->setYAxisRange();
287  update();
288 }
289 
294 {
295  return d->expectedStandardDeviation;
296 }
297 
302 {
303  return d->calculatedMeanValue;
304 }
305 
310 {
311  return d->calculatedStandardDeviation;
312 }
313 
314 void LeveyJenningsDiagram::setModel( QAbstractItemModel* model )
315 {
316  if ( this->model() != 0 )
317  {
318  disconnect( this->model(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
319  this, SLOT( calculateMeanAndStandardDeviation() ) );
320  disconnect( this->model(), SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
321  this, SLOT( calculateMeanAndStandardDeviation() ) );
322  disconnect( this->model(), SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
323  this, SLOT( calculateMeanAndStandardDeviation() ) );
324  disconnect( this->model(), SIGNAL( columnsInserted( const QModelIndex&, int, int ) ),
325  this, SLOT( calculateMeanAndStandardDeviation() ) );
326  disconnect( this->model(), SIGNAL( columnsRemoved( const QModelIndex&, int, int ) ),
327  this, SLOT( calculateMeanAndStandardDeviation() ) );
328  disconnect( this->model(), SIGNAL( modelReset() ),
329  this, SLOT( calculateMeanAndStandardDeviation() ) );
330  disconnect( this->model(), SIGNAL( layoutChanged() ),
331  this, SLOT( calculateMeanAndStandardDeviation() ) );
332  }
333  LineDiagram::setModel( model );
334  if ( this->model() != 0 )
335  {
336  connect( this->model(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
337  this, SLOT( calculateMeanAndStandardDeviation() ) );
338  connect( this->model(), SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
339  this, SLOT( calculateMeanAndStandardDeviation() ) );
340  connect( this->model(), SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
341  this, SLOT( calculateMeanAndStandardDeviation() ) );
342  connect( this->model(), SIGNAL( columnsInserted( const QModelIndex&, int, int ) ),
343  this, SLOT( calculateMeanAndStandardDeviation() ) );
344  connect( this->model(), SIGNAL( columnsRemoved( const QModelIndex&, int, int ) ),
345  this, SLOT( calculateMeanAndStandardDeviation() ) );
346  connect( this->model(), SIGNAL( modelReset() ),
347  this, SLOT( calculateMeanAndStandardDeviation() ) );
348  connect( this->model(), SIGNAL( layoutChanged() ),
349  this, SLOT( calculateMeanAndStandardDeviation() ) );
350 
352  }
353 }
354 
355 // TODO: This is the 'easy' solution
356 // evaluate whether this is enough or we need some better one or even boost here
358 {
359  QVector< qreal > values;
360  // first fetch all values
361  const QAbstractItemModel& m = *model();
362  const int rowCount = m.rowCount( rootIndex() );
363 
364  for ( int row = 0; row < rowCount; ++row )
365  {
366  const QVariant var = m.data( m.index( row, 1, rootIndex() ) );
367  if ( !var.isValid() )
368  continue;
369  const qreal value = var.toReal();
370  if ( ISNAN( value ) )
371  continue;
372  values << value;
373  }
374 
375  qreal sum = 0.0;
376  qreal sumSquares = 0.0;
377  KDAB_FOREACH( qreal value, values )
378  {
379  sum += value;
380  sumSquares += value * value;
381  }
382 
383  const int N = values.count();
384 
385  d->calculatedMeanValue = sum / N;
386  d->calculatedStandardDeviation = sqrt( ( static_cast< qreal >( N ) * sumSquares - sum * sum ) / ( N * ( N - 1 ) ) );
387 }
388 
389 // calculates the largest QDate not greater than \a dt.
390 static QDate floorDay( const QDateTime& dt )
391 {
392  return dt.date();
393 }
394 
395 // calculates the smallest QDate not less than \a dt.
396 static QDate ceilDay( const QDateTime& dt )
397 {
398  QDate result = dt.date();
399 
400  if ( QDateTime( result, QTime() ) < dt )
401  result = result.addDays( 1 );
402 
403  return result;
404 }
405 
406 // calculates the largest QDateTime like xx:00 not greater than \a dt.
407 static QDateTime floorHour( const QDateTime& dt )
408 {
409  return QDateTime( dt.date(), QTime( dt.time().hour(), 0 ) );
410 }
411 
412 // calculates the smallest QDateTime like xx:00 not less than \a dt.
413 static QDateTime ceilHour( const QDateTime& dt )
414 {
415  QDateTime result( dt.date(), QTime( dt.time().hour(), 0 ) );
416 
417  if ( result < dt )
418  result = result.addSecs( 3600 );
419 
420  return result;
421 }
422 
425 {
426  const qreal yMin = d->expectedMeanValue - 4 * d->expectedStandardDeviation;
427  const qreal yMax = d->expectedMeanValue + 4 * d->expectedStandardDeviation;
428 
429  d->setYAxisRange();
430 
431  // rounded down/up to the prev/next midnight (at least that's the default)
433  const unsigned int minTime = range.first.toTime_t();
434  const unsigned int maxTime = range.second.toTime_t();
435 
436  const qreal xMin = minTime / static_cast< qreal >( 24 * 60 * 60 );
437  const qreal xMax = maxTime / static_cast< qreal >( 24 * 60 * 60 ) - xMin;
438 
439  const QPointF bottomLeft( QPointF( 0, yMin ) );
440  const QPointF topRight( QPointF( xMax, yMax ) );
441 
442  return QPair< QPointF, QPointF >( bottomLeft, topRight );
443 }
444 
449 {
450  if ( d->timeRange != QPair< QDateTime, QDateTime >() )
451  return d->timeRange;
452 
453  const QAbstractItemModel& m = *model();
454  const int rowCount = m.rowCount( rootIndex() );
455 
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();
458 
459  if ( begin.secsTo( end ) > 86400 )
460  {
461  // if begin to end is more than 24h
462  // round down/up to the prev/next midnight
463  const QDate min = floorDay( begin );
464  const QDate max = ceilDay( end );
465  return QPair< QDateTime, QDateTime >( QDateTime( min ), QDateTime( max ) );
466  }
467  else if ( begin.secsTo( end ) > 3600 )
468  {
469  // more than 1h: rond down up to the prex/next hour
470  // if begin to end is more than 24h
471  const QDateTime min = floorHour( begin );
472  const QDateTime max = ceilHour( end );
473  return QPair< QDateTime, QDateTime >( min, max );
474  }
475  return QPair< QDateTime, QDateTime >( begin, end );
476 }
477 
483 {
484  if ( d->timeRange == timeRange )
485  return;
486 
487  d->timeRange = timeRange;
488  update();
489 }
490 
495 {
496  const unsigned int minTime = timeRange().first.toTime_t();
497 
498  KDAB_FOREACH( const QDateTime& dt, d->fluidicsPackChanges )
499  {
500  const qreal xValue = ( dt.toTime_t() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
501  const QPointF point( xValue, 0.0 );
502  drawFluidicsPackChangedSymbol( ctx, point );
503  }
504 
505  KDAB_FOREACH( const QDateTime& dt, d->sensorChanges )
506  {
507  const qreal xValue = ( dt.toTime_t() - minTime ) / static_cast< qreal >( 24 * 60 * 60 );
508  const QPointF point( xValue, 0.0 );
509  drawSensorChangedSymbol( ctx, point );
510  }
511 }
512 
515 {
516  d->reverseMapper.clear();
517 
518  // note: Not having any data model assigned is no bug
519  // but we can not draw a diagram then either.
520  if ( !checkInvariants( true ) ) return;
521  if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
522 
523  QPainter* const painter = ctx->painter();
524  const PainterSaver p( painter );
525  if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) < 4 )
526  return; // nothing to paint for us
527 
528  AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
529  ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( painter ) );
530 
531  const QAbstractItemModel& m = *model();
532  const int rowCount = m.rowCount( rootIndex() );
533 
534  const unsigned int minTime = timeRange().first.toTime_t();
535 
536  painter->setRenderHint( QPainter::Antialiasing, true );
537 
538  int prevLot = -1;
539  QPointF prevPoint;
540  bool hadMissingValue = false;
541 
542  for ( int row = 0; row < rowCount; ++row )
543  {
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() );
550 
551  painter->setPen( pen( lotIndex ) );
552 
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 );
559 
560  QVariant vExpectedMean = m.data( expectedMeanIndex );
561  const qreal expectedMean = vExpectedMean.toReal();
562  QVariant vExpectedSD = m.data( expectedSDIndex );
563  const qreal expectedSD = vExpectedSD.toReal();
564 
565  QPointF point = ctx->coordinatePlane()->translate( QPointF( xValue, value ) );
566 
567  if ( vValue.isNull() )
568  {
569  hadMissingValue = true;
570  }
571  else
572  {
573  if ( !vExpectedMean.isNull() && !vExpectedSD.isNull() )
574  {
575  // this calculates the 'logical' value relative to the expected mean and SD of this point
576  value -= expectedMean;
577  value /= expectedSD;
578  value *= d->expectedStandardDeviation;
579  value += d->expectedMeanValue;
580  point = ctx->coordinatePlane()->translate( QPointF( xValue, value ) );
581  }
582 
583  if ( prevLot == lot )
584  {
585  const QPen pen = painter->pen();
586  QPen newPen = pen;
587 
588  if ( hadMissingValue )
589  {
590  newPen.setDashPattern( QVector< qreal >() << 4.0 << 4.0 );
591  }
592 
593  painter->setPen( newPen );
594  painter->drawLine( prevPoint, point );
595  painter->setPen( pen );
596  // d->reverseMapper.addLine( valueIndex.row(), valueIndex.column(), prevPoint, point );
597  }
598  else if ( row > 0 )
599  {
600  drawLotChangeSymbol( ctx, QPointF( xValue, value ) );
601  }
602 
603  if ( value <= d->expectedMeanValue + 4 * d->expectedStandardDeviation &&
604  value >= d->expectedMeanValue - 4 * d->expectedStandardDeviation )
605  {
606  const QPointF location( xValue, value );
607  drawDataPointSymbol( ctx, location, ok );
608  d->reverseMapper.addCircle( valueIndex.row(),
609  valueIndex.column(),
610  ctx->coordinatePlane()->translate( location ),
611  iconRect().size() );
612  }
613  prevLot = lot;
614  prevPoint = point;
615  hadMissingValue = false;
616  }
617 
618  const QModelIndex current = selectionModel()->currentIndex();
619  if ( selectionModel()->rowIntersectsSelection( lotIndex.row(), lotIndex.parent() ) || current.sibling( current.row(), 0 ) == lotIndex )
620  {
621  const QPen pen = ctx->painter()->pen();
622  painter->setPen( d->scanLinePen );
623  painter->drawLine( ctx->coordinatePlane()->translate( QPointF( xValue, d->expectedMeanValue - 4 *
624  d->expectedStandardDeviation ) ),
625  ctx->coordinatePlane()->translate( QPointF( xValue, d->expectedMeanValue + 4 *
626  d->expectedStandardDeviation ) ) );
627  painter->setPen( pen );
628  }
629  }
630 
631  drawChanges( ctx );
632 
633  ctx->setCoordinatePlane( plane );
634 }
635 
641 void LeveyJenningsDiagram::drawDataPointSymbol( PaintContext* ctx, const QPointF& pos, bool ok )
642 {
643  const Symbol type = ok ? OkDataPoint : NotOkDataPoint;
644 
645  QPainter* const painter = ctx->painter();
646  const PainterSaver ps( painter );
647  const QPointF transPos = ctx->coordinatePlane()->translate( pos ).toPoint();
648  painter->translate( transPos );
649 
650  painter->setClipping( false );
651  iconRenderer( type )->render( painter, iconRect() );
652 }
653 
660 {
661  const QPointF transPos = ctx->coordinatePlane()->translate(
662  QPointF( pos.x(), d->lotChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
663  4 * d->expectedStandardDeviation
664  : d->expectedMeanValue -
665  4 * d->expectedStandardDeviation ) );
666 
667 
668  QPainter* const painter = ctx->painter();
669  const PainterSaver ps( painter );
670  painter->setClipping( false );
671  painter->translate( transPos );
672  iconRenderer( LotChanged )->render( painter, iconRect() );
673 }
674 
681 {
682  const QPointF transPos = ctx->coordinatePlane()->translate(
683  QPointF( pos.x(), d->sensorChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
684  4 * d->expectedStandardDeviation
685  : d->expectedMeanValue -
686  4 * d->expectedStandardDeviation ) );
687 
688  QPainter* const painter = ctx->painter();
689  const PainterSaver ps( painter );
690  painter->setClipping( false );
691  painter->translate( transPos );
692  iconRenderer( SensorChanged )->render( painter, iconRect() );
693 }
694 
701 {
702  const QPointF transPos = ctx->coordinatePlane()->translate(
703  QPointF( pos.x(), d->fluidicsPackChangedPosition & Qt::AlignTop ? d->expectedMeanValue +
704  4 * d->expectedStandardDeviation
705  : d->expectedMeanValue -
706  4 * d->expectedStandardDeviation ) );
707 
708  QPainter* const painter = ctx->painter();
709  const PainterSaver ps( painter );
710  painter->setClipping( false );
711  painter->translate( transPos );
712  iconRenderer( FluidicsPackChanged )->render( painter, iconRect() );
713 }
714 
719 {
721  TextAttributes test;
722  test.setFontSize( m );
723  const QFontMetrics fm( test.calculatedFont( coordinatePlane()->parent(), KDChartEnums::MeasureOrientationAuto ) );
724  const qreal height = fm.height() / 1.2;
725  return QRectF( -height / 2.0, -height / 2.0, height, height );
726 }
727 
732 {
733  if ( d->iconRenderer[ symbol ] == 0 )
734  d->iconRenderer[ symbol ] = new QSvgRenderer( d->icons[ symbol ], this );
735 
736  return d->iconRenderer[ symbol ];
737 }
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&#39;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
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)
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.
Class only listed here to document inheritance of some KDChart classes.
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)

Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/

https://www.kdab.com/development-resources/qt-tools/kd-chart/