00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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();
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
00090
00091 if ( groupWidth < 0 )
00092 groupWidth = 0;
00093
00094 if ( groupWidth * rowCount > width )
00095 groupWidth = width / rowCount;
00096 }
00097
00098
00099
00100 double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00101
00102
00103
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;
00119 double sumValues = 0;
00120 QVector <double > sumValuesVector;
00121
00122
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
00130 sumValues += qMax( point.value, -point.value );
00131 if ( col == colCount - 1 ) {
00132 sumValuesVector << sumValues ;
00133 sumValues = 0;
00134 }
00135 }
00136 }
00137
00138
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
00171
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 }