KD Chart 2  [rev.2.5]
KDChartLeveyJenningsAxis.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2012 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
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     // when we remove the first axis it will unregister itself and
00054     // propagate the next one to the primary, thus the while loop
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         //qDebug() << "CartesianAxis::compare() cannot compare to Null pointer";
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     // note: Not having any data model assigned is no bug
00143     //       but we can not draw an axis then either.
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     // nothing to draw, since we've no ticks
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() ) ); // perhaps we want to add a setter method later?
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         // don't draw labels which aren't in the valid range (might happen for calculated SDs)
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     // this triggers drawing of the ticks
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines

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