void NormalLyingBarDiagram::paint( PaintContext* ctx ) { reverseMapper().clear(); const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ; const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second ); const int rowCount = attributesModel()->rowCount(attributesModelRootIndex()); const int colCount = attributesModel()->columnCount(attributesModelRootIndex()); BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) ); double barWidth = 0; double maxDepth = 0; double width = boundLeft.y() - boundRight.y(); double groupWidth = width / (rowCount + 2); double spaceBetweenBars = 0; double spaceBetweenGroups = 0; if ( ba.useFixedBarWidth() ) { barWidth = ba.fixedBarWidth(); groupWidth += barWidth; // Pending Michel set a min and max value for the groupWidth // related to the area.width if ( groupWidth < 0 ) groupWidth = 0; if ( groupWidth * rowCount > width ) groupWidth = width / rowCount; } // maxLimit: allow the space between bars to be larger until area.width() // is covered by the groups. double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) ); //Pending Michel: FixMe if ( ba.useFixedDataValueGap() ) { if ( width > maxLimit ) spaceBetweenBars += ba.fixedDataValueGap(); else spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1); } if ( ba.useFixedValueBlockGap() ) { spaceBetweenGroups += ba.fixedValueBlockGap(); } calculateValueAndGapWidths( rowCount, colCount,groupWidth, barWidth, spaceBetweenBars, spaceBetweenGroups ); DataValueTextInfoList list; for( int row = rowCount - 1; row >= 0; --row ) { double offset = (groupWidth + spaceBetweenGroups) / 2.0 - spaceBetweenBars; if ( ba.useFixedDataValueGap() ) { if ( spaceBetweenBars > 0 ) { if ( width > maxLimit ) offset -= ba.fixedDataValueGap(); else offset -= ((width/rowCount) - groupWidth)/(colCount-1); } else { offset += barWidth/2; } } for( int column = colCount - 1; column >= 0; --column ) { offset -= barWidth + spaceBetweenBars; // paint one group const CartesianDiagramDataCompressor::CachePosition position( row, column ); const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position ); const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index ); const qreal value = point.value;//attributesModel()->data( sourceIndex ).toDouble(); QPointF topPoint = ctx->coordinatePlane()->translate( QPointF( value, rowCount - (point.key + 0.5) ) ); QPointF bottomPoint = ctx->coordinatePlane()->translate( QPointF( 0, rowCount - point.key ) ); const double barHeight = topPoint.x() - bottomPoint.x(); topPoint.ry() += offset; topPoint.rx() -= barHeight; const QRectF rect( topPoint, QSizeF( barHeight, barWidth ) ); appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ), Position::NorthEast, Position::SouthWest, point.value ); paintBars( ctx, sourceIndex, rect, maxDepth ); } } paintDataValueTextsAndMarkers( diagram(), ctx, list, false ); }
void StackedLyingBarDiagram::paint( PaintContext* ctx ) { reverseMapper().clear(); const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ; const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second ); const int rowCount = compressor().modelDataRows(); const int colCount = compressor().modelDataColumns(); BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) ); double barWidth = 0; double maxDepth = 0; double width = boundLeft.y() - boundRight.y(); double groupWidth = width/ (rowCount + 2); double spaceBetweenBars = 0; double spaceBetweenGroups = 0; if ( ba.useFixedBarWidth() ) { barWidth = ba.fixedBarWidth(); groupWidth += barWidth; // Pending Michel set a min and max value for the groupWidth // related to the area.width if ( groupWidth < 0 ) groupWidth = 0; if ( groupWidth * rowCount > width ) groupWidth = width / rowCount; } // maxLimit: allow the space between bars to be larger until area.width() // is covered by the groups. double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) ); //Pending Michel: FixMe if ( ba.useFixedDataValueGap() ) { if ( ctx->rectangle().width() > maxLimit ) spaceBetweenBars += ba.fixedDataValueGap(); else spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1); } if ( ba.useFixedValueBlockGap() ) spaceBetweenGroups += ba.fixedValueBlockGap(); calculateValueAndGapWidths( rowCount, colCount,groupWidth, barWidth, spaceBetweenBars, spaceBetweenGroups ); DataValueTextInfoList list; for( int row = rowCount - 1; row >= 0; --row ) { double offset = spaceBetweenGroups; if( ba.useFixedBarWidth() ) offset -= ba.fixedBarWidth(); if( offset < 0 ) offset = 0; for( int col = 0; col < colCount; ++col ) { double threeDOffset = 0.0; const CartesianDiagramDataCompressor::CachePosition position( row, col ); const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position ); const QModelIndex index = attributesModel()->mapToSource( p.index ); ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index ); const double value = p.value; double stackedValues = 0.0; double key = 0.0; if ( threeDAttrs.isEnabled() ){ if ( barWidth > 0 ) { barWidth = (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount; threeDOffset = threeDAttrs.depth(); } if ( barWidth <= 0 ) { barWidth = 0.1; threeDOffset = (width - (offset*rowCount))/ rowCount; } }else{ barWidth = (width - (offset*rowCount))/ rowCount; } for ( int k = col; k >= 0; --k ) { const CartesianDiagramDataCompressor::CachePosition position( row, k ); const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position ); if( (p.value >= 0.0 && point.value >= 0.0) || (p.value < 0.0 && point.value < 0.0) ) stackedValues += point.value; key = point.key; } QPointF point = ctx->coordinatePlane()->translate( QPointF( stackedValues, rowCount - key ) ); point.ry() += offset / 2 + threeDOffset; const QPointF previousPoint = ctx->coordinatePlane()->translate( QPointF( stackedValues - value, rowCount - key ) ); const double barHeight = point.x() - previousPoint.x(); point.rx() -= barHeight; const QRectF rect( point, QSizeF( barHeight , barWidth ) ); appendDataValueTextInfoToList( diagram(), list, index, PositionPoints( rect ), Position::NorthEast, Position::SouthWest, value ); paintBars( ctx, index, rect, maxDepth ); } } paintDataValueTextsAndMarkers( diagram(), ctx, list, false ); }
void NormalLyingBarDiagram::paint( PaintContext* ctx ) { // FIXME: in all LyingBarDiagram types, the datasets are rendered top to bottom, but the abscissa // (in that case Y axis) ticks are still bottom to top. So tick labels are in reverse order. reverseMapper().clear(); const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ; const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second ); const int rowCount = attributesModel()->rowCount( attributesModelRootIndex() ); const int colCount = attributesModel()->columnCount( attributesModelRootIndex() ); BarAttributes ba = diagram()->barAttributes(); qreal barWidth = 0; qreal maxDepth = 0; qreal width = boundLeft.y() - boundRight.y(); qreal groupWidth = width / rowCount; qreal spaceBetweenBars = 0; qreal spaceBetweenGroups = 0; if ( ba.useFixedBarWidth() ) { barWidth = ba.fixedBarWidth(); groupWidth += barWidth; // Pending Michel set a min and max value for the groupWidth // related to the area.width if ( groupWidth < 0 ) groupWidth = 0; if ( groupWidth * rowCount > width ) groupWidth = width / rowCount; } // maxLimit: allow the space between bars to be larger until area.width() // is covered by the groups. qreal maxLimit = rowCount * ( groupWidth + ( colCount - 1 ) * ba.fixedDataValueGap() ); //Pending Michel: FixMe if ( ba.useFixedDataValueGap() ) { if ( width > maxLimit ) spaceBetweenBars += ba.fixedDataValueGap(); else spaceBetweenBars = ( width / rowCount - groupWidth ) / ( colCount - 1 ); } if ( ba.useFixedValueBlockGap() ) { spaceBetweenGroups += ba.fixedValueBlockGap(); } calculateValueAndGapWidths( rowCount, colCount,groupWidth, barWidth, spaceBetweenBars, spaceBetweenGroups ); LabelPaintCache lpc; for ( int row = 0; row < rowCount; row++ ) { qreal offset = -groupWidth / 2 + spaceBetweenGroups / 2; if ( ba.useFixedDataValueGap() ) { if ( spaceBetweenBars > 0 ) { if ( width > maxLimit ) { offset -= ba.fixedDataValueGap(); } else { offset -= ( width / rowCount - groupWidth ) / ( colCount - 1 ); } } else { offset += barWidth / 2; } } for ( int column = 0; column < colCount; column++ ) { // paint one group const CartesianDiagramDataCompressor::CachePosition position( row, column ); const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position ); const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index ); QPointF dataPoint( 0, rowCount - ( point.key + 0.5 ) ); const QPointF topLeft = ctx->coordinatePlane()->translate( dataPoint ); dataPoint.rx() += point.value; const QPointF bottomRight = ctx->coordinatePlane()->translate( dataPoint ) + QPointF( 0, barWidth ); const QRectF rect = QRectF( topLeft, bottomRight ).translated( 1.0, offset ); m_private->addLabel( &lpc, sourceIndex, 0, PositionPoints( rect ), Position::North, Position::South, point.value ); paintBars( ctx, sourceIndex, rect, maxDepth ); offset += barWidth + spaceBetweenBars; } } m_private->paintDataValueTextsAndMarkers( ctx, lpc, false ); }
void PercentBarDiagram::paint( PaintContext* ctx ) { reverseMapper().clear(); const QPair<QPointF,QPointF> boundaries = diagram()->dataBoundaries(); // cached const QPointF boundLeft = ctx->coordinatePlane()->translate( boundaries.first ) ; const QPointF boundRight = ctx->coordinatePlane()->translate( boundaries.second ); const int rowCount = compressor().modelDataRows(); const int colCount = compressor().modelDataColumns(); BarAttributes ba = diagram()->barAttributes( diagram()->model()->index( 0, 0, diagram()->rootIndex() ) ); double barWidth = 0; double maxDepth = 0; double width = boundRight.x() - boundLeft.x(); double groupWidth = width/ (rowCount + 2); double spaceBetweenBars = 0; double spaceBetweenGroups = 0; if ( ba.useFixedBarWidth() ) { barWidth = ba.fixedBarWidth(); groupWidth += barWidth; // Pending Michel set a min and max value for the groupWidth // related to the area.width if ( groupWidth < 0 ) groupWidth = 0; if ( groupWidth * rowCount > width ) groupWidth = width / rowCount; } // maxLimit: allow the space between bars to be larger until area.width() // is covered by the groups. double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) ); //Pending Michel: FixMe if ( ba.useFixedDataValueGap() ) { if ( width > maxLimit ) spaceBetweenBars += ba.fixedDataValueGap(); else spaceBetweenBars = ((width/rowCount) - groupWidth)/(colCount-1); } if ( ba.useFixedValueBlockGap() ) spaceBetweenGroups += ba.fixedValueBlockGap(); calculateValueAndGapWidths( rowCount, colCount,groupWidth, barWidth, spaceBetweenBars, spaceBetweenGroups ); DataValueTextInfoList list; const double maxValue = 100; // always 100 % double sumValues = 0; QVector <double > sumValuesVector; //calculate sum of values for each column and store for( int row = 0; row < rowCount; ++row ) { for( int col = 0; col < colCount; ++col ) { const CartesianDiagramDataCompressor::CachePosition position( row, col ); const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position ); //if ( point.value > 0 ) sumValues += qMax( point.value, -point.value ); if ( col == colCount - 1 ) { sumValuesVector << sumValues ; sumValues = 0; } } } // calculate stacked percent value for( int col = 0; col < colCount; ++col ) { double offset = spaceBetweenGroups; if( ba.useFixedBarWidth() ) offset -= ba.fixedBarWidth(); if( offset < 0 ) offset = 0; for( int row = 0; row < rowCount ; ++row ) { const CartesianDiagramDataCompressor::CachePosition position( row, col ); const CartesianDiagramDataCompressor::DataPoint p = compressor().data( position ); QModelIndex sourceIndex = attributesModel()->mapToSource( p.index ); ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( sourceIndex ); if ( threeDAttrs.isEnabled() ){ if ( barWidth > 0 ) barWidth = (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount; if ( barWidth <= 0 ) { barWidth = 0; maxDepth = offset - ( width/rowCount); } }else{ barWidth = (width - (offset*rowCount))/ rowCount; } const double value = qMax( p.value, -p.value ); double stackedValues = 0.0; double key = 0.0; // calculate stacked percent value // we only take in account positives values for now. for( int k = col; k >= 0 ; --k ) { const CartesianDiagramDataCompressor::CachePosition position( row, k ); const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position ); stackedValues += qMax( point.value, -point.value ); key = point.key; } QPointF point, previousPoint; if( sumValuesVector.at( row ) != 0 && value > 0 ) { point = ctx->coordinatePlane()->translate( QPointF( key, stackedValues / sumValuesVector.at( row ) * maxValue ) ); point.rx() += offset / 2; previousPoint = ctx->coordinatePlane()->translate( QPointF( key, ( stackedValues - value)/sumValuesVector.at(row)* maxValue ) ); } const double barHeight = previousPoint.y() - point.y(); const QRectF rect( point, QSizeF( barWidth, barHeight ) ); appendDataValueTextInfoToList( diagram(), list, sourceIndex, PositionPoints( rect ), Position::NorthWest, Position::SouthEast, value ); paintBars( ctx, sourceIndex, rect, maxDepth ); } } paintDataValueTextsAndMarkers( diagram(), ctx, list, false ); }