KD Chart 2  [rev.2.5.1]
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
KDChartLeveyJenningsAxis.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2013 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 "KDChartLeveyJenningsAxis_p.h"
25 
26 #include <QDateTime>
27 #include <QPainter>
28 
29 #include "KDChartPaintContext.h"
30 #include "KDChartChart.h"
32 #include "KDChartAbstractGrid.h"
33 #include "KDChartPainterSaver_p.h"
34 #include "KDChartLayoutItems.h"
36 
37 #include <KDABLibFakes>
38 
39 #include <limits>
40 
41 using namespace KDChart;
42 
43 #define d (d_func())
44 
46  : CartesianAxis ( new Private( diagram, this ), diagram )
47 {
48  init();
49 }
50 
52 {
53  // when we remove the first axis it will unregister itself and
54  // propagate the next one to the primary, thus the while loop
55  while ( d->mDiagram ) {
56  LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( d->mDiagram );
57  cd->takeAxis( this );
58  }
59  Q_FOREACH( AbstractDiagram *diagram, d->secondaryDiagrams ) {
60  LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( diagram );
61  cd->takeAxis( this );
62  }
63 }
64 
65 void LeveyJenningsAxis::init ()
66 {
68  setDateFormat( Qt::TextDate );
69  const QStringList labels = QStringList() << tr( "-3sd" ) << tr( "-2sd" ) << tr( "mean" )
70  << tr( "+2sd" ) << tr( "+3sd" );
71 
72  setLabels( labels );
73 }
74 
79 {
80  return d->type;
81 }
82 
93 {
94  if ( type != d->type )
95  {
97  QPen pen = ta.pen();
98  QColor color = type == LeveyJenningsGridAttributes::Expected ? Qt::black : Qt::blue;
99  if ( qobject_cast< const LeveyJenningsDiagram* >( d->diagram() ) &&
100  qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() ) )
101  {
102  color = qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() )->gridAttributes().gridPen( type ).color();
103  }
104  pen.setColor( color );
105  ta.setPen( pen );
106  setTextAttributes( ta );
107  }
108  d->type = type;
109 }
110 
111 Qt::DateFormat LeveyJenningsAxis::dateFormat() const
112 {
113  return d->format;
114 }
115 
116 void LeveyJenningsAxis::setDateFormat(Qt::DateFormat format)
117 {
118  d->format = format;
119 }
120 
122 {
123  if ( other == this ) return true;
124  if ( ! other ) {
125  //qDebug() << "CartesianAxis::compare() cannot compare to Null pointer";
126  return false;
127  }
128  return ( static_cast<const CartesianAxis*>(this)->compare( other ) ) &&
129  ( type() == other->type() );
130 }
131 
133 {
134 
135  Q_ASSERT_X ( d->diagram(), "LeveyJenningsAxis::paint",
136  "Function call not allowed: The axis is not assigned to any diagram." );
137 
139  Q_ASSERT_X ( plane, "LeveyJenningsAxis::paint",
140  "Bad function call: PaintContext::coodinatePlane() NOT a levey jennings plane." );
141  Q_UNUSED(plane);
142  // note: Not having any data model assigned is no bug
143  // but we can not draw an axis then either.
144  if ( ! d->diagram()->model() )
145  return;
146 
147  if ( isOrdinate() )
148  paintAsOrdinate( context );
149  else
150  paintAsAbscissa( context );
151 }
152 
154 {
155  const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
156 
157  Q_ASSERT( isOrdinate() );
159 
160  const qreal meanValue = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedMeanValue()
161  : diag->calculatedMeanValue();
162  const qreal standardDeviation = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedStandardDeviation()
163  : diag->calculatedStandardDeviation();
164  const TextAttributes labelTA = textAttributes();
165  const bool drawLabels = labelTA.isVisible();
166 
167  // nothing to draw, since we've no ticks
168  if ( !drawLabels )
169  return;
170 
171  const QObject* referenceArea = plane->parent();
172 
173  const QVector< qreal > values = QVector< qreal >() << ( meanValue - 3 * standardDeviation )
174  << ( meanValue - 2 * standardDeviation )
175  << ( meanValue )
176  << ( meanValue + 2 * standardDeviation )
177  << ( meanValue + 3 * standardDeviation );
178 
179  Q_ASSERT_X( values.count() <= labels().count(), "LeveyJenningsAxis::paintAsOrdinate", "Need to have at least 5 labels" );
180 
181  TextLayoutItem labelItem( tr( "mean" ),
182  labelTA,
183  referenceArea,
185  Qt::AlignLeft );
186 
187  QPainter* const painter = context->painter();
188  const PainterSaver ps( painter );
189  painter->setRenderHint( QPainter::Antialiasing, true );
190  painter->setClipping( false );
191 
192  painter->setPen ( PrintingParameters::scalePen( labelTA.pen() ) ); // perhaps we want to add a setter method later?
193 
194  for ( int i = 0; i < values.count(); ++i )
195  {
196  const QPointF labelPos = plane->translate( QPointF( 0.0, values.at( i ) ) );
197  const QString label = customizedLabel( labels().at( i ) );
198  labelItem.setText( label );
199  const QSize size = labelItem.sizeHint();
200  const float xPos = position() == Left ? geometry().right() - size.width() : geometry().left();
201  labelItem.setGeometry( QRectF( QPointF( xPos, labelPos.y() - size.height() / 2.0 ), size ).toRect() );
202 
203  // don't draw labels which aren't in the valid range (might happen for calculated SDs)
204  if ( values.at( i ) > diag->expectedMeanValue() + 4 * diag->expectedStandardDeviation() )
205  continue;
206 
207  if ( values.at( i ) < diag->expectedMeanValue() - 4 * diag->expectedStandardDeviation() )
208  continue;
209 
210  labelItem.paint( painter );
211  }
212 }
213 
215 {
216  Q_ASSERT( isAbscissa() );
217 
218  // this triggers drawing of the ticks
219  setLabels( QStringList() << QString::fromLatin1( " " ) );
220  CartesianAxis::paintCtx( context );
221 
222  const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
224 
225  const QObject* referenceArea = plane->parent();
226  const TextAttributes labelTA = textAttributes();
227 
228  const bool drawLabels = labelTA.isVisible();
229 
230  if ( !drawLabels )
231  return;
232 
233 
234  const QPair< QDateTime, QDateTime > range = diag->timeRange();
235 
236  QPainter* const painter = context->painter();
237  const PainterSaver ps( painter );
238  painter->setRenderHint( QPainter::Antialiasing, true );
239  painter->setClipping( false );
240 
241 
242  TextLayoutItem labelItem( range.first.date().toString( dateFormat() ),
243  labelTA,
244  referenceArea,
246  Qt::AlignLeft );
247  QSize origSize = labelItem.sizeHint();
248  if ( range.first.secsTo( range.second ) < 86400 )
249  labelItem = TextLayoutItem( range.first.toString( dateFormat() ),
250  labelTA,
251  referenceArea,
253  Qt::AlignLeft );
254  QSize size = labelItem.sizeHint();
255 
256  float yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
257  labelItem.setGeometry( QRectF( QPointF( geometry().left() - origSize.width() / 2.0, yPos ), size ).toRect() );
258  labelItem.paint( painter );
259 
260 
261  TextLayoutItem labelItem2( range.second.date().toString( dateFormat() ),
262  labelTA,
263  referenceArea,
265  Qt::AlignLeft );
266  origSize = labelItem2.sizeHint();
267  if ( range.first.secsTo( range.second ) < 86400 )
268  labelItem2 = TextLayoutItem( range.second.toString( dateFormat() ),
269  labelTA,
270  referenceArea,
272  Qt::AlignLeft );
273  size = labelItem2.sizeHint();
274  yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
275  labelItem2.setGeometry( QRectF( QPointF( geometry().right() - size.width() + origSize.width() / 2.0, yPos ), size ).toRect() );
276  labelItem2.paint( painter );
277 }

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/