KDChartNormalBarDiagram_p.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KDChartNormalBarDiagram_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 using namespace std;
00034
00035 NormalBarDiagram::NormalBarDiagram( BarDiagram* d )
00036 : BarDiagramType( d )
00037 {
00038 }
00039
00040 BarDiagram::BarType NormalBarDiagram::type() const
00041 {
00042 return BarDiagram::Normal;
00043 }
00044
00045 const QPair<QPointF, QPointF> NormalBarDiagram::calculateDataBoundaries() const
00046 {
00047 const int rowCount = compressor().modelDataRows();
00048 const int colCount = compressor().modelDataColumns();
00049
00050 double xMin = 0.0;
00051 double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
00052 double yMin = 0.0, yMax = 0.0;
00053
00054 double usedDepth = 0;
00055
00056 bool bStarting = true;
00057 for ( int column = 0; column < colCount; ++column )
00058 {
00059 for ( int row = 0; row < rowCount; ++row )
00060 {
00061 const CartesianDiagramDataCompressor::CachePosition position( row, column );
00062 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00063 const double value = ISNAN( point.value ) ? 0.0 : point.value;
00064
00065 QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00066 ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex );
00067
00068 if ( threeDAttrs.isEnabled() )
00069 usedDepth = qMax( usedDepth, threeDAttrs.depth() );
00070
00071
00072
00073
00074 if( bStarting ){
00075 yMin = value;
00076 yMax = value;
00077 bStarting = false;
00078 }else{
00079 yMin = qMin( yMin, value );
00080 yMax = qMax( yMax, value );
00081 }
00082 }
00083 }
00084
00085
00086 if ( yMax == yMin ) {
00087 if ( yMin == 0.0 )
00088 yMax = 0.1;
00089 else if( yMax < 0.0 )
00090 yMax = 0.0;
00091 else if( yMin > 0.0 )
00092 yMin = 0.0;
00093 }
00094 const QPointF bottomLeft ( QPointF( xMin, yMin ) );
00095 const QPointF topRight ( QPointF( xMax, yMax ) );
00096
00097
00098
00099 return QPair< QPointF, QPointF >( bottomLeft, topRight );
00100 }
00101
00102 void NormalBarDiagram::paint( PaintContext* ctx )
00103 {
00104 reverseMapper().clear();
00105
00106 const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries();
00107
00108 const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ;
00109 const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second );
00110
00111 const int rowCount = attributesModel()->rowCount(attributesModelRootIndex());
00112 const int colCount = attributesModel()->columnCount(attributesModelRootIndex());
00113
00114 BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00115 ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) );
00116 double barWidth = 0;
00117 double maxDepth = 0;
00118 double width = boundRight.x() - boundLeft.x();
00119 double groupWidth = width / (rowCount + 2);
00120 double spaceBetweenBars = 0;
00121 double spaceBetweenGroups = 0;
00122
00123 if ( ba.useFixedBarWidth() ) {
00124
00125 barWidth = ba.fixedBarWidth();
00126 groupWidth += barWidth;
00127
00128
00129
00130 if ( groupWidth < 0 )
00131 groupWidth = 0;
00132
00133 if ( groupWidth * rowCount > width )
00134 groupWidth = width / rowCount;
00135 }
00136
00137
00138
00139 double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00140
00141
00142 if ( ba.useFixedDataValueGap() ) {
00143 if ( width > maxLimit )
00144 spaceBetweenBars += ba.fixedDataValueGap();
00145 else
00146 spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1);
00147 }
00148
00149 if ( ba.useFixedValueBlockGap() ) {
00150 spaceBetweenGroups += ba.fixedValueBlockGap();
00151 }
00152
00153 calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00154 barWidth, spaceBetweenBars, spaceBetweenGroups );
00155
00156 DataValueTextInfoList list;
00157
00158 for( int row = 0; row < rowCount; ++row )
00159 {
00160 double offset = -groupWidth/2 + spaceBetweenGroups/2;
00161
00162 if ( ba.useFixedDataValueGap() )
00163 {
00164 if ( spaceBetweenBars > 0 )
00165 {
00166 if ( width > maxLimit )
00167 offset -= ba.fixedDataValueGap();
00168 else
00169 offset -= ((width/rowCount) - groupWidth)/(colCount-1);
00170
00171 }
00172 else
00173 {
00174 offset += barWidth/2;
00175 }
00176 }
00177
00178 for( int column=0; column< colCount; ++column )
00179 {
00180
00181 const CartesianDiagramDataCompressor::CachePosition position( row, column );
00182 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00183 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00184 const qreal value = point.value;
00185 if ( ! point.hidden && !ISNAN( value ) ) {
00186 QPointF topPoint = ctx->coordinatePlane()->translate( QPointF( point.key + 0.5, value ) );
00187 QPointF bottomPoint = ctx->coordinatePlane()->translate( QPointF( point.key, 0 ) );
00188
00189 if ( threeDAttrs.isEnabled() ) {
00190 const double usedDepth = threeDAttrs.depth()/4;
00191 topPoint.setY( topPoint.y() + usedDepth + 1.0 );
00192 }
00193
00194 const double barHeight = bottomPoint.y() - topPoint.y();
00195 topPoint.setX( topPoint.x() + offset );
00196 const QRectF rect( topPoint, QSizeF( barWidth, barHeight ) );
00197 appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ),
00198 Position::NorthWest, Position::SouthEast,
00199 point.value );
00200 paintBars( ctx, sourceIndex, rect, maxDepth );
00201 }
00202 offset += barWidth + spaceBetweenBars;
00203 }
00204 }
00205 paintDataValueTextsAndMarkers( diagram(), ctx, list, false );
00206 }