KChart

KChartLeveyJenningsAxis.cpp
1/*
2 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3 *
4 * This file is part of the KD Chart library.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "KChartLeveyJenningsAxis.h"
10#include "KChartLeveyJenningsAxis_p.h"
11
12#include <QDateTime>
13#include <QPainter>
14
15#include "KChartPaintContext.h"
16#include "KChartChart.h"
17#include "KChartAbstractCartesianDiagram.h"
18#include "KChartAbstractGrid.h"
19#include "KChartPainterSaver_p.h"
20#include "KChartLayoutItems.h"
21#include "KChartPrintingParameters.h"
22#include "KChartMath_p.h"
23
24using namespace KChart;
25
26#define d (d_func())
27
29 : CartesianAxis ( new Private( diagram, this ), diagram )
30{
31 init();
32}
33
34LeveyJenningsAxis::~LeveyJenningsAxis ()
35{
36 // when we remove the first axis it will unregister itself and
37 // propagate the next one to the primary, thus the while loop
38 while ( d->mDiagram ) {
40 cd->takeAxis( this );
41 }
42 for ( AbstractDiagram *diagram : std::as_const(d->secondaryDiagrams) ) {
44 cd->takeAxis( this );
45 }
46}
47
48void LeveyJenningsAxis::init ()
49{
50 setType( LeveyJenningsGridAttributes::Expected );
51 setDateFormat( Qt::TextDate );
52 const QStringList labels = QStringList() << tr( "-3sd" ) << tr( "-2sd" ) << tr( "mean" )
53 << tr( "+2sd" ) << tr( "+3sd" );
54
56}
57
58LeveyJenningsGridAttributes::GridType LeveyJenningsAxis::type() const
59{
60 return d->type;
61}
62
63void LeveyJenningsAxis::setType( LeveyJenningsGridAttributes::GridType type )
64{
65 if ( type != d->type )
66 {
68 QPen pen = ta.pen();
69 QColor color = type == LeveyJenningsGridAttributes::Expected ? Qt::black : Qt::blue;
70 if ( qobject_cast< const LeveyJenningsDiagram* >( d->diagram() ) &&
71 qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() ) )
72 {
73 color = qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() )->gridAttributes().gridPen( type ).color();
74 }
75 pen.setColor( color );
76 ta.setPen( pen );
78 }
79 d->type = type;
80}
81
82Qt::DateFormat LeveyJenningsAxis::dateFormat() const
83{
84 return d->format;
85}
86
87void LeveyJenningsAxis::setDateFormat(Qt::DateFormat format)
88{
89 d->format = format;
90}
91
93{
94 if ( other == this ) return true;
95 if ( ! other ) {
96 //qDebug() << "CartesianAxis::compare() cannot compare to Null pointer";
97 return false;
98 }
99 return ( static_cast<const CartesianAxis*>(this)->compare( other ) ) &&
100 ( type() == other->type() );
101}
102
104{
105
106 Q_ASSERT_X ( d->diagram(), "LeveyJenningsAxis::paint",
107 "Function call not allowed: The axis is not assigned to any diagram." );
108
109 LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
110 Q_ASSERT_X ( plane, "LeveyJenningsAxis::paint",
111 "Bad function call: PaintContext::coodinatePlane() NOT a levey jennings plane." );
112 Q_UNUSED(plane);
113 // note: Not having any data model assigned is no bug
114 // but we can not draw an axis then either.
115 if ( ! d->diagram()->model() )
116 return;
117
118 if ( isOrdinate() )
119 paintAsOrdinate( context );
120 else
121 paintAsAbscissa( context );
122}
123
124void LeveyJenningsAxis::paintAsOrdinate( PaintContext* context )
125{
126 const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
127
128 Q_ASSERT( isOrdinate() );
129 LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
130
131 const qreal meanValue = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedMeanValue()
132 : diag->calculatedMeanValue();
133 const qreal standardDeviation = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedStandardDeviation()
135 const TextAttributes labelTA = textAttributes();
136 const bool drawLabels = labelTA.isVisible();
137
138 // nothing to draw, since we've no ticks
139 if ( !drawLabels )
140 return;
141
142 const QObject* referenceArea = plane->parent();
143
144 const QVector< qreal > values = QVector< qreal >() << ( meanValue - 3 * standardDeviation )
145 << ( meanValue - 2 * standardDeviation )
146 << ( meanValue )
147 << ( meanValue + 2 * standardDeviation )
148 << ( meanValue + 3 * standardDeviation );
149
150 Q_ASSERT_X( values.count() <= labels().count(), "LeveyJenningsAxis::paintAsOrdinate", "Need to have at least 5 labels" );
151
152 TextLayoutItem labelItem( tr( "mean" ),
153 labelTA,
154 referenceArea,
155 KChartEnums::MeasureOrientationMinimum,
157
158 QPainter* const painter = context->painter();
159 const PainterSaver ps( painter );
160 painter->setRenderHint( QPainter::Antialiasing, true );
161 painter->setClipping( false );
162
163 painter->setPen ( PrintingParameters::scalePen( labelTA.pen() ) ); // perhaps we want to add a setter method later?
164
165 for ( int i = 0; i < values.count(); ++i )
166 {
167 const QPointF labelPos = plane->translate( QPointF( 0.0, values.at( i ) ) );
168 const QString label = customizedLabel( labels().at( i ) );
169 labelItem.setText( label );
170 const QSize size = labelItem.sizeHint();
171 const float xPos = position() == Left ? geometry().right() - size.width() : geometry().left();
172 labelItem.setGeometry( QRectF( QPointF( xPos, labelPos.y() - size.height() / 2.0 ), size ).toRect() );
173
174 // don't draw labels which aren't in the valid range (might happen for calculated SDs)
175 if ( values.at( i ) > diag->expectedMeanValue() + 4 * diag->expectedStandardDeviation() )
176 continue;
177
178 if ( values.at( i ) < diag->expectedMeanValue() - 4 * diag->expectedStandardDeviation() )
179 continue;
180
181 labelItem.paint( painter );
182 }
183}
184
185void LeveyJenningsAxis::paintAsAbscissa( PaintContext* context )
186{
187 Q_ASSERT( isAbscissa() );
188
189 // this triggers drawing of the ticks
191 CartesianAxis::paintCtx( context );
192
193 const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
194 LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
195
196 const QObject* referenceArea = plane->parent();
197 const TextAttributes labelTA = textAttributes();
198
199 const bool drawLabels = labelTA.isVisible();
200
201 if ( !drawLabels )
202 return;
203
204
205 const QPair< QDateTime, QDateTime > range = diag->timeRange();
206
207 QPainter* const painter = context->painter();
208 const PainterSaver ps( painter );
209 painter->setRenderHint( QPainter::Antialiasing, true );
210 painter->setClipping( false );
211
212
213 TextLayoutItem labelItem( range.first.date().toString( dateFormat() ),
214 labelTA,
215 referenceArea,
216 KChartEnums::MeasureOrientationMinimum,
218 QSize origSize = labelItem.sizeHint();
219 if ( range.first.secsTo( range.second ) < 86400 )
220 labelItem = TextLayoutItem( range.first.toString( dateFormat() ),
221 labelTA,
222 referenceArea,
223 KChartEnums::MeasureOrientationMinimum,
225 QSize size = labelItem.sizeHint();
226
227 float yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
228 labelItem.setGeometry( QRectF( QPointF( geometry().left() - origSize.width() / 2.0, yPos ), size ).toRect() );
229 labelItem.paint( painter );
230
231
232 TextLayoutItem labelItem2( range.second.date().toString( dateFormat() ),
233 labelTA,
234 referenceArea,
235 KChartEnums::MeasureOrientationMinimum,
237 origSize = labelItem2.sizeHint();
238 if ( range.first.secsTo( range.second ) < 86400 )
239 labelItem2 = TextLayoutItem( range.second.toString( dateFormat() ),
240 labelTA,
241 referenceArea,
242 KChartEnums::MeasureOrientationMinimum,
244 size = labelItem2.sizeHint();
245 yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
246 labelItem2.setGeometry( QRectF( QPointF( geometry().right() - size.width() + origSize.width() / 2.0, yPos ), size ).toRect() );
247 labelItem2.paint( painter );
248}
virtual const QString customizedLabel(const QString &label) const
Reimplement this method if you want to adjust axis labels before they are printed.
void setLabels(const QStringList &list)
Use this to specify your own set of strings, to be used as axis labels.
QStringList labels() const
Returns a list of strings, that are used as axis labels, as set via setLabels.
void setTextAttributes(const TextAttributes &a)
Use this to specify the text attributes to be used for axis labels.
TextAttributes textAttributes() const
Returns the text attributes to be used for axis labels.
virtual void takeAxis(CartesianAxis *axis)
Removes the axis from the diagram, without deleting it.
AbstractDiagram defines the interface for diagram classes.
The class for cartesian axes.
void paintCtx(PaintContext *) override
reimpl
QRect geometry() const override
pure virtual in QLayoutItem
const QPointF translate(const QPointF &diagramPoint) const override
Translate the given point in value space coordinates to a position in pixel space.
The class for levey jennings axes.
void paintCtx(PaintContext *) override
reimpl
LeveyJenningsGridAttributes::GridType type() const
void setType(LeveyJenningsGridAttributes::GridType type)
Sets the type of the axis to type.
bool compare(const LeveyJenningsAxis *other) const
Returns true if both axes have the same settings.
LeveyJenningsAxis(LeveyJenningsDiagram *diagram=nullptr)
C'tor of the class for levey jennings axes.
Levey Jennings coordinate plane This is actually nothing real more than a plain cartesian coordinate ...
LeveyDiagram defines a Levey Jennings chart.
float expectedStandardDeviation() const
Returns the expected standard deviation over all QC values.
float calculatedStandardDeviation() const
Returns the calculated standard deviation over all QC values.
float expectedMeanValue() const
Returns the expected mean values over all QC values.
float calculatedMeanValue() const
Returns the calculated mean values over all QC values.
QPair< QDateTime, QDateTime > timeRange() const
Returns the timerange of the diagram's data.
Stores information about painting diagrams.
A set of text attributes.
void setPen(const QPen &pen)
Set the pen to use for rendering the text.
Layout item showing a text.
const_reference at(qsizetype i) const const
qsizetype count() const const
T qobject_cast(QObject *object)
QString tr(const char *sourceText, const char *disambiguation, int n)
void setClipping(bool enable)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
void setColor(const QColor &color)
qreal y() const const
int bottom() const const
int left() const const
int right() const const
int top() const const
QRect toRect() const const
int height() const const
int width() const const
QString fromLatin1(QByteArrayView str)
AlignLeft
TextDate
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:09:30 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.