0
0
mirror of https://github.com/fralx/LimeReport.git synced 2025-09-23 08:29:07 +03:00

ChartItem has been refactored

This commit is contained in:
Arin Alexander
2020-01-11 02:11:55 +03:00
parent 03c1e37b94
commit 919173870a
12 changed files with 753 additions and 571 deletions

View File

@@ -0,0 +1,64 @@
#include "lrhorizontalbarchart.h"
namespace LimeReport{
void HorizontalBarChart::paintChart(QPainter *painter, QRectF chartRect)
{
QRectF calcRect = verticalLabelsRect(painter, chartRect.adjusted(
hPadding(chartRect),
vPadding(chartRect) * 2,
-(chartRect.width() * 0.9),
-(vPadding(chartRect) * 2 + valuesVMargin(painter))
));
qreal barsShift = calcRect.width();
paintHorizontalGrid(painter, chartRect.adjusted(
hPadding(chartRect) + barsShift,
vPadding(chartRect),
-(hPadding(chartRect)),-vPadding(chartRect)));
paintHorizontalBars(painter, chartRect.adjusted(
hPadding(chartRect) + barsShift,
vPadding(chartRect) * 2,
-(hPadding(chartRect)),
-(vPadding(chartRect) * 2) ));
paintVerticalLabels(painter, calcRect);
}
void HorizontalBarChart::paintHorizontalBars(QPainter *painter, QRectF barsRect)
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing,false);
int delta = int(maxValue()-minValue());
delta = genNextValue(delta);
qreal vStep = (barsRect.height()-painter->fontMetrics().height()) / valuesCount() / seriesCount();
qreal hStep = (barsRect.width()-painter->fontMetrics().width(QString::number(maxValue()))) / delta;
if (!m_chartItem->series().isEmpty() && (m_chartItem->itemMode() != DesignMode)){
int curSeries = 0;
foreach (SeriesItem* series, m_chartItem->series()) {
qreal curVOffset = curSeries*vStep+barsRect.top();
painter->setBrush(series->color());
foreach (qreal value, series->data()->values()) {
painter->drawRect(QRectF((-minValue()*hStep)+barsRect.left(), curVOffset, value*hStep, vStep));
curVOffset+=vStep*seriesCount();
}
curSeries++;
}
} else {
qreal curVOffset = barsRect.top();
int curColor = 0;
for (int i=0; i<9; ++i){
if (curColor==3) curColor=0;
painter->setBrush(color_map[curColor]);
painter->drawRect(QRectF(barsRect.left(), curVOffset, designValues()[i]*hStep, vStep));
curVOffset+=vStep;
curColor++;
}
}
painter->restore();
}
}

View File

@@ -0,0 +1,17 @@
#ifndef HORIZONTALBARCHART_H
#define HORIZONTALBARCHART_H
#include "lrchartitem.h"
namespace LimeReport{
class HorizontalBarChart: public AbstractBarChart{
public:
HorizontalBarChart(ChartItem* chartItem):AbstractBarChart(chartItem){}
void paintChart(QPainter *painter, QRectF chartRect);
void paintHorizontalBars(QPainter *painter, QRectF barsRect);
};
} // namespace LimeReport
#endif // HORIZONTALBARCHART_H

View File

@@ -0,0 +1,97 @@
#include "lrlineschart.h"
namespace LimeReport {
void LinesChart::paintChart(QPainter *painter, QRectF chartRect)
{
QRectF calcRect = horizontalLabelsRect(
painter,
chartRect.adjusted(
hPadding(chartRect) * 2 + valuesHMargin(painter),
chartRect.height() - (painter->fontMetrics().height() + vPadding(chartRect)*2),
-(hPadding(chartRect) * 2),
-vPadding(chartRect)
)
);
qreal barsShift = calcRect.height();
paintVerticalGrid(
painter,
chartRect.adjusted(
hPadding(chartRect),
vPadding(chartRect) + valuesVMargin(painter),
-hPadding(chartRect),
-(vPadding(chartRect) + barsShift)
)
);
paintSerialLines(
painter,
chartRect.adjusted(
hPadding(chartRect) * 2 + valuesHMargin(painter),
vPadding(chartRect) + valuesVMargin(painter),
-(hPadding(chartRect) * 2),
-(vPadding(chartRect)+barsShift)
)
);
paintHorizontalLabels(painter, calcRect);
}
void LinesChart::drawDesignMode(QPainter* painter, qreal hStep, qreal vStep, qreal topShift, QRectF barsRect){
for (int i = 0; i < valuesCount()-1; ++i){
QPoint startPoint = QPoint((i+1) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - designValues()[i] * vStep
);
QPoint endPoint = QPoint((i+2) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - designValues()[i+1] * vStep
);
drawSegment(painter, startPoint, endPoint, color_map[0]);
startPoint = QPoint((i+1) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - designValues()[i+3] * vStep
);
endPoint = QPoint((i+2) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - designValues()[i+3+1] * vStep
);
drawSegment(painter, startPoint, endPoint, color_map[1]);
startPoint = QPoint((i+1) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - designValues()[i+6] * vStep
);
endPoint = QPoint((i+2) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - designValues()[i+6+1] * vStep
);
drawSegment(painter, startPoint, endPoint, color_map[2]);
}
}
void LinesChart::paintSerialLines(QPainter* painter, QRectF barsRect)
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing,true);
int delta = int(maxValue() - minValue());
delta = genNextValue(delta);
qreal vStep = barsRect.height() / delta;
qreal hStep = barsRect.width() / valuesCount();
qreal topShift = (delta - (maxValue() - minValue())) * vStep +barsRect.top();
if (m_chartItem->itemMode() != DesignMode){
foreach (SeriesItem* series, m_chartItem->series()) {
QPen pen(series->color());
pen.setWidth(4);
painter->setPen(pen);
for (int i = 0; i < series->data()->values().count()-1; ++i ){
QPoint startPoint = QPoint((i+1) * hStep + barsRect.left() - hStep/2,
(maxValue()*vStep+topShift) - series->data()->values().at(i) * vStep);
QPoint endPoint = QPoint((i+2) * hStep + barsRect.left() - hStep/2,
(maxValue() * vStep+topShift) - series->data()->values().at(i+1) * vStep);
drawSegment(painter, startPoint, endPoint, series->color());
}
}
} else {
drawDesignMode(painter, hStep, vStep, topShift, barsRect);
}
painter->restore();
}
} //namespace LimeReport

View File

@@ -0,0 +1,17 @@
#ifndef LINESCHART_H
#define LINESCHART_H
#include "lrchartitem.h"
namespace LimeReport {
class LinesChart: public AbstractBarChart{
public:
LinesChart(ChartItem* chartItem):AbstractBarChart(chartItem){}
void paintChart(QPainter *painter, QRectF chartRect);
private:
void paintSerialLines(QPainter *painter, QRectF barsRect);
void drawDesignMode(QPainter *painter, qreal hStep, qreal vStep, qreal topShift, QRectF barsRect);
};
}
#endif // LINESCHART_H

View File

@@ -0,0 +1,172 @@
#include "lrpiechart.h"
namespace LimeReport{
void PieChart::drawPercent(QPainter *painter, QRectF chartRect, qreal startAngle, qreal angle)
{
painter->save();
QPointF center(chartRect.left()+chartRect.width()/2,chartRect.top()+chartRect.height()/2);
qreal percent = angle/3.6;
#ifdef HAVE_QT4
qreal radAngle = (angle/2+startAngle)*(M_PI/180);
#endif
#ifdef HAVE_QT5
qreal radAngle = qDegreesToRadians(angle/2+startAngle);
#endif
qreal radius = painter->fontMetrics().width("99,9%");
qreal border = chartRect.height()*0.02;
qreal length = (chartRect.height())/2-(radius/2+border);
qreal x,y;
x = length*qCos(radAngle);
y = length*qSin(radAngle);
QPointF endPoint(center.x()+x,center.y()-y);
painter->setPen(Qt::white);
QRectF textRect(endPoint.x()-(radius/2),endPoint.y()-(radius/2),radius,radius);
qreal arcLength = 3.14 * length * angle / 180;
if (arcLength >= radius)
painter->drawText(textRect,Qt::AlignCenter,QString::number(percent,'f',1)+"%");
painter->restore();
}
void PieChart::paintChart(QPainter *painter, QRectF chartRect)
{
painter->save();
QPen pen(Qt::white);
pen.setWidthF(2);
painter->setPen(pen);
QBrush brush(Qt::transparent);
painter->setBrush(brush);
painter->setBackground(QBrush(Qt::NoBrush));
QRectF tmpRect = chartRect;
if (chartRect.height()>chartRect.width()){
tmpRect.setHeight(chartRect.width());
tmpRect.adjust(0,(chartRect.bottom()-tmpRect.bottom())/2,
0,(chartRect.bottom()-tmpRect.bottom())/2);
} else {
tmpRect.setWidth(chartRect.height());
}
chartRect = tmpRect;
painter->drawRect(chartRect);
if (!m_chartItem->series().isEmpty()&&!m_chartItem->series().at(0)->data()->values().isEmpty()){
SeriesItem* si = m_chartItem->series().at(0);
qreal sum = 0;
foreach(qreal value, si->data()->values()){
sum+=value;
}
qreal onePercent = sum / 100;
qreal currentDegree = 0;
for(int i=0; i<si->data()->values().count(); ++i){
qreal value = si->data()->values().at(i);
qreal sectorDegree = (value/onePercent)*3.6;
painter->setBrush(si->data()->colors().at(i));
painter->drawPie(chartRect,currentDegree*16,sectorDegree*16);
drawPercent(painter, chartRect, currentDegree, sectorDegree);
currentDegree += sectorDegree;
}
} else {
painter->setBrush(color_map[0]);
painter->drawPie(chartRect,0,260*16);
drawPercent(painter, chartRect, 0, 260);
painter->setBrush(color_map[1]);
painter->drawPie(chartRect,260*16,40*16);
drawPercent(painter, chartRect, 260, 40);
painter->setBrush(color_map[2]);
painter->drawPie(chartRect,300*16,60*16);
drawPercent(painter, chartRect, 300, 60);
}
pen.setWidthF(1);
pen.setColor(Qt::gray);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
painter->drawEllipse(chartRect);
painter->restore();
}
void PieChart::paintChartLegend(QPainter *painter, QRectF legendRect)
{
prepareLegendToPaint(legendRect, painter);
int indicatorSize = painter->fontMetrics().height()/2;
painter->setRenderHint(QPainter::Antialiasing,false);
if (m_chartItem->drawLegendBorder())
painter->drawRect(legendRect);
painter->setRenderHint(QPainter::Antialiasing,true);
QRectF indicatorsRect = legendRect.adjusted(painter->fontMetrics().height()/2,painter->fontMetrics().height()/2,0,0);
if (!m_chartItem->series().isEmpty() && !m_chartItem->series().at(0)->data()->labels().isEmpty()){
qreal cw = 0;
SeriesItem* si = m_chartItem->series().at(0);
for (int i=0;i<si->data()->labels().count();++i){
QString label = si->data()->labels().at(i);
painter->setPen(Qt::black);
painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label);
painter->setPen(si->data()->colors().at(i));
painter->setBrush(si->data()->colors().at(i));
painter->drawEllipse(
indicatorsRect.adjusted(
0,
cw+indicatorSize/2,
-(indicatorsRect.width()-indicatorSize),
-(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2))
)
);
cw += painter->fontMetrics().height();
}
} else {
qreal cw = 0;
for (int i=0;i<m_designLabels.size();++i){
QString label = m_designLabels.at(i);
painter->setPen(Qt::black);
painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label);
painter->setBrush(color_map[i]);
painter->setPen(color_map[i]);
painter->drawEllipse(
indicatorsRect.adjusted(
0,
cw+indicatorSize/2,
-(indicatorsRect.width()-indicatorSize),
-(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2))
)
);
cw += painter->fontMetrics().height();
}
}
}
QSizeF PieChart::calcChartLegendSize(const QFont &font)
{
QFontMetrics fm(font);
qreal cw = 0;
qreal maxWidth = 0;
if (!m_chartItem->series().isEmpty() && !m_chartItem->series().at(0)->data()->labels().isEmpty()){
SeriesItem* si = m_chartItem->series().at(0);
foreach(QString label, si->data()->labels()){
cw += fm.height();
if (maxWidth<fm.width(label))
maxWidth = fm.width(label)+10;
}
} else {
foreach(QString label, m_designLabels){
cw += fm.height();
if (maxWidth<fm.width(label))
maxWidth = fm.width(label)+10;
}
}
cw += fm.height();
return QSizeF(maxWidth+fm.height()*2,cw);
}
}

View File

@@ -0,0 +1,19 @@
#ifndef PIECHART_H
#define PIECHART_H
#include "lrchartitem.h"
namespace LimeReport{
class PieChart : public AbstractChart{
public:
PieChart(ChartItem* chartItem):AbstractChart(chartItem){}
QSizeF calcChartLegendSize(const QFont &font);
void paintChart(QPainter *painter, QRectF chartRect);
void paintChartLegend(QPainter *painter, QRectF legendRect);
protected:
void drawPercent(QPainter *painter, QRectF chartRect, qreal startAngle, qreal angle);
};
} // namespace LimeReport
#endif // PIECHART_H

View File

@@ -0,0 +1,123 @@
#include "lrverticalbarchart.h"
namespace LimeReport{
void VerticalBarChart::paintChart(QPainter *painter, QRectF chartRect)
{
QRectF calcRect = horizontalLabelsRect(
painter,
chartRect.adjusted(
hPadding(chartRect) * 2 + valuesHMargin(painter),
chartRect.height() - (painter->fontMetrics().height() + vPadding(chartRect) * 2),
-(hPadding(chartRect) * 2),
-vPadding(chartRect)
)
);
qreal barsShift = calcRect.height();
paintVerticalGrid(
painter,
chartRect.adjusted(
hPadding(chartRect),
vPadding(chartRect) + valuesVMargin(painter),
-hPadding(chartRect),
-(vPadding(chartRect) + barsShift)
)
);
paintVerticalBars(
painter,
chartRect.adjusted(
hPadding(chartRect) * 2 + valuesHMargin(painter),
vPadding(chartRect) + valuesVMargin(painter),
-hPadding(chartRect) * 2,
-(vPadding(chartRect) + barsShift)
)
);
paintSerialLines(
painter,
chartRect.adjusted(
hPadding(chartRect) * 2 + valuesHMargin(painter),
vPadding(chartRect) + valuesVMargin(painter),
-hPadding(chartRect) * 2,
-(vPadding(chartRect) + barsShift)
)
);
paintHorizontalLabels(painter, calcRect);
}
void VerticalBarChart::paintVerticalBars(QPainter *painter, QRectF barsRect)
{
int delta = int(maxValue() - minValue());
delta = genNextValue(delta);
int barSeriesCount = 0;
foreach(SeriesItem* series, m_chartItem->series()){
if (series->preferredType() == SeriesItem::Bar) barSeriesCount++;
}
barSeriesCount = (m_chartItem->itemMode() == DesignMode) ? seriesCount() : barSeriesCount;
if (barSeriesCount < 1) return;
painter->save();
painter->setRenderHint(QPainter::Antialiasing,false);
qreal vStep = barsRect.height() / delta;
qreal hStep = (barsRect.width() / valuesCount()) / (barSeriesCount == 0 ? 1 : barSeriesCount);
qreal topShift = (delta - (maxValue() - minValue())) * vStep + barsRect.top();
if (!m_chartItem->series().isEmpty() && (m_chartItem->itemMode() != DesignMode)){
int curSeries = 0;
foreach (SeriesItem* series, m_chartItem->series()) {
if (series->preferredType() == SeriesItem::Bar){
qreal curHOffset = curSeries * hStep + barsRect.left();
painter->setBrush(series->color());
foreach (qreal value, series->data()->values()) {
painter->drawRect(QRectF(curHOffset, maxValue() * vStep + topShift, hStep, -value * vStep));
curHOffset += hStep * barSeriesCount;
}
curSeries++;
}
}
} else {
qreal curHOffset = barsRect.left();
int curColor = 0;
for (int i = 0; i < 9; ++i){
if (curColor == 3) curColor = 0;
painter->setBrush(color_map[curColor]);
painter->drawRect(QRectF(curHOffset, maxValue() * vStep + barsRect.top(), hStep, -designValues()[i] * vStep));
curHOffset += hStep;
curColor++;
}
}
painter->restore();
}
void VerticalBarChart::paintSerialLines(QPainter* painter, QRectF barsRect)
{
painter->save();
painter->setRenderHint(QPainter::Antialiasing,true);
int delta = int(maxValue() - minValue());
delta = genNextValue(delta);
qreal vStep = barsRect.height() / delta;
qreal hStep = (barsRect.width() / valuesCount());
qreal topShift = (delta - (maxValue()-minValue())) * vStep + barsRect.top();
if (!m_chartItem->series().isEmpty()){
foreach (SeriesItem* series, m_chartItem->series()) {
if (series->preferredType() == SeriesItem::Line){
for (int i = 0; i < series->data()->values().count()-1; ++i ){
QPoint startPoint = QPoint((i+1)*hStep + barsRect.left()-hStep/2,
(maxValue() * vStep+topShift) - series->data()->values().at(i) * vStep
);
QPoint endPoint = QPoint((i+2)*hStep + barsRect.left()-hStep/2,
(maxValue() * vStep+topShift) - series->data()->values().at(i+1) * vStep
);
drawSegment(painter, startPoint, endPoint, series->color());
}
}
}
}
painter->restore();
}
} // namespace LimeReport

View File

@@ -0,0 +1,19 @@
#ifndef VERTICALBARCHART_H
#define VERTICALBARCHART_H
#include "lrchartitem.h"
namespace LimeReport{
class VerticalBarChart: public AbstractBarChart{
public:
VerticalBarChart(ChartItem* chartItem):AbstractBarChart(chartItem){}
void paintChart(QPainter *painter, QRectF chartRect);
// void paintVerticalGrid(QPainter *painter, QRectF gridRect);
void paintVerticalBars(QPainter *painter, QRectF barsRect);
void paintSerialLines(QPainter *painter, QRectF barsRect);
};
} //namespace LimeReport
#endif // VERTICALBARCHART_H