1
/****************************************************************************
2
** Copyright (C) 2007 Klarävdalens Datakonsult AB. All rights reserved.
4
** This file is part of the KD Chart library.
6
** This file may be used under the terms of the GNU General Public
7
** License versions 2.0 or 3.0 as published by the Free Software
8
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
9
** included in the packaging of this file. Alternatively you may (at
10
** your option) use any later version of the GNU General Public
11
** License if such license has been publicly approved by
12
** Klarälvdalens Datakonsult AB (or its successors, if any).
14
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
15
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
16
** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
17
** not expressly granted herein.
19
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
**********************************************************************/
24
#include "KDChartLeveyJenningsAxis.h"
25
#include "KDChartLeveyJenningsAxis_p.h"
30
#include "KDChartPaintContext.h"
31
#include "KDChartChart.h"
32
#include "KDChartAbstractCartesianDiagram.h"
33
#include "KDChartAbstractGrid.h"
34
#include "KDChartPainterSaver_p.h"
35
#include "KDChartLayoutItems.h"
36
#include "KDChartPrintingParameters.h"
38
#include <KDABLibFakes>
42
using namespace KDChart;
46
LeveyJenningsAxis::LeveyJenningsAxis ( LeveyJenningsDiagram* diagram )
47
: CartesianAxis ( new Private( diagram, this ), diagram )
52
LeveyJenningsAxis::~LeveyJenningsAxis ()
54
// when we remove the first axis it will unregister itself and
55
// propagate the next one to the primary, thus the while loop
56
while ( d->mDiagram ) {
57
LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( d->mDiagram );
60
Q_FOREACH( AbstractDiagram *diagram, d->secondaryDiagrams ) {
61
LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( diagram );
66
void LeveyJenningsAxis::init ()
68
setType( LeveyJenningsGridAttributes::Expected );
69
setDateFormat( Qt::TextDate );
70
const QStringList labels = QStringList() << tr( "-3sd" ) << tr( "-2sd" ) << tr( "mean" )
71
<< tr( "+2sd" ) << tr( "+3sd" );
77
* @return The axis' type.
79
LeveyJenningsGridAttributes::GridType LeveyJenningsAxis::type() const
85
* Sets the type of the axis to \a type.
86
* This method colors the label to the default color of the
88
* Please make sure to re-set the colors after calling this,
89
* if you want them different.
90
* Setting the type is only valid for axes located right or left
91
* from the diagram. An axis on the bottom always shows the timeline.
93
void LeveyJenningsAxis::setType( LeveyJenningsGridAttributes::GridType type )
97
TextAttributes ta = textAttributes();
99
QColor color = type == LeveyJenningsGridAttributes::Expected ? Qt::black : Qt::blue;
100
if( qobject_cast< const LeveyJenningsDiagram* >( d->diagram() ) &&
101
qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() ) )
103
color = qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() )->gridAttributes().gridPen( type ).color();
105
pen.setColor( color );
107
setTextAttributes( ta );
112
Qt::DateFormat LeveyJenningsAxis::dateFormat() const
117
void LeveyJenningsAxis::setDateFormat(Qt::DateFormat format)
122
bool LeveyJenningsAxis::compare( const LeveyJenningsAxis* other )const
124
if( other == this ) return true;
126
//qDebug() << "CartesianAxis::compare() cannot compare to Null pointer";
129
return ( static_cast<const CartesianAxis*>(this)->compare( other ) ) &&
130
( type() == other->type() );
133
void LeveyJenningsAxis::paintCtx( PaintContext* context )
136
Q_ASSERT_X ( d->diagram(), "LeveyJenningsAxis::paint",
137
"Function call not allowed: The axis is not assigned to any diagram." );
139
LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
140
Q_ASSERT_X ( plane, "LeveyJenningsAxis::paint",
141
"Bad function call: PaintContext::coodinatePlane() NOT a levey jennings plane." );
143
// note: Not having any data model assigned is no bug
144
// but we can not draw an axis then either.
145
if( ! d->diagram()->model() )
149
paintAsOrdinate( context );
151
paintAsAbscissa( context );
154
void LeveyJenningsAxis::paintAsOrdinate( PaintContext* context )
156
const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
158
Q_ASSERT( isOrdinate() );
159
LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
161
const qreal meanValue = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedMeanValue()
162
: diag->calculatedMeanValue();
163
const qreal standardDeviation = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedStandardDeviation()
164
: diag->calculatedStandardDeviation();
165
const TextAttributes labelTA = textAttributes();
166
const bool drawLabels = labelTA.isVisible();
168
// nothing to draw, since we've no ticks
172
const QObject* referenceArea = plane->parent();
174
const QVector< qreal > values = QVector< qreal >() << ( meanValue - 3 * standardDeviation )
175
<< ( meanValue - 2 * standardDeviation )
177
<< ( meanValue + 2 * standardDeviation )
178
<< ( meanValue + 3 * standardDeviation );
180
Q_ASSERT_X( values.count() <= labels().count(), "LeveyJenningsAxis::paintAsOrdinate", "Need to have at least 5 labels" );
182
TextLayoutItem labelItem( tr( "mean" ),
185
KDChartEnums::MeasureOrientationMinimum,
188
QPainter* const painter = context->painter();
189
const PainterSaver ps( painter );
190
painter->setRenderHint( QPainter::Antialiasing, true );
191
painter->setClipping( false );
193
painter->setPen ( PrintingParameters::scalePen( labelTA.pen() ) ); // perhaps we want to add a setter method later?
195
for( int i = 0; i < values.count(); ++i )
197
const QPointF labelPos = plane->translate( QPointF( 0.0, values.at( i ) ) );
198
const QString label = customizedLabel( labels().at( i ) );
199
labelItem.setText( label );
200
const QSize size = labelItem.sizeHint();
201
const float xPos = position() == Left ? geometry().right() - size.width() : geometry().left();
202
labelItem.setGeometry( QRectF( QPointF( xPos, labelPos.y() - size.height() / 2.0 ), size ).toRect() );
204
// don't draw labels which aren't in the valid range (might happen for calculated SDs)
205
if( values.at( i ) > diag->expectedMeanValue() + 4 * diag->expectedStandardDeviation() )
208
if( values.at( i ) < diag->expectedMeanValue() - 4 * diag->expectedStandardDeviation() )
211
labelItem.paint( painter );
215
void LeveyJenningsAxis::paintAsAbscissa( PaintContext* context )
217
Q_ASSERT( isAbscissa() );
219
// this triggers drawing of the ticks
220
setLabels( QStringList() << QString::fromLatin1( " " ) );
221
CartesianAxis::paintCtx( context );
223
const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
224
LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
226
const QObject* referenceArea = plane->parent();
227
const TextAttributes labelTA = textAttributes();
229
const bool drawLabels = labelTA.isVisible();
235
const QPair< QDateTime, QDateTime > range = diag->timeRange();
237
QPainter* const painter = context->painter();
238
const PainterSaver ps( painter );
239
painter->setRenderHint( QPainter::Antialiasing, true );
240
painter->setClipping( false );
243
TextLayoutItem labelItem( range.first.date().toString( dateFormat() ),
246
KDChartEnums::MeasureOrientationMinimum,
248
QSize origSize = labelItem.sizeHint();
249
if( range.first.secsTo( range.second ) < 86400 )
250
labelItem = TextLayoutItem( range.first.toString( dateFormat() ),
253
KDChartEnums::MeasureOrientationMinimum,
255
QSize size = labelItem.sizeHint();
257
float yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
258
labelItem.setGeometry( QRectF( QPointF( geometry().left() - origSize.width() / 2.0, yPos ), size ).toRect() );
259
labelItem.paint( painter );
262
TextLayoutItem labelItem2( range.second.date().toString( dateFormat() ),
265
KDChartEnums::MeasureOrientationMinimum,
267
origSize = labelItem2.sizeHint();
268
if( range.first.secsTo( range.second ) < 86400 )
269
labelItem2 = TextLayoutItem( range.second.toString( dateFormat() ),
272
KDChartEnums::MeasureOrientationMinimum,
274
size = labelItem2.sizeHint();
275
yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
276
labelItem2.setGeometry( QRectF( QPointF( geometry().right() - size.width() + origSize.width() / 2.0, yPos ), size ).toRect() );
277
labelItem2.paint( painter );