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 <QModelIndex>
00031
00032 #include "KDChartBarDiagram.h"
00033 #include "KDChartTextAttributes.h"
00034 #include "KDChartAttributesModel.h"
00035 #include "KDChartAbstractCartesianDiagram.h"
00036 #include "KDChartPercentBarDiagram_p.h"
00037
00038 using namespace KDChart;
00039
00040 PercentBarDiagram::PercentBarDiagram( BarDiagram* d )
00041 : BarDiagramType( d )
00042 {
00043 }
00044
00045 BarDiagram::BarType PercentBarDiagram::type() const
00046 {
00047 return BarDiagram::Percent;
00048 }
00049
00050 const QPair<QPointF, QPointF> PercentBarDiagram::calculateDataBoundaries() const
00051 {
00052 const int rowCount = compressor().modelDataRows();
00053 const int colCount = compressor().modelDataColumns();
00054
00055 const double xMin = 0;
00056 const double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00057 double yMin = 0.0, yMax = 0.0;
00058 for( int col = 0; col < colCount; ++col )
00059 {
00060 for( int row = 0; row < rowCount; ++row )
00061 {
00062
00063 const QModelIndex idx = diagram()->model()->index( row, col, diagram()->rootIndex() );
00064
00065 double value = diagram()->model()->data( idx ).toDouble();
00066 if ( value > 0 )
00067 yMax = qMax( yMax, value );
00068 }
00069 }
00070
00071 if ( yMax == yMin ) {
00072 if ( yMin == 0.0 )
00073 yMax = 0.1;
00074 else
00075 yMax = 0.0;
00076 }
00077 const QPointF bottomLeft( QPointF( xMin, yMin ) );
00078 const QPointF topRight( QPointF( xMax, yMax ) );
00079
00080
00081 return QPair< QPointF, QPointF >( bottomLeft, topRight );
00082 }
00083
00084 void PercentBarDiagram::paint( PaintContext* ctx )
00085 {
00086 reverseMapper().clear();
00087
00088 const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries();
00089
00090 const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00091 const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00092
00093 const int rowCount = compressor().modelDataRows();
00094 const int colCount = compressor().modelDataColumns();
00095
00096 BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00097 double barWidth = 0;
00098 double maxDepth = 0;
00099 double width = boundRight.x() - boundLeft.x();
00100 double groupWidth = width/ (rowCount + 2);
00101 double spaceBetweenBars = 0;
00102 double spaceBetweenGroups = 0;
00103
00104 if ( ba.useFixedBarWidth() ) {
00105 barWidth = ba.fixedBarWidth();
00106 groupWidth += barWidth;
00107
00108
00109
00110 if ( groupWidth < 0 )
00111 groupWidth = 0;
00112
00113 if ( groupWidth * rowCount > ctx->rectangle().width() )
00114 groupWidth = ctx->rectangle().width() / rowCount;
00115 }
00116
00117
00118
00119 double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00120
00121
00122
00123 if ( ba.useFixedDataValueGap() ) {
00124 if ( ctx->rectangle().width() > maxLimit )
00125 spaceBetweenBars += ba.fixedDataValueGap();
00126 else
00127 spaceBetweenBars = ((ctx->rectangle().width()/rowCount) - groupWidth)/(colCount-1);
00128 }
00129
00130 if ( ba.useFixedValueBlockGap() )
00131 spaceBetweenGroups += ba.fixedValueBlockGap();
00132
00133 calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00134 barWidth, spaceBetweenBars, spaceBetweenGroups );
00135
00136 DataValueTextInfoList list;
00137 const double maxValue = 100;
00138 double sumValues = 0;
00139 QVector <double > sumValuesVector;
00140
00141
00142 for( int row = 0; row < rowCount; ++row )
00143 {
00144 for( int col = 0; col < colCount; ++col )
00145 {
00146 const CartesianDiagramDataCompressor::CachePosition position( row, col );
00147 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00148 if ( point.value > 0 )
00149 sumValues += point.value;
00150 if ( col == colCount - 1 ) {
00151 sumValuesVector << sumValues ;
00152 sumValues = 0;
00153 }
00154 }
00155 }
00156
00157
00158 for( int col = 0; col < colCount; ++col )
00159 {
00160 double offset = spaceBetweenGroups;
00161 if( ba.useFixedBarWidth() )
00162 offset -= ba.fixedBarWidth();
00163
00164 if( offset < 0 )
00165 offset = 0;
00166
00167 for( int row = 0; row < rowCount ; ++row )
00168 {
00169 const CartesianDiagramDataCompressor::CachePosition position( row, col );
00170 const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position );
00171 QModelIndex sourceIndex = attributesModel()->mapToSource( p.index );
00172 ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
00173
00174 if ( threeDAttrs.isEnabled() ){
00175 if ( barWidth > 0 )
00176 barWidth = (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00177 if ( barWidth <= 0 ) {
00178 barWidth = 0;
00179 maxDepth = offset - ( width/rowCount);
00180 }
00181 }else{
00182 barWidth = (ctx->rectangle().width() - (offset*rowCount))/ rowCount;
00183 }
00184
00185 const double value = p.value;
00186 double stackedValues = 0.0;
00187 double key = 0.0;
00188
00189
00190
00191 for( int k = col; k >= 0 ; --k )
00192 {
00193 const CartesianDiagramDataCompressor::CachePosition position( row, k );
00194 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00195 if ( point.value > 0)
00196 stackedValues += point.value;
00197 key = point.key;
00198 }
00199
00200 QPointF point, previousPoint;
00201 if( sumValuesVector.at( row ) != 0 && value > 0 ) {
00202 point = ctx->coordinatePlane()->translate( QPointF( key, stackedValues / sumValuesVector.at( row ) * maxValue ) );
00203 point.rx() += offset / 2;
00204
00205 previousPoint = ctx->coordinatePlane()->translate( QPointF( key, ( stackedValues - value)/sumValuesVector.at(row)* maxValue ) );
00206 }
00207 const double barHeight = previousPoint.y() - point.y();
00208
00209 const QRectF rect( point, QSizeF( barWidth, barHeight ) );
00210 appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ),
00211 Position::NorthWest, Position::SouthEast,
00212 p.value );
00213 paintBars( ctx, sourceIndex, rect, maxDepth );
00214 }
00215 }
00216 paintDataValueTextsAndMarkers( diagram(), ctx, list, false );
00217 }