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