From 919173870a88066e6160e619ebb0cfe283e0c515 Mon Sep 17 00:00:00 2001 From: Arin Alexander Date: Sat, 11 Jan 2020 02:11:55 +0300 Subject: [PATCH] ChartItem has been refactored --- common.pri | 2 +- .../items/charts/lrhorizontalbarchart.cpp | 64 ++ .../items/charts/lrhorizontalbarchart.h | 17 + limereport/items/charts/lrlineschart.cpp | 97 +++ limereport/items/charts/lrlineschart.h | 17 + limereport/items/charts/lrpiechart.cpp | 172 +++++ limereport/items/charts/lrpiechart.h | 19 + .../items/charts/lrverticalbarchart.cpp | 123 +++ limereport/items/charts/lrverticalbarchart.h | 19 + limereport/items/lrchartitem.cpp | 717 +++++------------- limereport/items/lrchartitem.h | 56 +- limereport/limereport.pri | 21 +- 12 files changed, 753 insertions(+), 571 deletions(-) create mode 100644 limereport/items/charts/lrhorizontalbarchart.cpp create mode 100644 limereport/items/charts/lrhorizontalbarchart.h create mode 100644 limereport/items/charts/lrlineschart.cpp create mode 100644 limereport/items/charts/lrlineschart.h create mode 100644 limereport/items/charts/lrpiechart.cpp create mode 100644 limereport/items/charts/lrpiechart.h create mode 100644 limereport/items/charts/lrverticalbarchart.cpp create mode 100644 limereport/items/charts/lrverticalbarchart.h diff --git a/common.pri b/common.pri index 17f5c7c..84e603c 100644 --- a/common.pri +++ b/common.pri @@ -127,7 +127,7 @@ RCC_DIR = $${ARCH_DIR}/$${BUILD_TYPE}/rcc LIMEREPORT_VERSION_MAJOR = 1 LIMEREPORT_VERSION_MINOR = 5 -LIMEREPORT_VERSION_RELEASE = 28 +LIMEREPORT_VERSION_RELEASE = 29 LIMEREPORT_VERSION = '$${LIMEREPORT_VERSION_MAJOR}.$${LIMEREPORT_VERSION_MINOR}.$${LIMEREPORT_VERSION_RELEASE}' DEFINES *= LIMEREPORT_VERSION_STR=\\\"$${LIMEREPORT_VERSION}\\\" diff --git a/limereport/items/charts/lrhorizontalbarchart.cpp b/limereport/items/charts/lrhorizontalbarchart.cpp new file mode 100644 index 0000000..e2713dd --- /dev/null +++ b/limereport/items/charts/lrhorizontalbarchart.cpp @@ -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(); +} + +} diff --git a/limereport/items/charts/lrhorizontalbarchart.h b/limereport/items/charts/lrhorizontalbarchart.h new file mode 100644 index 0000000..af478dc --- /dev/null +++ b/limereport/items/charts/lrhorizontalbarchart.h @@ -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 diff --git a/limereport/items/charts/lrlineschart.cpp b/limereport/items/charts/lrlineschart.cpp new file mode 100644 index 0000000..30f2949 --- /dev/null +++ b/limereport/items/charts/lrlineschart.cpp @@ -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 + diff --git a/limereport/items/charts/lrlineschart.h b/limereport/items/charts/lrlineschart.h new file mode 100644 index 0000000..6e10cf4 --- /dev/null +++ b/limereport/items/charts/lrlineschart.h @@ -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 diff --git a/limereport/items/charts/lrpiechart.cpp b/limereport/items/charts/lrpiechart.cpp new file mode 100644 index 0000000..f54e62d --- /dev/null +++ b/limereport/items/charts/lrpiechart.cpp @@ -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; idata()->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;idata()->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;isetPen(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 (maxWidthfontMetrics().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 diff --git a/limereport/items/charts/lrverticalbarchart.h b/limereport/items/charts/lrverticalbarchart.h new file mode 100644 index 0000000..9cfe8f8 --- /dev/null +++ b/limereport/items/charts/lrverticalbarchart.h @@ -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 diff --git a/limereport/items/lrchartitem.cpp b/limereport/items/lrchartitem.cpp index abeb2e4..b80e700 100644 --- a/limereport/items/lrchartitem.cpp +++ b/limereport/items/lrchartitem.cpp @@ -9,6 +9,11 @@ #include "lrreportengine_p.h" #include "lrdatadesignintf.h" +#include "charts/lrpiechart.h" +#include "charts/lrverticalbarchart.h" +#include "charts/lrhorizontalbarchart.h" +#include "charts/lrlineschart.h" + namespace{ const QString xmlTag = "ChartItem"; @@ -32,15 +37,15 @@ QColor generateColor() } QColor color_map[39] = { - QColor(51,102,204), QColor(220,57,18), QColor(225, 153, 0), QColor(16, 150, 24), QColor(153,0,153), - QColor(0,153,198), QColor(221, 68, 119), - QColor(255,0,0), QColor(0,0,139), QColor(0,205,0), QColor(233,30,99), QColor(255,255,0), QColor(244,67,54), - QColor(156,39,176), QColor(103,58,183), QColor(63,81,181), QColor(33,153,243), - QColor(0,150,136), QColor(78,175,80), QColor(139,195,74), QColor(205,228,57), - QColor(0,139,0), QColor(0,0,255), QColor(255,235,59), QColor(255,193,7), - QColor(255,152,0), QColor(255,87,34), QColor(121,85,72), QColor(158,158,158), - QColor(96,125,139), QColor(241,153,185), QColor(64,64,64), - QColor(188,229,218), QColor(139,0,0), QColor(139,139,0), QColor(171, 130, 255), + QColor(51,102,204), QColor(220,57,18), QColor(225, 153, 0), QColor(16, 150, 24), + QColor(153,0,153), QColor(0,153,198), QColor(221, 68, 119), QColor(255,0,0), + QColor(0,0,139), QColor(0,205,0), QColor(233,30,99), QColor(255,255,0), + QColor(244,67,54), QColor(156,39,176), QColor(103,58,183), QColor(63,81,181), + QColor(33,153,243), QColor(0,150,136), QColor(78,175,80), QColor(139,195,74), + QColor(205,228,57), QColor(0,139,0), QColor(0,0,255), QColor(255,235,59), + QColor(255,193,7), QColor(255,152,0), QColor(255,87,34), QColor(121,85,72), + QColor(158,158,158), QColor(96,125,139), QColor(241,153,185), QColor(64,64,64), + QColor(188,229,218), QColor(139,0,0), QColor(139,139,0), QColor(171, 130, 255), QColor(139, 123, 139), QColor(255, 0, 255), QColor(139, 69, 19) }; @@ -297,6 +302,8 @@ void ChartItem::setChartType(const ChartType &chartType) case HorizontalBar: m_chart = new HorizontalBarChart(this); break; + case Lines: + m_chart = new LinesChart(this); } notify("chartType",oldValue,m_chartType); update(); @@ -462,378 +469,14 @@ void AbstractChart::prepareLegendToPaint(QRectF &legendRect, QPainter *painter) } } -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; idata()->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;idata()->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;isetPen(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 (maxWidthfontMetrics().width(QString::number(delta))+4; -} - -qreal VerticalBarChart::valuesVMargin(QPainter *painter) -{ - return painter->fontMetrics().height(); -} - -QRectF VerticalBarChart::labelsRect(QPainter *painter, QRectF labelsRect) -{ - qreal maxWidth = 0; - - foreach (QString label, m_chartItem->labels()) { - if (painter->fontMetrics().width(label)>maxWidth) - maxWidth = painter->fontMetrics().width(label); - } - - if (maxWidth+vPadding(m_chartItem->rect())> labelsRect.height()) - return labelsRect; - else - return labelsRect.adjusted(0,(labelsRect.height()-(maxWidth+vPadding(m_chartItem->rect()))),0,0); -} - -void VerticalBarChart::paintChart(QPainter *painter, QRectF chartRect) -{ - QRectF calcRect = labelsRect(painter, chartRect.adjusted( - hPadding(chartRect)*2+valuesHMargin(painter), - chartRect.height()*0.5, - -(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) )); - paintLabels(painter,calcRect); -} - - -void VerticalBarChart::paintVerticalGrid(QPainter *painter, QRectF gridRect) -{ - int delta = int(maxValue()-minValue()); - delta = genNextValue(delta); - - painter->setRenderHint(QPainter::Antialiasing,false); - qreal vStep = gridRect.height() / 4; - - for (int i=0;i<5;i++){ - painter->drawText(QRectF(gridRect.bottomLeft()-QPointF(0,vStep*i+painter->fontMetrics().height()), - QSizeF(valuesHMargin(painter),painter->fontMetrics().height())), - QString::number(minValue()+i*delta/4)); - painter->drawLine(gridRect.bottomLeft()-QPointF(-valuesHMargin(painter),vStep*i), - gridRect.bottomRight()-QPointF(0,vStep*i)); - } - - painter->setRenderHint(QPainter::Antialiasing,true); -} - - - -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->series().at(0)->data()->labels().isEmpty()){ - 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){ - 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 - ); - painter->drawLine(startPoint, endPoint); - QRect startPointRect(startPoint,startPoint); - QRect endPointRect(endPoint,endPoint); - int radius = 4; - painter->setBrush(series->color()); - painter->drawEllipse(startPointRect.adjusted(radius,radius,-radius,-radius)); - painter->drawEllipse(endPointRect.adjusted(radius,radius,-radius,-radius)); - - } - } - } - } - painter->restore(); -} - -void VerticalBarChart::paintLabels(QPainter *painter, QRectF labelsRect) -{ - painter->save(); - qreal hStep = (labelsRect.width() / valuesCount()); - bool rotateLabels = false; - QFontMetrics fm = painter->fontMetrics(); - foreach(QString label, m_chartItem->labels()){ - if (fm.width(label) > hStep){ - rotateLabels = true; - break; - } - } - if (!m_chartItem->labels().isEmpty()){ - if (rotateLabels){ - painter->rotate(270); - painter->translate( -(labelsRect.top()+labelsRect.height()), labelsRect.left() ); - foreach (QString label, m_chartItem->labels()) { - painter->drawText(QRectF(QPoint(0,0), - QSize(labelsRect.height()-4, hStep)), Qt::AlignVCenter | Qt::AlignRight, label); - painter->translate(0,hStep); - } - painter->rotate(-270); - } else { - painter->translate( labelsRect.left(), labelsRect.top() ); - foreach (QString label, m_chartItem->labels()) { - painter->drawText(QRectF(QPoint(0, 4), - QSize(hStep, labelsRect.height()-4)), Qt::AlignHCenter | Qt::AlignTop, label); - painter->translate(hStep, 0); - } - } - } - painter->restore(); -} - AbstractSeriesChart::AbstractSeriesChart(ChartItem *chartItem) :AbstractChart(chartItem) { @@ -850,7 +493,7 @@ AbstractSeriesChart::AbstractSeriesChart(ChartItem *chartItem) qreal AbstractSeriesChart::maxValue() { - if (m_chartItem->itemMode()==DesignMode) return 40; + if (m_chartItem->itemMode() == DesignMode) return 40; qreal maxValue = 0; foreach(SeriesItem* series, m_chartItem->series()){ foreach(qreal value, series->data()->values()){ @@ -862,7 +505,7 @@ qreal AbstractSeriesChart::maxValue() qreal AbstractSeriesChart::minValue() { - if (m_chartItem->itemMode()==DesignMode) return 0; + if (m_chartItem->itemMode() == DesignMode) return 0; qreal minValue = 0; foreach(SeriesItem* series, m_chartItem->series()){ foreach(qreal value, series->data()->values()){ @@ -872,15 +515,25 @@ qreal AbstractSeriesChart::minValue() return minValue; } +qreal AbstractSeriesChart::hPadding(QRectF chartRect) +{ + return (chartRect.width() * 0.02); +} + +qreal AbstractSeriesChart::vPadding(QRectF chartRect) +{ + return (chartRect.height() * 0.02); +} + int AbstractSeriesChart::valuesCount() { - if (m_chartItem->itemMode()==DesignMode) return 3; - return (m_chartItem->series().isEmpty())?(0):(m_chartItem->series().at(0)->data()->values().count()); + if (m_chartItem->itemMode() == DesignMode) return 3; + return (m_chartItem->series().isEmpty()) ? 0 : m_chartItem->series().at(0)->data()->values().count(); } int AbstractSeriesChart::seriesCount() { - if (m_chartItem->itemMode()==DesignMode) return 3; + if (m_chartItem->itemMode() == DesignMode) return 3; return m_chartItem->series().count(); } @@ -908,154 +561,48 @@ QSizeF AbstractSeriesChart::calcChartLegendSize(const QFont &font) return QSizeF(maxWidth+fm.height()*2,cw); } -qreal HorizontalBarChart::valuesHMargin(QPainter *painter) -{ - int delta = int(maxValue()-minValue()); - delta = genNextValue(delta); - return painter->fontMetrics().width(QString::number(delta))+4; -} - -qreal HorizontalBarChart::valuesVMargin(QPainter *painter) -{ - return painter->fontMetrics().height(); -} - -void HorizontalBarChart::paintChart(QPainter *painter, QRectF chartRect) -{ - QRectF calcRect = labelsRect(painter, chartRect.adjusted( - hPadding(chartRect), - vPadding(chartRect)*2, - -(chartRect.width()*0.5), - -(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) )); - - paintLabels(painter,calcRect); -} - -void HorizontalBarChart::paintHorizontalGrid(QPainter *painter, QRectF gridRect) -{ - painter->save(); - int delta = int(maxValue()-minValue()); - delta = genNextValue(delta); - - painter->setRenderHint(QPainter::Antialiasing,false); - qreal hStep = (gridRect.width()-painter->fontMetrics().width(QString::number(maxValue()))) / 4; - - painter->setFont(adaptValuesFont(hStep-4,painter->font())); - - for (int i=0;i<5;i++){ - painter->drawText(QRectF(gridRect.left()+4+hStep*i,gridRect.bottom()-painter->fontMetrics().height(), - hStep,painter->fontMetrics().height()), - QString::number(minValue()+i*delta/4)); - painter->drawLine( gridRect.left()+hStep*i, gridRect.bottom(), - gridRect.left()+hStep*i, gridRect.top()); - - } - painter->restore(); -} - -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->series().at(0)->data()->labels().isEmpty()){ - 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(); -} - -QRectF HorizontalBarChart::labelsRect(QPainter *painter, QRectF labelsRect) -{ - qreal maxWidth = 0; - - foreach (QString label, m_chartItem->labels()) { - if (painter->fontMetrics().width(label)>maxWidth) - maxWidth = painter->fontMetrics().width(label); - } - - if (maxWidth+hPadding(m_chartItem->rect())*2> labelsRect.width()) - return labelsRect; - else - return labelsRect.adjusted(0,0,-(labelsRect.width()-(maxWidth+hPadding(m_chartItem->rect())*2)),0); -} - -QFont HorizontalBarChart::adaptLabelsFont(QRectF rect, QFont font) -{ - QString maxWord; - QFontMetrics fm(font); - +bool AbstractSeriesChart::verticalLabels(QPainter* painter, QRectF labelsRect){ + qreal hStep = (labelsRect.width() / valuesCount()); + QFontMetrics fm = painter->fontMetrics(); foreach(QString label, m_chartItem->labels()){ - foreach (QString currentWord, label.split(QRegExp("\\W+"))){ - if (fm.width(maxWord) hStep){ + return true; } } - - qreal curWidth = fm.width(maxWord); - QFont tmpFont = font; - while (curWidth>rect.width() && tmpFont.pixelSize()>1){ - tmpFont.setPixelSize(tmpFont.pixelSize()-1); - QFontMetricsF tmpFM(tmpFont); - curWidth = tmpFM.width(maxWord); - } - return tmpFont; + return false; } -QFont HorizontalBarChart::adaptValuesFont(qreal width, QFont font) -{ - QString strValue = QString::number(maxValue()); - QFont tmpFont = font; - QScopedPointer fm(new QFontMetricsF(tmpFont)); - qreal curWidth = fm->width(strValue); - while (curWidth>width && tmpFont.pixelSize()>1){ - tmpFont.setPixelSize(tmpFont.pixelSize()-1); - fm.reset(new QFontMetricsF(tmpFont)); - curWidth = fm->width(strValue); - } - return tmpFont; -} - -void HorizontalBarChart::paintLabels(QPainter *painter, QRectF labelsRect) +void AbstractSeriesChart::paintHorizontalLabels(QPainter *painter, QRectF labelsRect) { painter->save(); - painter->setFont(adaptLabelsFont(labelsRect.adjusted(0,0,-hPadding(m_chartItem->rect()),0), - painter->font())); + qreal hStep = (labelsRect.width() / valuesCount()); + if (!m_chartItem->labels().isEmpty()){ + if (verticalLabels(painter, labelsRect)){ + painter->rotate(270); + painter->translate( -(labelsRect.top()+labelsRect.height()), labelsRect.left() ); + foreach (QString label, m_chartItem->labels()) { + painter->drawText(QRectF(QPoint(0,0), + QSize(labelsRect.height()-4, hStep)), Qt::AlignVCenter | Qt::AlignRight, label); + painter->translate(0,hStep); + } + painter->rotate(-270); + } else { + painter->translate( labelsRect.left(), labelsRect.top() ); + foreach (QString label, m_chartItem->labels()) { + painter->drawText(QRectF(QPoint(0, 4), + QSize(hStep, labelsRect.height()-4)), Qt::AlignHCenter | Qt::AlignTop, label); + painter->translate(hStep, 0); + } + } + } + painter->restore(); +} + +void AbstractSeriesChart::paintVerticalLabels(QPainter *painter, QRectF labelsRect) +{ + painter->save(); + painter->setFont(adaptLabelsFont(labelsRect.adjusted(0, 0, -hPadding(m_chartItem->rect()), 0), + painter->font())); qreal vStep = (labelsRect.height() / valuesCount()); int curLabel = 0; @@ -1072,14 +619,106 @@ void HorizontalBarChart::paintLabels(QPainter *painter, QRectF labelsRect) painter->restore(); } -qreal AbstractBarChart::hPadding(QRectF chartRect) +void AbstractSeriesChart::paintHorizontalGrid(QPainter *painter, QRectF gridRect) { - return (chartRect.width()*0.02); + painter->save(); + int delta = int(maxValue() - minValue()); + delta = genNextValue(delta); + + painter->setRenderHint(QPainter::Antialiasing,false); + qreal hStep = (gridRect.width() - painter->fontMetrics().width(QString::number(maxValue()))) / 4; + + painter->setFont(adaptValuesFont(hStep-4, painter->font())); + + for (int i=0;i<5;i++){ + painter->drawText(QRectF(gridRect.left() + 4 + hStep * i, gridRect.bottom() - painter->fontMetrics().height(), + hStep, painter->fontMetrics().height()), + QString::number(minValue() + i * delta / 4)); + painter->drawLine( gridRect.left()+hStep*i, gridRect.bottom(), + gridRect.left()+hStep*i, gridRect.top()); + + } + painter->restore(); } -qreal AbstractBarChart::vPadding(QRectF chartRect) +void AbstractSeriesChart::paintVerticalGrid(QPainter *painter, QRectF gridRect) { - return (chartRect.height()*0.02); + int delta = int(maxValue()-minValue()); + delta = genNextValue(delta); + + painter->setRenderHint(QPainter::Antialiasing,false); + qreal vStep = gridRect.height() / 4; + + for (int i=0;i<5;i++){ + painter->drawText(QRectF(gridRect.bottomLeft()-QPointF(0,vStep*i+painter->fontMetrics().height()), + QSizeF(valuesHMargin(painter),painter->fontMetrics().height())), + QString::number(minValue()+i*delta/4)); + painter->drawLine(gridRect.bottomLeft()-QPointF(-valuesHMargin(painter),vStep*i), + gridRect.bottomRight()-QPointF(0,vStep*i)); + } + + painter->setRenderHint(QPainter::Antialiasing,true); +} + +void AbstractSeriesChart::drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color) +{ + int radius = 4; + QPen pen(color); + pen.setWidth(radius); + painter->setPen(pen); + painter->drawLine(startPoint, endPoint); + QRect startPointRect(startPoint,startPoint); + QRect endPointRect(endPoint,endPoint); + painter->setBrush(color); + painter->drawEllipse(startPointRect.adjusted(radius,radius,-radius,-radius)); + painter->drawEllipse(endPointRect.adjusted(radius,radius,-radius,-radius)); +} + +qreal AbstractSeriesChart::valuesHMargin(QPainter *painter) +{ + int delta = int(maxValue()-minValue()); + delta = genNextValue(delta); + return painter->fontMetrics().width(QString::number(delta))+4; +} + +qreal AbstractSeriesChart::valuesVMargin(QPainter *painter) +{ + return painter->fontMetrics().height(); +} + +QFont AbstractSeriesChart::adaptLabelsFont(QRectF rect, QFont font) +{ + QString maxWord; + QFontMetrics fm(font); + + foreach(QString label, m_chartItem->labels()){ + foreach (QString currentWord, label.split(QRegExp("\\W+"))){ + if (fm.width(maxWord) < fm.width(currentWord)) maxWord = currentWord; + } + } + + qreal curWidth = fm.width(maxWord); + QFont tmpFont = font; + while (curWidth>rect.width() && tmpFont.pixelSize() > 1){ + tmpFont.setPixelSize(tmpFont.pixelSize() - 1); + QFontMetricsF tmpFM(tmpFont); + curWidth = tmpFM.width(maxWord); + } + return tmpFont; +} + +QFont AbstractSeriesChart::adaptValuesFont(qreal width, QFont font) +{ + QString strValue = QString::number(maxValue()); + QFont tmpFont = font; + QScopedPointer fm(new QFontMetricsF(tmpFont)); + qreal curWidth = fm->width(strValue); + while (curWidth > width && tmpFont.pixelSize() > 1){ + tmpFont.setPixelSize(tmpFont.pixelSize() - 1); + fm.reset(new QFontMetricsF(tmpFont)); + curWidth = fm->width(strValue); + } + return tmpFont; } void AbstractBarChart::paintChartLegend(QPainter *painter, QRectF legendRect) @@ -1129,4 +768,34 @@ void AbstractBarChart::paintChartLegend(QPainter *painter, QRectF legendRect) } } +QRectF AbstractBarChart::verticalLabelsRect(QPainter *painter, QRectF labelsRect) +{ + qreal maxWidth = 0; + + foreach (QString label, m_chartItem->labels()) { + if (painter->fontMetrics().width(label)>maxWidth) + maxWidth = painter->fontMetrics().width(label); + } + + if (maxWidth + hPadding(m_chartItem->rect()) * 2 < labelsRect.width()) + return labelsRect; + else + return labelsRect.adjusted(0, 0, -(labelsRect.width() - (maxWidth + hPadding(m_chartItem->rect()) * 2)), 0); +} + +QRectF AbstractBarChart::horizontalLabelsRect(QPainter *painter, QRectF labelsRect) +{ + qreal maxWidth = 0; + + foreach (QString label, m_chartItem->labels()) { + if (painter->fontMetrics().width(label)>maxWidth) + maxWidth = painter->fontMetrics().width(label); + } + + if ((maxWidth + vPadding(m_chartItem->rect()) < labelsRect.height()) || !verticalLabels(painter, labelsRect)) + return labelsRect; + else + return labelsRect.adjusted(0, (labelsRect.height() - maxWidth), 0, 0); +} + } // namespace LimeReport diff --git a/limereport/items/lrchartitem.h b/limereport/items/lrchartitem.h index ee38f6b..bd1ca40 100644 --- a/limereport/items/lrchartitem.h +++ b/limereport/items/lrchartitem.h @@ -81,56 +81,34 @@ protected: qreal minValue(); int valuesCount(); int seriesCount(); + bool verticalLabels(QPainter* painter, QRectF labelsRect); QSizeF calcChartLegendSize(const QFont &font); qreal* designValues(){ return m_designValues;} + virtual qreal hPadding(QRectF chartRect); + virtual qreal vPadding(QRectF chartRect); + virtual void paintHorizontalLabels(QPainter *painter, QRectF labelsRect); + virtual void paintVerticalLabels(QPainter *painter, QRectF labelsRect); + virtual void paintHorizontalGrid(QPainter *painter, QRectF gridRect); + virtual void paintVerticalGrid(QPainter *painter, QRectF gridRect); + virtual void drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color); + virtual qreal valuesHMargin(QPainter *painter); + virtual qreal valuesVMargin(QPainter *painter); + virtual QFont adaptLabelsFont(QRectF rect, QFont font); + virtual QFont adaptValuesFont(qreal width, QFont font); + private: qreal m_designValues [9]; }; -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); -}; +int genNextValue(int value); class AbstractBarChart: public AbstractSeriesChart{ public: AbstractBarChart(ChartItem* chartItem):AbstractSeriesChart(chartItem){} - qreal hPadding(QRectF chartRect); - qreal vPadding(QRectF chartRect); void paintChartLegend(QPainter *painter, QRectF legendRect); -}; - -class HorizontalBarChart: public AbstractBarChart{ -public: - HorizontalBarChart(ChartItem* chartItem):AbstractBarChart(chartItem){} - qreal valuesHMargin(QPainter *painter); - qreal valuesVMargin(QPainter *painter); - void paintChart(QPainter *painter, QRectF chartRect); - void paintHorizontalGrid(QPainter *painter, QRectF gridRect); - void paintHorizontalBars(QPainter *painter, QRectF barsRect); - QRectF labelsRect(QPainter* painter, QRectF labelsRect); - void paintLabels(QPainter *painter, QRectF labelsRect); protected: - QFont adaptLabelsFont(QRectF rect, QFont font); - QFont adaptValuesFont(qreal width, QFont font); -}; - -class VerticalBarChart: public AbstractBarChart{ -public: - VerticalBarChart(ChartItem* chartItem):AbstractBarChart(chartItem){} - qreal valuesHMargin(QPainter *painter); - qreal valuesVMargin(QPainter *painter); - QRectF labelsRect(QPainter* painter, QRectF labelsRect); - void paintChart(QPainter *painter, QRectF chartRect); - void paintVerticalGrid(QPainter *painter, QRectF gridRect); - void paintVerticalBars(QPainter *painter, QRectF barsRect); - void paintSerialLines(QPainter *painter, QRectF barsRect); - void paintLabels(QPainter *painter, QRectF labelsRect); + QRectF verticalLabelsRect(QPainter* painter, QRectF horizontalLabelsRect); + virtual QRectF horizontalLabelsRect(QPainter* painter, QRectF horizontalLabelsRect); }; class ChartItem : public LimeReport::ItemDesignIntf @@ -152,7 +130,7 @@ public: enum LegendAlign{LegendAlignTop,LegendAlignCenter,LegendAlignBottom}; enum TitleAlign{TitleAlignLeft, TitleAlignCenter, TitleAlignRight}; - enum ChartType{Pie, VerticalBar, HorizontalBar}; + enum ChartType{Pie, VerticalBar, HorizontalBar, Lines}; ChartItem(QObject* owner, QGraphicsItem* parent); ~ChartItem(); diff --git a/limereport/limereport.pri b/limereport/limereport.pri index 0918890..219dbb4 100644 --- a/limereport/limereport.pri +++ b/limereport/limereport.pri @@ -43,6 +43,12 @@ SOURCES += \ $$REPORT_PATH/items/lrverticallayout.cpp \ $$REPORT_PATH/items/lrlayoutmarker.cpp \ $$REPORT_PATH/items/lrabstractlayout.cpp \ + $$REPORT_PATH/items/lrchartitem.cpp \ + $$REPORT_PATH/items/lrchartitemeditor.cpp \ + $$REPORT_PATH/items/charts/lrhorizontalbarchart.cpp \ + $$REPORT_PATH/items/charts/lrlineschart.cpp \ + $$REPORT_PATH/items/charts/lrpiechart.cpp \ + $$REPORT_PATH/items/charts/lrverticalbarchart.cpp \ $$REPORT_PATH/lrbanddesignintf.cpp \ $$REPORT_PATH/lrpageitemdesignintf.cpp \ $$REPORT_PATH/lrpagedesignintf.cpp \ @@ -65,8 +71,6 @@ SOURCES += \ $$REPORT_PATH/lrsettingdialog.cpp \ $$REPORT_PATH/lritemscontainerdesignitf.cpp \ $$REPORT_PATH/lrcolorindicator.cpp \ - $$REPORT_PATH/items/lrchartitem.cpp \ - $$REPORT_PATH/items/lrchartitemeditor.cpp \ $$REPORT_PATH/lrreporttranslation.cpp \ $$REPORT_PATH/exporters/lrpdfexporter.cpp \ $$REPORT_PATH/lrpreparedpages.cpp @@ -104,6 +108,8 @@ HEADERS += \ $$REPORT_PATH/scripteditor/lrscripthighlighter.h \ $$REPORT_PATH/items/editors/lritemeditorwidget.h \ $$REPORT_PATH/items/editors/lrfonteditorwidget.h \ + $$REPORT_PATH/items/editors/lrtextalignmenteditorwidget.h \ + $$REPORT_PATH/items/editors/lritemsborderseditorwidget.h \ $$REPORT_PATH/items/lrtextitem.h \ $$REPORT_PATH/items/lrhorizontallayout.h \ $$REPORT_PATH/items/lrtextitemeditor.h \ @@ -114,6 +120,12 @@ HEADERS += \ $$REPORT_PATH/items/lrverticallayout.h \ $$REPORT_PATH/items/lrlayoutmarker.h \ $$REPORT_PATH/items/lrabstractlayout.h \ + $$REPORT_PATH/items/lrchartitem.h \ + $$REPORT_PATH/items/lrchartitemeditor.h \ + $$REPORT_PATH/items/charts/lrhorizontalbarchart.h \ + $$REPORT_PATH/items/charts/lrlineschart.h \ + $$REPORT_PATH/items/charts/lrpiechart.h \ + $$REPORT_PATH/items/charts/lrverticalbarchart.h \ $$REPORT_PATH/lrbanddesignintf.h \ $$REPORT_PATH/lrpageitemdesignintf.h \ $$REPORT_PATH/lrbandsmanager.h \ @@ -145,10 +157,6 @@ HEADERS += \ $$REPORT_PATH/lrpreviewreportwidget_p.h \ $$REPORT_PATH/lritemscontainerdesignitf.h \ $$REPORT_PATH/lrcolorindicator.h \ - $$REPORT_PATH/items/lrchartitem.h \ - $$REPORT_PATH/items/lrchartitemeditor.h \ - $$REPORT_PATH/items/editors/lrtextalignmenteditorwidget.h \ - $$REPORT_PATH/items/editors/lritemsborderseditorwidget.h \ $$REPORT_PATH/lrreporttranslation.h \ $$REPORT_PATH/lrreportdesignwindowintrerface.h \ $$REPORT_PATH/lrexporterintf.h \ @@ -157,7 +165,6 @@ HEADERS += \ $$REPORT_PATH/lrpreparedpages.h \ $$REPORT_PATH/lrpreparedpagesintf.h - contains(CONFIG, staticlib){ HEADERS += $$REPORT_PATH/lrfactoryinitializer.h }