23 #include "KDChartPercentLineDiagram_p.h" 25 #include <QModelIndex> 32 #include "PaintingHelpers_p.h" 38 : LineDiagramType( d )
49 const qreal xMin = 0.0;
50 qreal xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
51 if ( !diagram()->centerDataPoints() && diagram()->model() )
53 const qreal yMin = 0.0;
54 const qreal yMax = 100.0;
56 QPointF bottomLeft( QPointF( xMin, yMin ) );
57 QPointF topRight( QPointF( xMax, yMax ) );
63 if ( qFuzzyIsNull( m_private->tension ) ) {
64 paintWithLines( ctx );
67 paintWithSplines( ctx, m_private->tension );
71 void PercentLineDiagram::paintWithLines(
PaintContext* ctx )
73 reverseMapper().clear();
75 const int columnCount = compressor().modelDataColumns();
76 const int rowCount = compressor().modelDataRows();
87 maxFound = columnCount;
89 const int lastVisibleColumn = maxFound - 1;
92 LineAttributesInfoList lineList;
101 for (
int row = 0; row < rowCount; ++row )
103 for (
int col = 0; col < columnCount; ++col )
105 const CartesianDiagramDataCompressor::CachePosition position( row, col );
106 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
107 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
108 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
111 point.value = interpolateMissingValue( position );
112 if ( point.value > 0 )
113 sumValues += point.value;
114 if ( col == lastVisibleColumn )
116 percentSumValues << sumValues ;
123 bool bFirstDataset =
true;
125 for (
int column = 0; column < columnCount; ++column )
129 QModelIndex indexPreviousCell;
133 for (
int row = 0; row < rowCount; ++row )
135 const CartesianDiagramDataCompressor::CachePosition position( row, column );
136 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
137 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
138 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
139 const bool bDisplayCellArea = laCell.
displayArea();
141 qreal stackedValues = 0, nextValues = 0, nextKey = 0;
142 for (
int column2 = column;
146 const CartesianDiagramDataCompressor::CachePosition position( row, column2 );
147 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
151 point.value = interpolateMissingValue( position );
153 const qreal val = point.value;
155 stackedValues += val;
157 if ( row + 1 < rowCount ) {
158 const CartesianDiagramDataCompressor::CachePosition position( row + 1, column2 );
159 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
163 point.value = interpolateMissingValue( position );
165 const qreal val = point.value;
171 if ( percentSumValues.at( row ) != 0 )
172 stackedValues = stackedValues / percentSumValues.at( row ) * maxValue;
176 QPointF nextPoint = ctx->
coordinatePlane()->
translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, stackedValues ) );
179 const QPointF ptNorthWest( nextPoint );
180 const QPointF ptSouthWest(
184 : bottomPoints.at( row )
190 if ( row + 1 < rowCount ) {
191 if ( percentSumValues.at( row + 1 ) != 0 )
192 nextValues = nextValues / percentSumValues.at( row + 1 ) * maxValue;
195 QPointF toPoint = ctx->
coordinatePlane()->
translate( QPointF( diagram()->centerDataPoints() ? nextKey + 0.5 : nextKey, nextValues ) );
196 lineList.append( LineAttributesInfo( sourceIndex, nextPoint, toPoint ) );
197 ptNorthEast = toPoint;
202 : bottomPoints.at( row + 1 )
205 if ( areas.count() && laCell != laPreviousCell ) {
209 if ( bDisplayCellArea ) {
211 poly << ptNorthWest << ptNorthEast << ptSouthEast << ptSouthWest;
213 laPreviousCell = laCell;
214 indexPreviousCell = sourceIndex;
219 ptNorthEast = ptNorthWest;
220 ptSouthEast = ptSouthWest;
223 if ( !ISNAN( point.value ) )
225 const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
230 if ( areas.count() ) {
234 bottomPoints = points;
235 bFirstDataset =
false;
240 void PercentLineDiagram::paintWithSplines(
PaintContext* ctx, qreal tension )
242 reverseMapper().clear();
244 const int columnCount = compressor().modelDataColumns();
245 const int rowCount = compressor().modelDataRows();
256 maxFound = columnCount;
258 const int lastVisibleColumn = maxFound - 1;
261 LineAttributesInfoList lineList;
265 qreal maxValue = 100;
270 for (
int row = 0; row < rowCount; ++row )
272 for (
int col = 0; col < columnCount; ++col )
274 const CartesianDiagramDataCompressor::CachePosition position( row, col );
275 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
276 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
277 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
280 point.value = interpolateMissingValue( position );
281 if ( point.value > 0 )
282 sumValues += point.value;
283 if ( col == lastVisibleColumn )
285 percentSumValues << sumValues ;
291 for (
int column = 0; column < columnCount; ++column )
295 QModelIndex indexPreviousCell;
298 for (
int row = 0; row < rowCount; ++row )
300 const CartesianDiagramDataCompressor::CachePosition position( row, column );
301 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
302 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
303 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
304 const bool bDisplayCellArea = laCell.
displayArea();
326 struct valueAtLambda {
328 : rowCount( rowCount )
335 PercentLineDiagram* _this;
338 qreal operator() (
int row,
int col )
const 340 if ( row < 0 || row >= rowCount ) {
344 const CartesianDiagramDataCompressor::CachePosition position( row, col );
345 const CartesianDiagramDataCompressor::DataPoint point = _this->compressor().data( position );
347 return !ISNAN( point.value ) ? point.value
353 valueAtLambda valueAt( rowCount,
this, policy );
356 struct safeAddPositiveLambda {
357 qreal operator() (qreal accumulator, qreal newValue)
const 359 return ISNAN( newValue ) || newValue <= 0 ? accumulator : accumulator + newValue;
362 safeAddPositiveLambda safeAddPositive;
368 if ( ! qFuzzyIsNull( percentSumValues.at( row ) ) ) {
369 for (
int currentRow = 0; currentRow < 4; ++currentRow ) {
370 stackedValuesTop[currentRow] = safeAddPositive( stackedValuesTop[currentRow], valueAt( row - 1 + currentRow, column ) );
373 for (
int column2 = column - 1; column2 >= 0; --column2 )
375 for (
int currentRow = 0; currentRow < 4; ++currentRow ) {
376 stackedValuesTop[currentRow] = safeAddPositive( stackedValuesTop[currentRow], valueAt( row - 1 + currentRow, column2 ) );
377 stackedValuesBottom[currentRow] = safeAddPositive( stackedValuesBottom[currentRow], valueAt( row - 1 + currentRow, column2 ) );
381 for (
int currentRow = 0; currentRow < 4; ++currentRow ) {
382 stackedValuesTop[currentRow] /= percentSumValues.at( row ) / maxValue;
383 stackedValuesBottom[currentRow] /= percentSumValues.at( row ) / maxValue;
393 struct dataAtLambda {
394 dataAtLambda(
PaintContext* ctx, PercentLineDiagram* _this )
401 PercentLineDiagram* _this;
403 QPointF operator() (
const QVector<qreal>& source, qreal key,
int index )
const 405 return ctx->
coordinatePlane()->
translate( QPointF( _this->diagram()->centerDataPoints() ? key + 0.5 : key, source[index] ) );
408 dataAtLambda dataAt( ctx,
this );
410 const QPointF ptNorthWest = dataAt( stackedValuesTop, point.key, 1 );
411 const QPointF ptSouthWest =
412 bDisplayCellArea ? dataAt( stackedValuesBottom, point.key, 1 )
418 if ( row + 1 < rowCount ) {
419 ptNorthEast = dataAt( stackedValuesTop, nextKey, 2 );
420 lineList.append( LineAttributesInfo( sourceIndex, ptNorthWest, ptNorthEast ) );
422 bDisplayCellArea ? dataAt( stackedValuesBottom, nextKey, 2 )
425 if ( areas.count() && laCell != laPreviousCell ) {
430 if ( bDisplayCellArea ) {
432 path.moveTo( ptNorthWest );
434 const QPointF ptBeforeNorthWest =
435 row > 0 ? dataAt( stackedValuesTop, point.key - 1, 0 )
437 const QPointF ptAfterNorthEast =
438 row < rowCount - 1 ? dataAt( stackedValuesTop, point.key + 2, 3 )
440 addSplineChunkTo( path, tension, ptBeforeNorthWest, ptNorthWest, ptNorthEast, ptAfterNorthEast );
442 path.lineTo( ptNorthEast );
443 path.lineTo( ptSouthEast );
445 const QPointF ptBeforeSouthWest =
446 row > 0 ? dataAt( stackedValuesBottom, point.key - 1, 0 )
448 const QPointF ptAfterSouthEast =
449 row < rowCount - 1 ? dataAt( stackedValuesBottom, point.key + 2, 3 )
451 addSplineChunkTo( path, tension, ptAfterSouthEast, ptSouthEast, ptSouthWest, ptBeforeSouthWest, ReverseSplineDirection );
454 laPreviousCell = laCell;
455 indexPreviousCell = sourceIndex;
460 ptNorthEast = ptNorthWest;
461 ptSouthEast = ptSouthWest;
464 if ( !ISNAN( point.value ) )
466 const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
471 if ( areas.count() ) {
KDChartEnums::PositionValue value() const
Returns an integer value corresponding to this Position.
void paintElements(AbstractDiagram::Private *diagramPrivate, PaintContext *ctx, const LabelPaintCache &lpc, const LineAttributesInfoList &lineList)
virtual const QPointF translate(const QPointF &diagramPoint) const =0
Translate the given point in value space coordinates to a position in pixel space.
AbstractCoordinatePlane * coordinatePlane() const
Set of attributes for changing the appearance of line charts.
void paintAreas(AbstractDiagram::Private *diagramPrivate, PaintContext *ctx, const QModelIndex &index, const QList< QPolygonF > &areas, uint opacity)
static const Position & NorthWest
LineDiagram defines a common line diagram.
Stores information about painting diagrams.
Stores the absolute target points of a Position.
MissingValuesPolicy
MissingValuesPolicy specifies how a missing value will be shown in a line diagram.
uint transparency() const
MissingValuesPolicy missingValuesPolicy() const