KDChartLeveyJenningsAxis.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2007 Klarävdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Chart library.
00005  **
00006  ** This file may be distributed and/or modified under the terms of the
00007  ** GNU General Public License version 2 as published by the Free Software
00008  ** Foundation and appearing in the file LICENSE.GPL included in the
00009  ** packaging of this file.
00010  **
00011  ** Licensees holding valid commercial KD Chart licenses may use this file in
00012  ** accordance with the KD Chart Commercial License Agreement provided with
00013  ** the Software.
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  ** See http://www.kdab.net/kdchart for
00019  **   information about KD Chart Commercial License Agreements.
00020  **
00021  ** Contact info@kdab.net if any conditions of this
00022  ** licensing are not clear to you.
00023  **
00024  **********************************************************************/
00025 
00026 #include "KDChartLeveyJenningsAxis.h"
00027 #include "KDChartLeveyJenningsAxis_p.h"
00028 
00029 #include <QDateTime>
00030 #include <QPainter>
00031 
00032 #include "KDChartPaintContext.h"
00033 #include "KDChartChart.h"
00034 #include "KDChartAbstractCartesianDiagram.h"
00035 #include "KDChartAbstractGrid.h"
00036 #include "KDChartPainterSaver_p.h"
00037 #include "KDChartLayoutItems.h"
00038 #include "KDChartPrintingParameters.h"
00039 
00040 #include <KDABLibFakes>
00041 
00042 #include <limits>
00043 
00044 using namespace KDChart;
00045 
00046 #define d (d_func())
00047 
00048 LeveyJenningsAxis::LeveyJenningsAxis ( LeveyJenningsDiagram* diagram )
00049     : CartesianAxis ( new Private( diagram, this ), diagram )
00050 {
00051     init();
00052 }
00053 
00054 LeveyJenningsAxis::~LeveyJenningsAxis ()
00055 {
00056     // when we remove the first axis it will unregister itself and
00057     // propagate the next one to the primary, thus the while loop
00058     while ( d->mDiagram ) {
00059         LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( d->mDiagram );
00060         cd->takeAxis( this );
00061     }
00062     Q_FOREACH( AbstractDiagram *diagram, d->secondaryDiagrams ) {
00063         LeveyJenningsDiagram *cd = qobject_cast< LeveyJenningsDiagram* >( diagram );
00064         cd->takeAxis( this );
00065     }
00066 }
00067 
00068 void LeveyJenningsAxis::init ()
00069 {
00070     setType( LeveyJenningsGridAttributes::Expected );
00071     setDateFormat( Qt::TextDate );
00072     const QStringList labels = QStringList() << tr( "-3sd" ) << tr( "-2sd" ) << tr( "mean" )
00073                                              << tr( "+2sd" ) << tr( "+3sd" );
00074 
00075     setLabels( labels );
00076 }
00077 
00081 LeveyJenningsGridAttributes::GridType LeveyJenningsAxis::type() const
00082 {
00083     return d->type;
00084 }
00085 
00095 void LeveyJenningsAxis::setType( LeveyJenningsGridAttributes::GridType type )
00096 {
00097     if( type != d->type )
00098     {
00099         TextAttributes ta = textAttributes();
00100         QPen pen = ta.pen();
00101         QColor color = type == LeveyJenningsGridAttributes::Expected ? Qt::black : Qt::blue;
00102         if( qobject_cast< const LeveyJenningsDiagram* >( d->diagram() ) && 
00103             qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() ) )
00104         {
00105             color = qobject_cast< const LeveyJenningsCoordinatePlane* >( d->diagram()->coordinatePlane() )->gridAttributes().gridPen( type ).color();
00106         }
00107         pen.setColor( color );
00108         ta.setPen( pen );
00109         setTextAttributes( ta );
00110     }
00111     d->type = type;
00112 }
00113 
00114 Qt::DateFormat LeveyJenningsAxis::dateFormat() const
00115 {
00116     return d->format;
00117 }
00118 
00119 void LeveyJenningsAxis::setDateFormat(Qt::DateFormat format)
00120 {
00121     d->format = format;
00122 }
00123 
00124 bool LeveyJenningsAxis::compare( const LeveyJenningsAxis* other )const
00125 {
00126     if( other == this ) return true;
00127     if( ! other ){
00128         //qDebug() << "CartesianAxis::compare() cannot compare to Null pointer";
00129         return false;
00130     }
00131     return  ( static_cast<const CartesianAxis*>(this)->compare( other ) ) &&
00132             ( type() == other->type() );
00133 }
00134 
00135 void LeveyJenningsAxis::paintCtx( PaintContext* context )
00136 {
00137 
00138     Q_ASSERT_X ( d->diagram(), "LeveyJenningsAxis::paint",
00139                  "Function call not allowed: The axis is not assigned to any diagram." );
00140 
00141     LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
00142     Q_ASSERT_X ( plane, "LeveyJenningsAxis::paint",
00143                  "Bad function call: PaintContext::coodinatePlane() NOT a levey jennings plane." );
00144 
00145     // note: Not having any data model assigned is no bug
00146     //       but we can not draw an axis then either.
00147     if( ! d->diagram()->model() )
00148         return;
00149 
00150     if( isOrdinate() )
00151         paintAsOrdinate( context );
00152     else
00153         paintAsAbscissa( context );
00154 }
00155 
00156 void LeveyJenningsAxis::paintAsOrdinate( PaintContext* context )
00157 {
00158     const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
00159 
00160     Q_ASSERT( isOrdinate() );
00161     LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
00162     
00163     const qreal meanValue =         type() == LeveyJenningsGridAttributes::Expected ? diag->expectedMeanValue() 
00164                                                                                     : diag->calculatedMeanValue();
00165     const qreal standardDeviation = type() == LeveyJenningsGridAttributes::Expected ? diag->expectedStandardDeviation() 
00166                                                                                     : diag->calculatedStandardDeviation();
00167     const TextAttributes labelTA = textAttributes();
00168     const bool drawLabels = labelTA.isVisible();
00169 
00170     // nothing to draw, since we've no ticks
00171     if( !drawLabels )
00172         return;
00173     
00174     const QObject* referenceArea = plane->parent();
00175 
00176     const QVector< qreal > values = QVector< qreal >() << ( meanValue - 3 * standardDeviation )
00177                                                        << ( meanValue - 2 * standardDeviation )
00178                                                        << ( meanValue )
00179                                                        << ( meanValue + 2 * standardDeviation )
00180                                                        << ( meanValue + 3 * standardDeviation );
00181 
00182     Q_ASSERT_X( values.count() <= labels().count(), "LeveyJenningsAxis::paintAsOrdinate", "Need to have at least 5 labels" );
00183 
00184     TextLayoutItem labelItem( tr( "mean" ), 
00185                               labelTA,
00186                               referenceArea,
00187                               KDChartEnums::MeasureOrientationMinimum,
00188                               Qt::AlignLeft );
00189 
00190     QPainter* const painter = context->painter();
00191     const PainterSaver ps( painter );
00192     painter->setRenderHint( QPainter::Antialiasing, true );
00193     painter->setClipping( false );
00194     
00195     painter->setPen ( PrintingParameters::scalePen( labelTA.pen() ) ); // perhaps we want to add a setter method later?
00196 
00197     for( int i = 0; i < values.count(); ++i )
00198     {
00199         const QPointF labelPos = plane->translate( QPointF( 0.0, values.at( i ) ) );
00200         const QString label = customizedLabel( labels().at( i ) );
00201         labelItem.setText( label );
00202         const QSize size = labelItem.sizeHint();
00203         const float xPos = position() == Left ? geometry().right() - size.width() : geometry().left();
00204         labelItem.setGeometry( QRectF( QPointF( xPos, labelPos.y() - size.height() / 2.0 ), size ).toRect() );
00205 
00206         // don't draw labels which aren't in the valid range (might happen for calculated SDs)
00207         if( values.at( i ) > diag->expectedMeanValue() + 4 * diag->expectedStandardDeviation() )
00208             continue;
00209 
00210         if( values.at( i ) < diag->expectedMeanValue() - 4 * diag->expectedStandardDeviation() )
00211             continue;
00212 
00213         labelItem.paint( painter );
00214     }    
00215 }
00216 
00217 void LeveyJenningsAxis::paintAsAbscissa( PaintContext* context )
00218 {
00219     Q_ASSERT( isAbscissa() );
00220 
00221     // this triggers drawing of the ticks
00222     setLabels( QStringList() << QString::fromLatin1( " " ) );
00223     CartesianAxis::paintCtx( context );
00224 
00225     const LeveyJenningsDiagram* const diag = dynamic_cast< const LeveyJenningsDiagram* >( d->diagram() );
00226     LeveyJenningsCoordinatePlane* plane = dynamic_cast<LeveyJenningsCoordinatePlane*>(context->coordinatePlane());
00227 
00228     const QObject* referenceArea = plane->parent();
00229     const TextAttributes labelTA = textAttributes();
00230     
00231     const bool drawLabels = labelTA.isVisible();
00232 
00233     if( !drawLabels )
00234         return;
00235 
00236 
00237     const QPair< QDateTime, QDateTime > range = diag->timeRange();
00238 
00239     QPainter* const painter = context->painter();
00240     const PainterSaver ps( painter );
00241     painter->setRenderHint( QPainter::Antialiasing, true );
00242     painter->setClipping( false );
00243      
00244 
00245     TextLayoutItem labelItem( range.first.date().toString( dateFormat() ), 
00246                               labelTA,
00247                               referenceArea,
00248                               KDChartEnums::MeasureOrientationMinimum,
00249                               Qt::AlignLeft );
00250     QSize origSize = labelItem.sizeHint();
00251     if( range.first.secsTo( range.second ) < 86400 )
00252         labelItem = TextLayoutItem( range.first.toString( dateFormat() ), 
00253                                   labelTA,
00254                                   referenceArea,
00255                                   KDChartEnums::MeasureOrientationMinimum,
00256                                   Qt::AlignLeft );
00257     QSize size = labelItem.sizeHint();
00258 
00259     float yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
00260     labelItem.setGeometry( QRectF( QPointF( geometry().left() - origSize.width() / 2.0, yPos ), size ).toRect() );
00261     labelItem.paint( painter );
00262 
00263     
00264     TextLayoutItem labelItem2( range.second.date().toString( dateFormat() ), 
00265                               labelTA,
00266                               referenceArea,
00267                               KDChartEnums::MeasureOrientationMinimum,
00268                               Qt::AlignLeft );
00269     origSize = labelItem2.sizeHint();
00270     if( range.first.secsTo( range.second ) < 86400 )
00271         labelItem2 = TextLayoutItem( range.second.toString( dateFormat() ), 
00272                                      labelTA,
00273                                      referenceArea,
00274                                      KDChartEnums::MeasureOrientationMinimum,
00275                                      Qt::AlignLeft );
00276     size = labelItem2.sizeHint();
00277     yPos = position() == Bottom ? geometry().bottom() - size.height() : geometry().top();
00278     labelItem2.setGeometry( QRectF( QPointF( geometry().right() - size.width() + origSize.width() / 2.0, yPos ), size ).toRect() );
00279     labelItem2.paint( painter );
00280 }

Generated on Thu Mar 4 23:19:11 2010 for KD Chart 2 by  doxygen 1.5.4