KD Chart 2  [rev.2.5]
KDChartPercentBarDiagram_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 "KDChartPercentBarDiagram_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 
00034 PercentBarDiagram::PercentBarDiagram( BarDiagram* d )
00035     : BarDiagramType( d )
00036 {
00037 }
00038 
00039 BarDiagram::BarType PercentBarDiagram::type() const
00040 {
00041     return BarDiagram::Percent;
00042 }
00043 
00044 const QPair<QPointF, QPointF> PercentBarDiagram::calculateDataBoundaries() const
00045 {
00046     const int rowCount = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00047     const int colCount = diagram()->model() ? diagram()->model()->columnCount( diagram()->rootIndex() ) : 0;
00048 
00049     const qreal xMin = 0.0;
00050     const qreal xMax = rowCount;
00051     const qreal yMin = 0.0;
00052     const qreal yMax = 100.0;
00053 
00054     qreal usedDepth = 0;
00055 
00056     for( int row = 0; row < rowCount ; ++row ) {
00057         for( int col = 0; col < colCount; ++col ) {
00058             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00059             const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
00060             QModelIndex sourceIndex = attributesModel()->mapToSource( p.index );
00061             ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
00062 
00063             if ( threeDAttrs.isEnabled() && threeDAttrs.depth() > usedDepth ) {
00064                 usedDepth = threeDAttrs.depth();
00065             }
00066         }
00067     }
00068 
00069     return QPair< QPointF, QPointF >( QPointF( xMin, yMin ), QPointF( xMax, yMax + usedDepth * 0.3 ) );
00070 }
00071 
00072 void PercentBarDiagram::paint( PaintContext* ctx )
00073 {
00074     reverseMapper().clear();
00075 
00076     const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached
00077 
00078     const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00079     const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00080 
00081     const int rowCount = compressor().modelDataRows();
00082     const int colCount = compressor().modelDataColumns();
00083 
00084     BarAttributes ba = diagram()->barAttributes();
00085     qreal barWidth = 0;
00086     qreal maxDepth = 0;
00087     qreal width = boundRight.x() - boundLeft.x();
00088     qreal groupWidth = width/ (rowCount + 2);
00089     qreal spaceBetweenBars = 0;
00090     qreal spaceBetweenGroups = 0;
00091 
00092     if ( ba.useFixedBarWidth() ) {
00093         barWidth = ba.fixedBarWidth();
00094         groupWidth += barWidth;
00095 
00096         // Pending Michel set a min and max value for the groupWidth
00097         // related to the area.width
00098         if ( groupWidth < 0 )
00099             groupWidth = 0;
00100 
00101         if ( groupWidth  * rowCount > width )
00102             groupWidth = width / rowCount;
00103     }
00104 
00105     // maxLimit: allow the space between bars to be larger until area.width()
00106     // is covered by the groups.
00107     qreal maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00108 
00109 
00110     //Pending Michel: FixMe
00111     if ( ba.useFixedDataValueGap() ) {
00112         if ( width > maxLimit )
00113             spaceBetweenBars += ba.fixedDataValueGap();
00114         else
00115             spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1);
00116     }
00117 
00118     if ( ba.useFixedValueBlockGap() )
00119         spaceBetweenGroups += ba.fixedValueBlockGap();
00120 
00121     calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00122                                 barWidth, spaceBetweenBars, spaceBetweenGroups );
00123 
00124     LabelPaintCache lpc;
00125     const qreal maxValue = 100; // always 100 %
00126     qreal sumValues = 0;
00127     QVector <qreal > sumValuesVector;
00128 
00129     //calculate sum of values for each column and store
00130     for( int row = 0; row < rowCount; ++row )
00131     {
00132         for( int col = 0; col < colCount; ++col )
00133         {
00134             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00135             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00136             //if ( point.value > 0 )
00137             sumValues += qMax( point.value, -point.value );
00138             if ( col == colCount - 1 ) {
00139                 sumValuesVector <<  sumValues ;
00140                 sumValues = 0;
00141             }
00142         }
00143     }
00144 
00145     // calculate stacked percent value
00146     for( int col = 0; col < colCount; ++col )
00147     {
00148         qreal offset = spaceBetweenGroups;
00149         if( ba.useFixedBarWidth() )
00150             offset -= ba.fixedBarWidth();
00151         
00152         if( offset < 0 )
00153             offset = 0;
00154 
00155         for( int row = 0; row < rowCount ; ++row )
00156         {
00157             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00158             const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
00159             QModelIndex sourceIndex = attributesModel()->mapToSource( p.index );
00160             ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
00161 
00162             if ( threeDAttrs.isEnabled() ){
00163                 if ( barWidth > 0 )
00164                     barWidth =  (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00165                 if ( barWidth <= 0 ) {
00166                     barWidth = 0;
00167                     maxDepth = offset - ( width/rowCount);
00168                 }
00169             }else{
00170                 barWidth = (width - (offset*rowCount))/ rowCount;
00171             }
00172 
00173             const qreal value = qMax( p.value, -p.value );
00174             qreal stackedValues = 0.0;
00175             qreal key = 0.0;
00176             
00177             // calculate stacked percent value
00178             // we only take in account positives values for now.
00179             for( int k = col; k >= 0 ; --k )
00180             {
00181                 const CartesianDiagramDataCompressor::CachePosition position( row, k );
00182                 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00183                 stackedValues += qMax( point.value, -point.value );
00184                 key = point.key;
00185             }
00186 
00187             QPointF point, previousPoint;
00188             if( sumValuesVector.at( row ) != 0 && value > 0 ) {
00189                 point = ctx->coordinatePlane()->translate( QPointF( key,  stackedValues / sumValuesVector.at( row ) * maxValue ) );
00190                 point.rx() += offset / 2;
00191 
00192                 previousPoint = ctx->coordinatePlane()->translate( QPointF( key, ( stackedValues - value)/sumValuesVector.at(row)* maxValue ) );
00193             }
00194             const qreal barHeight = previousPoint.y() - point.y();
00195 
00196             const QRectF rect( point, QSizeF( barWidth, barHeight ) );
00197             addLabel( &lpc, sourceIndex, PositionPoints( rect ), Position::North,
00198                       Position::South, value );
00199             paintBars( ctx, sourceIndex, rect, maxDepth );
00200         }
00201     }
00202     paintDataValueTextsAndMarkers( ctx, lpc, false );
00203 }
 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/