Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KDChartLeveyJenningsAxis.h"
00024 #include "KDChartLeveyJenningsAxis_p.h"
00025
00026 #include <QDateTime>
00027 #include <QPainter>
00028
00029 #include "KDChartPaintContext.h"
00030 #include "KDChartChart.h"
00031 #include "KDChartAbstractCartesianDiagram.h"
00032 #include "KDChartAbstractGrid.h"
00033 #include "KDChartPainterSaver_p.h"
00034 #include "KDChartLayoutItems.h"
00035 #include "KDChartPrintingParameters.h"
00036
00037 #include <KDABLibFakes>
00038
00039 #include <limits>
00040
00041 using namespace KDChart;
00042
00043 #define d (d_func())
00044
00045 LeveyJenningsAxis::LeveyJenningsAxis ( LeveyJenningsDiagram* diagram )
00046 : CartesianAxis ( new Private( diagram, this ), diagram )
00047 {
00048 init();
00049 }
00050
00051 LeveyJenningsAxis::~LeveyJenningsAxis ()
00052 {
00053
00054
00055 while ( d->mDiagram ) {
00056 LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( d->mDiagram );
00057 cd->takeAxis( this );
00058 }
00059 Q_FOREACH( AbstractDiagram *diagram, d->secondaryDiagrams ) {
00060 LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( diagram );
00061 cd->takeAxis( this );
00062 }
00063 }
00064
00065 void LeveyJenningsAxis::init ()
00066 {
00067 setType( LeveyJenningsGridAttributes::Expected );
00068 setDateFormat( Qt::TextDate );
00069 const QStringList labels = QStringList() << tr( "-3sd" ) << tr( "-2sd" ) << tr( "mean" )
00070 << tr( "+2sd" ) << tr( "+3sd" );
00071
00072 setLabels( labels );
00073 }
00074
00078 LeveyJenningsGridAttributes::GridType LeveyJenningsAxis::type() const
00079 {
00080 return d->type;
00081 }
00082
00092 void LeveyJenningsAxis::setType( LeveyJenningsGridAttributes::GridType type )
00093 {
00094 if( type != d->type )
00095 {
00096 TextAttributes ta = textAttributes();
00097 QPen pen = ta.pen();
00098 QColor color = type == LeveyJenningsGridAttributes::Expected ? Qt::black : Qt::blue;
00099 if( qobject_cast< const LeveyJenningsDiagram* >( d->diagram() ) &&
00100 qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() ) )
00101 {
00102 color = qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() )->gridAttributes().gridPen( type ).color();
00103 }
00104 pen.setColor( color );
00105 ta.setPen( pen );
00106 setTextAttributes( ta );
00107 }
00108 d->type = type;
00109 }
00110
00111 Qt::DateFormat LeveyJenningsAxis::dateFormat() const
00112 {
00113 return d->format;
00114 }
00115
00116 void LeveyJenningsAxis::setDateFormat(Qt::DateFormat format)
00117 {
00118 d->format = format;
00119 }
00120
00121 bool LeveyJenningsAxis::compare( const LeveyJenningsAxis* other )const
00122 {
00123 if( other == this ) return true;
00124 if( ! other ){
00125
00126 return false;
00127 }
00128 return ( static_cast<const CartesianAxis*>(this)->compare( other ) ) &&
00129 ( type() == other->type() );
00130 }
00131
00132 void LeveyJenningsAxis::paintCtx( PaintContext* context )
00133 {
00134
00135 Q_ASSERT_X ( d->diagram(), "LeveyJenningsAxis::paint",
00136 "Function call not allowed: The axis is not assigned to any diagram." );
00137
00138 LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
00139 Q_ASSERT_X ( plane, "LeveyJenningsAxis::paint",
00140 "Bad function call: PaintContext::coodinatePlane() NOT a levey jennings plane." );
00141 Q_UNUSED(plane);
00142
00143
00144 if( ! d->diagram()->model() )
00145 return;
00146
00147 if( isOrdinate() )
00148 paintAsOrdinate( context );
00149 else
00150 paintAsAbscissa( context );
00151 }
00152
00153 void LeveyJenningsAxis::paintAsOrdinate( PaintContext* context )
00154 {
00155 const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
00156
00157 Q_ASSERT( isOrdinate() );
00158 LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
00159
00160 const qreal meanValue = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedMeanValue()
00161 : diag->calculatedMeanValue();
00162 const qreal standardDeviation = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedStandardDeviation()
00163 : diag->calculatedStandardDeviation();
00164 const TextAttributes labelTA = textAttributes();
00165 const bool drawLabels = labelTA.isVisible();
00166
00167
00168 if( !drawLabels )
00169 return;
00170
00171 const QObject* referenceArea = plane->parent();
00172
00173 const QVector< qreal > values = QVector< qreal >() << ( meanValue - 3 * standardDeviation )
00174 << ( meanValue - 2 * standardDeviation )
00175 << ( meanValue )
00176 << ( meanValue + 2 * standardDeviation )
00177 << ( meanValue + 3 * standardDeviation );
00178
00179 Q_ASSERT_X( values.count() <= labels().count(), "LeveyJenningsAxis::paintAsOrdinate", "Need to have at least 5 labels" );
00180
00181 TextLayoutItem labelItem( tr( "mean" ),
00182 labelTA,
00183 referenceArea,
00184 KDChartEnums::MeasureOrientationMinimum,
00185 Qt::AlignLeft );
00186
00187 QPainter* const painter = context->painter();
00188 const PainterSaver ps( painter );
00189 painter->setRenderHint( QPainter::Antialiasing, true );
00190 painter->setClipping( false );
00191
00192 painter->setPen ( PrintingParameters::scalePen( labelTA.pen() ) );
00193
00194 for( int i = 0; i < values.count(); ++i )
00195 {
00196 const QPointF labelPos = plane->translate( QPointF( 0.0, values.at( i ) ) );
00197 const QString label = customizedLabel( labels().at( i ) );
00198 labelItem.setText( label );
00199 const QSize size = labelItem.sizeHint();
00200 const float xPos = position() == Left ? geometry().right() - size.width() : geometry().left();
00201 labelItem.setGeometry( QRectF( QPointF( xPos, labelPos.y() - size.height() / 2.0 ), size ).toRect() );
00202
00203
00204 if( values.at( i ) > diag->expectedMeanValue() + 4 * diag->expectedStandardDeviation() )
00205 continue;
00206
00207 if( values.at( i ) < diag->expectedMeanValue() - 4 * diag->expectedStandardDeviation() )
00208 continue;
00209
00210 labelItem.paint( painter );
00211 }
00212 }
00213
00214 void LeveyJenningsAxis::paintAsAbscissa( PaintContext* context )
00215 {
00216 Q_ASSERT( isAbscissa() );
00217
00218
00219 setLabels( QStringList() << QString::fromLatin1( " " ) );
00220 CartesianAxis::paintCtx( context );
00221
00222 const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
00223 LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
00224
00225 const QObject* referenceArea = plane->parent();
00226 const TextAttributes labelTA = textAttributes();
00227
00228 const bool drawLabels = labelTA.isVisible();
00229
00230 if( !drawLabels )
00231 return;
00232
00233
00234 const QPair< QDateTime, QDateTime > range = diag->timeRange();
00235
00236 QPainter* const painter = context->painter();
00237 const PainterSaver ps( painter );
00238 painter->setRenderHint( QPainter::Antialiasing, true );
00239 painter->setClipping( false );
00240
00241
00242 TextLayoutItem labelItem( range.first.date().toString( dateFormat() ),
00243 labelTA,
00244 referenceArea,
00245 KDChartEnums::MeasureOrientationMinimum,
00246 Qt::AlignLeft );
00247 QSize origSize = labelItem.sizeHint();
00248 if( range.first.secsTo( range.second ) < 86400 )
00249 labelItem = TextLayoutItem( range.first.toString( dateFormat() ),
00250 labelTA,
00251 referenceArea,
00252 KDChartEnums::MeasureOrientationMinimum,
00253 Qt::AlignLeft );
00254 QSize size = labelItem.sizeHint();
00255
00256 float yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
00257 labelItem.setGeometry( QRectF( QPointF( geometry().left() - origSize.width() / 2.0, yPos ), size ).toRect() );
00258 labelItem.paint( painter );
00259
00260
00261 TextLayoutItem labelItem2( range.second.date().toString( dateFormat() ),
00262 labelTA,
00263 referenceArea,
00264 KDChartEnums::MeasureOrientationMinimum,
00265 Qt::AlignLeft );
00266 origSize = labelItem2.sizeHint();
00267 if( range.first.secsTo( range.second ) < 86400 )
00268 labelItem2 = TextLayoutItem( range.second.toString( dateFormat() ),
00269 labelTA,
00270 referenceArea,
00271 KDChartEnums::MeasureOrientationMinimum,
00272 Qt::AlignLeft );
00273 size = labelItem2.sizeHint();
00274 yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
00275 labelItem2.setGeometry( QRectF( QPointF( geometry().right() - size.width() + origSize.width() / 2.0, yPos ), size ).toRect() );
00276 labelItem2.paint( painter );
00277 }