KD Chart 2  [rev.2.5]
KDChartNormalBarDiagram_p.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 "KDChartNormalBarDiagram_p.h"
00024 
00025 #include <QModelIndex>
00026 
00027 #include "KDChartBarDiagram.h"
00028 #include "KDChartTextAttributes.h"
00029 #include "KDChartAttributesModel.h"
00030 #include "KDChartAbstractCartesianDiagram.h"
00031 
00032 using namespace KDChart;
00033 using namespace std;
00034 
00035 NormalBarDiagram::NormalBarDiagram( BarDiagram* d )
00036     : BarDiagramType( d )
00037 {
00038 }
00039 
00040 BarDiagram::BarType NormalBarDiagram::type() const
00041 {
00042     return BarDiagram::Normal;
00043 }
00044 
00045 const QPair<QPointF, QPointF> NormalBarDiagram::calculateDataBoundaries() const
00046 {
00047     const int rowCount = compressor().modelDataRows();
00048     const int colCount = compressor().modelDataColumns();
00049 
00050     const qreal xMin = 0.0;
00051     const qreal xMax = rowCount;
00052     qreal yMin = 0.0;
00053     qreal yMax = 0.0;
00054 
00055     qreal usedDepth = 0;
00056 
00057     bool isFirst = true;
00058     for ( int column = 0; column < colCount; ++column ) {
00059         for ( int row = 0; row < rowCount; ++row ) {
00060             const CartesianDiagramDataCompressor::CachePosition position( row, column );
00061             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00062             const qreal value = ISNAN( point.value ) ? 0.0 : point.value;
00063 
00064             QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00065             ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
00066 
00067             if ( threeDAttrs.isEnabled() )
00068                 usedDepth = qMax( usedDepth, threeDAttrs.depth() );
00069 
00070             // this is always true yMin can be 0 in case all values
00071             // are the same
00072             // same for yMax it can be zero if all values are negative
00073             if ( isFirst ) {
00074                 yMin = value;
00075                 yMax = value;
00076                 isFirst = false;
00077             } else {
00078                 yMin = qMin( yMin, value );
00079                 yMax = qMax( yMax, value );
00080             }
00081         }
00082     }
00083 
00084     // special cases
00085     if ( yMax == yMin ) {
00086         if ( yMin == 0.0 ) {
00087             yMax = 0.1; // we need at least a range
00088         } else if ( yMax < 0.0 ) {
00089             yMax = 0.0; // extend the range to zero
00090         } else if ( yMin > 0.0 ) {
00091             yMin = 0.0; // dito
00092         }
00093     }
00094 
00095     return QPair< QPointF, QPointF >( QPointF( xMin, yMin ), QPointF( xMax, yMax ) );
00096 }
00097 
00098 void NormalBarDiagram::paint( PaintContext* ctx )
00099 {
00100     reverseMapper().clear();
00101 
00102     const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached
00103 
00104     const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00105     const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00106 
00107     const int rowCount = attributesModel()->rowCount(attributesModelRootIndex());
00108     const int colCount = attributesModel()->columnCount(attributesModelRootIndex());
00109 
00110     BarAttributes ba = diagram()->barAttributes();
00111     ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes();
00112 
00113     //we need some margin (hence the 2.5) for the three dimensional depth
00114     const qreal threeDepthMargin = ( threeDAttrs.isEnabled() ) ? 2.5 * threeDAttrs.depth() : 0;
00115 
00116     qreal barWidth = 0;
00117     qreal maxDepth = 0;
00118     qreal width = boundRight.x() - boundLeft.x() - threeDepthMargin;
00119     qreal groupWidth = width / rowCount;
00120     qreal spaceBetweenBars = 0;
00121     qreal spaceBetweenGroups = 0;
00122 
00123     if ( ba.useFixedBarWidth() ) {
00124 
00125         barWidth = ba.fixedBarWidth();
00126         groupWidth += barWidth;
00127 
00128         // Pending Michel set a min and max value for the groupWidth
00129         // related to the area.width
00130         if ( groupWidth < 0 )
00131             groupWidth = 0;
00132 
00133         if ( groupWidth  * rowCount > width )
00134             groupWidth = width / rowCount;
00135     }
00136 
00137     // maxLimit: allow the space between bars to be larger until area.width()
00138     // is covered by the groups.
00139     qreal maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00140 
00141     //Pending Michel: FixMe
00142     if ( ba.useFixedDataValueGap() ) {
00143         if ( width > maxLimit ) {
00144             spaceBetweenBars += ba.fixedDataValueGap();
00145         } else {
00146             spaceBetweenBars = ( ( width / rowCount ) - groupWidth ) / ( colCount - 1 );
00147         }
00148     }
00149 
00150     if ( ba.useFixedValueBlockGap() ) {
00151         spaceBetweenGroups += ba.fixedValueBlockGap();
00152     }
00153 
00154     calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00155                                 barWidth, spaceBetweenBars, spaceBetweenGroups );
00156 
00157     LabelPaintCache lpc;
00158 
00159     for ( int row = 0; row < rowCount; ++row ) {
00160         qreal offset = -groupWidth / 2 + spaceBetweenGroups / 2;
00161 
00162         if ( ba.useFixedDataValueGap() ) {
00163             if ( spaceBetweenBars > 0 ) {
00164                 if ( width > maxLimit ) {
00165                     offset -= ba.fixedDataValueGap();
00166                 } else {
00167                     offset -= ( ( width / rowCount ) - groupWidth ) / ( colCount - 1 );
00168                 }
00169             } else {
00170                 offset += barWidth / 2;
00171             }
00172         }
00173 
00174         for ( int column = 0; column < colCount; ++column ) {
00175             // paint one group
00176             const CartesianDiagramDataCompressor::CachePosition position( row,  column );
00177             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00178             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00179             const qreal value = point.value;//attributesModel()->data( sourceIndex ).toReal();
00180             if ( ! point.hidden && !ISNAN( value ) ) {
00181                 QPointF topPoint = ctx->coordinatePlane()->translate( QPointF( point.key + 0.5, value ) );
00182                 QPointF bottomPoint =  ctx->coordinatePlane()->translate( QPointF( point.key, 0 ) );
00183 
00184                 if ( threeDAttrs.isEnabled() ) {
00185                     const qreal usedDepth = threeDAttrs.depth()/4;
00186                     topPoint.setY( topPoint.y() + usedDepth + 1.0 );
00187                 }
00188 
00189                 const qreal barHeight = bottomPoint.y() - topPoint.y();
00190                 topPoint.setX( topPoint.x() + offset );
00191                 const QRectF rect( topPoint, QSizeF( barWidth, barHeight ) );
00192                 addLabel( &lpc, sourceIndex, PositionPoints( rect ), Position::North,
00193                           Position::South, point.value );
00194                 paintBars( ctx, sourceIndex, rect, maxDepth );
00195             }
00196             offset += barWidth + spaceBetweenBars;
00197         }
00198     }
00199     paintDataValueTextsAndMarkers( ctx, lpc, false );
00200 }
 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/