KDChartPercentBarDiagram_p.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003    */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KD Chart library.
00009  **
00010  ** This file may be distributed and/or modified under the terms of the
00011  ** GNU General Public License version 2 as published by the Free Software
00012  ** Foundation and appearing in the file LICENSE.GPL included in the
00013  ** packaging of this file.
00014  **
00015  ** Licensees holding valid commercial KD Chart licenses may use this file in
00016  ** accordance with the KD Chart Commercial License Agreement provided with
00017  ** the Software.
00018  **
00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021  **
00022  ** See http://www.kdab.net/kdchart for
00023  **   information about KD Chart Commercial License Agreements.
00024  **
00025  ** Contact info@kdab.net if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 
00030 #include "KDChartPercentBarDiagram_p.h"
00031 
00032 #include <QModelIndex>
00033 
00034 #include "KDChartBarDiagram.h"
00035 #include "KDChartTextAttributes.h"
00036 #include "KDChartAttributesModel.h"
00037 #include "KDChartAbstractCartesianDiagram.h"
00038 
00039 using namespace KDChart;
00040 
00041 PercentBarDiagram::PercentBarDiagram( BarDiagram* d )
00042     : BarDiagramType( d )
00043 {
00044 }
00045 
00046 BarDiagram::BarType PercentBarDiagram::type() const
00047 {
00048     return BarDiagram::Percent;
00049 }
00050 
00051 const QPair<QPointF, QPointF> PercentBarDiagram::calculateDataBoundaries() const
00052 {
00053     const double xMin = 0.0;
00054     const double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00055     const double yMin = 0.0;
00056     const double yMax = 100.0;
00057 
00058     const QPointF bottomLeft( QPointF( xMin, yMin ) );
00059     const QPointF topRight( QPointF( xMax, yMax ) );
00060 
00061     //qDebug() << "BarDiagram::calculateDataBoundaries () returns ( " << bottomLeft << topRight <<")";
00062     return QPair< QPointF, QPointF >( bottomLeft,  topRight );
00063 }
00064 
00065 void PercentBarDiagram::paint( PaintContext* ctx )
00066 {
00067     reverseMapper().clear();
00068 
00069     const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached
00070 
00071     const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00072     const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00073 
00074     const int rowCount = compressor().modelDataRows();
00075     const int colCount = compressor().modelDataColumns();
00076 
00077     BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00078     double barWidth = 0;
00079     double maxDepth = 0;
00080     double width = boundRight.x() - boundLeft.x();
00081     double groupWidth = width/ (rowCount + 2);
00082     double spaceBetweenBars = 0;
00083     double spaceBetweenGroups = 0;
00084 
00085     if ( ba.useFixedBarWidth() ) {
00086         barWidth = ba.fixedBarWidth();
00087         groupWidth += barWidth;
00088 
00089         // Pending Michel set a min and max value for the groupWidth
00090         // related to the area.width
00091         if ( groupWidth < 0 )
00092             groupWidth = 0;
00093 
00094         if ( groupWidth  * rowCount > width )
00095             groupWidth = width / rowCount;
00096     }
00097 
00098     // maxLimit: allow the space between bars to be larger until area.width()
00099     // is covered by the groups.
00100     double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00101 
00102 
00103     //Pending Michel: FixMe
00104     if ( ba.useFixedDataValueGap() ) {
00105         if ( width > maxLimit )
00106             spaceBetweenBars += ba.fixedDataValueGap();
00107         else
00108             spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1);
00109     }
00110 
00111     if ( ba.useFixedValueBlockGap() )
00112         spaceBetweenGroups += ba.fixedValueBlockGap();
00113 
00114     calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00115                                 barWidth, spaceBetweenBars, spaceBetweenGroups );
00116 
00117     DataValueTextInfoList list;
00118     const double maxValue = 100; // always 100 %
00119     double sumValues = 0;
00120     QVector <double > sumValuesVector;
00121 
00122     //calculate sum of values for each column and store
00123     for( int row = 0; row < rowCount; ++row )
00124     {
00125         for( int col = 0; col < colCount; ++col )
00126         {
00127             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00128             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00129             //if ( point.value > 0 )
00130             sumValues += qMax( point.value, -point.value );
00131             if ( col == colCount - 1 ) {
00132                 sumValuesVector <<  sumValues ;
00133                 sumValues = 0;
00134             }
00135         }
00136     }
00137 
00138     // calculate stacked percent value
00139     for( int col = 0; col < colCount; ++col )
00140     {
00141         double offset = spaceBetweenGroups;
00142         if( ba.useFixedBarWidth() )
00143             offset -= ba.fixedBarWidth();
00144         
00145         if( offset < 0 )
00146             offset = 0;
00147 
00148         for( int row = 0; row < rowCount ; ++row )
00149         {
00150             const CartesianDiagramDataCompressor::CachePosition position( row, col );
00151             const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
00152             QModelIndex sourceIndex = attributesModel()->mapToSource( p.index );
00153             ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
00154 
00155             if ( threeDAttrs.isEnabled() ){
00156                 if ( barWidth > 0 )
00157                     barWidth =  (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00158                 if ( barWidth <= 0 ) {
00159                     barWidth = 0;
00160                     maxDepth = offset - ( width/rowCount);
00161                 }
00162             }else{
00163                 barWidth = (width - (offset*rowCount))/ rowCount;
00164             }
00165 
00166             const double value = qMax( p.value, -p.value );
00167             double stackedValues = 0.0;
00168             double key = 0.0;
00169             
00170             // calculate stacked percent value
00171             // we only take in account positives values for now.
00172             for( int k = col; k >= 0 ; --k )
00173             {
00174                 const CartesianDiagramDataCompressor::CachePosition position( row, k );
00175                 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00176                 stackedValues += qMax( point.value, -point.value );
00177                 key = point.key;
00178             }
00179 
00180             QPointF point, previousPoint;
00181             if(  sumValuesVector.at( row ) != 0 && value > 0 ) {
00182                 point = ctx->coordinatePlane()->translate( QPointF( key,  stackedValues / sumValuesVector.at( row ) * maxValue ) );
00183                 point.rx() += offset / 2;
00184 
00185                 previousPoint = ctx->coordinatePlane()->translate( QPointF( key, ( stackedValues - value)/sumValuesVector.at(row)* maxValue ) );
00186             }
00187             const double barHeight = previousPoint.y() - point.y();
00188 
00189             const QRectF rect( point, QSizeF( barWidth, barHeight ) );
00190             appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ),
00191                                               Position::NorthWest, Position::SouthEast,
00192                                               value );
00193             paintBars( ctx, sourceIndex, rect, maxDepth );
00194         }
00195     }
00196     paintDataValueTextsAndMarkers(  diagram(),  ctx,  list,  false );
00197 }

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