23 #include "KDChartStackedLineDiagram_p.h" 25 #include <QAbstractItemModel> 32 #include "PaintingHelpers_p.h" 38 : LineDiagramType( d )
49 const int rowCount = compressor().modelDataRows();
50 const int colCount = compressor().modelDataColumns();
52 qreal xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) : 0;
53 if ( !diagram()->centerDataPoints() && diagram()->model() )
55 qreal yMin = 0, yMax = 0;
57 bool bStarting =
true;
58 for (
int row = 0; row < rowCount; ++row )
61 qreal stackedValues = 0.0;
62 qreal negativeStackedValues = 0.0;
63 for (
int col = datasetDimension() - 1; col < colCount; col += datasetDimension() ) {
64 const CartesianDiagramDataCompressor::CachePosition position( row, col );
65 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
67 if ( ISNAN( point.value ) )
70 if ( point.value >= 0.0 )
71 stackedValues += point.value;
73 negativeStackedValues += point.value;
82 yMin = qMin( qMin( yMin, negativeStackedValues ), stackedValues );
83 yMax = qMax( qMax( yMax, negativeStackedValues ), stackedValues );
87 const QPointF bottomLeft( xMin, yMin );
88 const QPointF topRight( xMax, yMax );
95 if ( qFuzzyIsNull( m_private->tension ) ) {
96 paintWithLines( ctx );
99 paintWithSplines( ctx, m_private->tension );
103 void StackedLineDiagram::paintWithLines(
PaintContext* ctx )
105 reverseMapper().clear();
107 const int columnCount = compressor().modelDataColumns();
108 const int rowCount = compressor().modelDataRows();
123 LineAttributesInfoList lineList;
128 bool bFirstDataset =
true;
130 for (
int column = 0; column < columnCount; ++column )
132 CartesianDiagramDataCompressor::CachePosition previousCellPosition;
136 QModelIndex indexPreviousCell;
140 for (
int row = 0; row < rowCount; ++row ) {
141 const CartesianDiagramDataCompressor::CachePosition position( row, column );
142 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
143 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
145 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
146 const bool bDisplayCellArea = laCell.
displayArea();
153 qreal stackedValues = 0, nextValues = 0, nextKey = 0;
154 for (
int column2 = column; column2 >= 0; --column2 )
156 const CartesianDiagramDataCompressor::CachePosition position( row, column2 );
157 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
158 if ( !ISNAN( point.value ) )
160 stackedValues += point.value;
164 const qreal interpolation = interpolateMissingValue( position );
165 if ( !ISNAN( interpolation ) )
166 stackedValues += interpolation;
170 if ( row + 1 < rowCount ) {
171 const CartesianDiagramDataCompressor::CachePosition position( row + 1, column2 );
172 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
173 if ( !ISNAN( point.value ) )
175 nextValues += point.value;
179 const qreal interpolation = interpolateMissingValue( position );
180 if ( !ISNAN( interpolation ) )
181 nextValues += interpolation;
187 const QPointF nextPoint = ctx->
coordinatePlane()->
translate( QPointF( diagram()->centerDataPoints() ? point.key + 0.5 : point.key, stackedValues ) );
190 const QPointF ptNorthWest( nextPoint );
191 const QPointF ptSouthWest(
195 : bottomPoints.at( row )
201 if ( row + 1 < rowCount ) {
202 QPointF toPoint = ctx->
coordinatePlane()->
translate( QPointF( diagram()->centerDataPoints() ? nextKey + 0.5 : nextKey, nextValues ) );
203 lineList.append( LineAttributesInfo( sourceIndex, nextPoint, toPoint ) );
204 ptNorthEast = toPoint;
209 : bottomPoints.at( row + 1 )
212 if ( areas.count() && laCell != laPreviousCell ) {
216 if ( bDisplayCellArea ) {
218 poly << ptNorthWest << ptNorthEast << ptSouthEast << ptSouthWest;
220 laPreviousCell = laCell;
221 indexPreviousCell = sourceIndex;
226 ptNorthEast = ptNorthWest;
227 ptSouthEast = ptSouthWest;
230 const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
231 if ( !ISNAN( point.value ) )
235 if ( areas.count() ) {
239 bottomPoints = points;
240 bFirstDataset =
false;
245 void StackedLineDiagram::paintWithSplines(
PaintContext* ctx, qreal tension )
247 reverseMapper().clear();
249 const int columnCount = compressor().modelDataColumns();
250 const int rowCount = compressor().modelDataRows();
265 LineAttributesInfoList lineList;
269 for (
int column = 0; column < columnCount; ++column )
271 CartesianDiagramDataCompressor::CachePosition previousCellPosition;
275 QModelIndex indexPreviousCell;
278 for (
int row = 0; row < rowCount; ++row ) {
279 const CartesianDiagramDataCompressor::CachePosition position( row, column );
280 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
281 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
283 const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
284 const bool bDisplayCellArea = laCell.
displayArea();
309 struct valueAtLambda {
311 : rowCount( rowCount )
318 StackedLineDiagram* _this;
321 qreal operator() (
int row,
int col )
const 323 if ( row < 0 || row >= rowCount ) {
327 const CartesianDiagramDataCompressor::CachePosition position( row, col );
328 const CartesianDiagramDataCompressor::DataPoint point = _this->compressor().data( position );
330 return !ISNAN( point.value ) ? point.value
336 valueAtLambda valueAt( rowCount,
this, policy );
339 struct safeAddLambda {
340 qreal operator() (qreal accumulator, qreal newValue)
const 342 return ISNAN( newValue ) ? accumulator : accumulator + newValue;
345 safeAddLambda safeAdd;
351 for (
int currentRow = 0; currentRow < 4; ++currentRow ) {
352 stackedValuesTop[currentRow] = safeAdd( stackedValuesTop[currentRow], valueAt( row - 1 + currentRow, column ) );
355 for (
int column2 = column - 1; column2 >= 0; --column2 )
357 for (
int currentRow = 0; currentRow < 4; ++currentRow ) {
358 stackedValuesTop[currentRow] = safeAdd( stackedValuesTop[currentRow], valueAt( row - 1 + currentRow, column2 ) );
359 stackedValuesBottom[currentRow] = safeAdd( stackedValuesBottom[currentRow], valueAt( row - 1 + currentRow, column2 ) );
369 struct dataAtLambda {
370 dataAtLambda(
PaintContext* ctx, StackedLineDiagram* _this )
377 StackedLineDiagram* _this;
379 QPointF operator() (
const QVector<qreal>& source, qreal key,
int index )
const 381 return ctx->
coordinatePlane()->
translate( QPointF( _this->diagram()->centerDataPoints() ? key + 0.5 : key, source[index] ) );
384 dataAtLambda dataAt( ctx,
this );
386 const QPointF ptNorthWest = dataAt( stackedValuesTop, point.key, 1 );
387 const QPointF ptSouthWest =
388 bDisplayCellArea ? dataAt( stackedValuesBottom, point.key, 1 )
394 if ( row + 1 < rowCount ) {
395 ptNorthEast = dataAt( stackedValuesTop, nextKey, 2 );
396 lineList.append( LineAttributesInfo( sourceIndex, ptNorthWest, ptNorthEast ) );
398 bDisplayCellArea ? dataAt( stackedValuesBottom, nextKey, 2 )
401 if ( areas.count() && laCell != laPreviousCell ) {
406 if ( bDisplayCellArea ) {
408 path.moveTo( ptNorthWest );
410 const QPointF ptBeforeNorthWest =
411 row > 0 ? dataAt( stackedValuesTop, point.key - 1, 0 )
413 const QPointF ptAfterNorthEast =
414 row < rowCount - 1 ? dataAt( stackedValuesTop, point.key + 2, 3 )
416 addSplineChunkTo( path, tension, ptBeforeNorthWest, ptNorthWest, ptNorthEast, ptAfterNorthEast );
418 path.lineTo( ptNorthEast );
419 path.lineTo( ptSouthEast );
421 const QPointF ptBeforeSouthWest =
422 row > 0 ? dataAt( stackedValuesBottom, point.key - 1, 0 )
424 const QPointF ptAfterSouthEast =
425 row < rowCount - 1 ? dataAt( stackedValuesBottom, point.key + 2, 3 )
427 addSplineChunkTo( path, tension, ptAfterSouthEast, ptSouthEast, ptSouthWest, ptBeforeSouthWest, ReverseSplineDirection );
430 laPreviousCell = laCell;
431 indexPreviousCell = sourceIndex;
436 ptNorthEast = ptNorthWest;
437 ptSouthEast = ptSouthWest;
440 const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
441 if ( !ISNAN( point.value ) )
445 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