0
0
mirror of https://github.com/fralx/LimeReport.git synced 2024-12-27 09:58:11 +03:00
LimeReport/limereport/items/lrchartitem.cpp

836 lines
25 KiB
C++
Raw Normal View History

2016-11-02 01:34:45 +03:00
#include "lrchartitem.h"
#include <QStyleOptionGraphicsItem>
#include <QPainter>
#include "lrdesignelementsfactory.h"
#include "lrchartitemeditor.h"
#include "lrdatasourcemanager.h"
#include "lrpagedesignintf.h"
#include "lrreportengine_p.h"
#include "lrdatadesignintf.h"
2020-01-11 02:11:55 +03:00
#include "charts/lrpiechart.h"
#include "charts/lrverticalbarchart.h"
#include "charts/lrhorizontalbarchart.h"
#include "charts/lrlineschart.h"
2016-11-02 01:34:45 +03:00
namespace{
const QString xmlTag = "ChartItem";
LimeReport::BaseDesignIntf * createChartItem(QObject* owner, LimeReport::BaseDesignIntf* parent){
return new LimeReport::ChartItem(owner,parent);
}
bool registred = LimeReport::DesignElementsFactory::instance().registerCreator(
xmlTag, LimeReport::ItemAttribs(QObject::tr("Chart Item"),"Item"), createChartItem
);
}
namespace LimeReport{
QColor generateColor()
{
2021-08-23 08:07:08 +03:00
int red = (rand()%(256 - 1)) + 1;
int green = (rand()%(256 - 1)) + 1;
int blue = (rand()%(256 - 1)) + 1;;
2016-11-02 01:34:45 +03:00
return QColor(red,green,blue);
}
QColor color_map[39] = {
2020-01-11 02:11:55 +03:00
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),
2016-11-02 01:34:45 +03:00
QColor(139, 123, 139), QColor(255, 0, 255), QColor(139, 69, 19)
2017-07-13 14:39:07 +03:00
};
2016-11-02 01:34:45 +03:00
QString SeriesItem::name() const
{
return m_name;
}
void SeriesItem::setName(const QString &name)
{
m_name = name;
}
QString SeriesItem::valuesColumn() const
{
return m_valuesColumn;
}
void SeriesItem::setValuesColumn(const QString &valuesColumn)
{
m_valuesColumn = valuesColumn;
}
QString SeriesItem::labelsColumn() const
{
return m_labelsColumn;
}
void SeriesItem::setLabelsColumn(const QString &labelsColumn)
{
m_labelsColumn = labelsColumn;
}
SeriesItem *SeriesItem::clone()
{
SeriesItem* result = new SeriesItem();
2017-09-27 01:05:22 +03:00
for (int i = 0; i < this->metaObject()->propertyCount(); ++i){
result->setProperty(this->metaObject()->property(i).name(),property(this->metaObject()->property(i).name()));
}
2016-11-02 01:34:45 +03:00
return result;
}
void SeriesItem::fillSeriesData(IDataSource *dataSource)
{
2019-12-18 23:13:33 +03:00
m_data.clear();
2016-11-02 01:34:45 +03:00
if (dataSource){
dataSource->first();
int currentColorIndex = 0;
while(!dataSource->eof()){
if (!m_labelsColumn.isEmpty())
m_data.labels().append(dataSource->data(m_labelsColumn).toString());
m_data.values().append(dataSource->data(m_valuesColumn).toDouble());
m_data.colors().append((currentColorIndex<32)?color_map[currentColorIndex]:generateColor());
dataSource->next();
currentColorIndex++;
}
}
}
QColor SeriesItem::color() const
{
return m_color;
}
void SeriesItem::setColor(const QColor &color)
{
m_color = color;
}
2017-09-27 01:05:22 +03:00
SeriesItem::SeriesItemPreferredType SeriesItem::preferredType() const
{
return m_preferredType;
}
void SeriesItem::setPreferredType(const SeriesItemPreferredType& type)
{
m_preferredType = type;
}
2016-11-02 01:34:45 +03:00
ChartItem::ChartItem(QObject *owner, QGraphicsItem *parent)
: ItemDesignIntf(xmlTag, owner, parent), m_legendBorder(true),
m_legendAlign(LegendAlignCenter), m_titleAlign(TitleAlignCenter),
2020-04-06 19:48:16 +03:00
m_chartType(Pie), m_labelsField(""), m_isEmpty(true),
m_showLegend(true)
2016-11-02 01:34:45 +03:00
{
m_labels<<"First"<<"Second"<<"Thrid";
m_chart = new PieChart(this);
}
ChartItem::~ChartItem()
{
foreach (SeriesItem* series, m_series) {
delete series;
}
m_series.clear();
delete m_chart;
}
ChartItem::TitleAlign ChartItem::titleAlign() const
{
return m_titleAlign;
}
void ChartItem::setTitleAlign(const TitleAlign &titleAlign)
{
if (m_titleAlign != titleAlign){
TitleAlign oldValue = m_titleAlign;
m_titleAlign = titleAlign;
notify("titleAlign",oldValue,m_titleAlign);
update();
}
}
void ChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->save();
setupPainter(painter);
painter->setFont(transformToSceneFont(painter->font()));
painter->setRenderHint(QPainter::Antialiasing,true);
painter->setRenderHint(QPainter::TextAntialiasing,true);
qreal borderMargin = (rect().height()*0.01>10)?(10):(rect().height()*0.01);
qreal maxTitleHeight = rect().height()*0.2;
QFont tmpFont = painter->font();
qreal titleOffset = !m_title.isEmpty()?(((painter->fontMetrics().height()+borderMargin*2)<maxTitleHeight)?
(painter->fontMetrics().height()+borderMargin*2):
(maxTitleHeight)):0;
QRectF titleRect = QRectF(borderMargin,borderMargin,rect().width()-borderMargin*2,titleOffset);
2020-04-06 19:48:16 +03:00
QRectF legendRect = QRectF(0,0,0,0);
if (m_showLegend)
legendRect = m_chart->calcChartLegendRect(painter->font(), rect(), false, borderMargin, titleOffset);
2016-11-02 01:34:45 +03:00
QRectF diagramRect = rect().adjusted(borderMargin,titleOffset+borderMargin,
-(legendRect.width()+borderMargin*2),-borderMargin);
paintChartTitle(painter, titleRect);
2020-04-06 19:48:16 +03:00
if (m_showLegend)
m_chart->paintChartLegend(painter,legendRect);
2016-11-02 01:34:45 +03:00
m_chart->paintChart(painter,diagramRect);
painter->restore();
ItemDesignIntf::paint(painter,option,widget);
}
BaseDesignIntf *ChartItem::createSameTypeItem(QObject *owner, QGraphicsItem *parent)
{
ChartItem* result = new ChartItem(owner,parent);
foreach (SeriesItem* series, m_series) {
result->m_series.append(series->clone());
}
return result;
}
QObject *ChartItem::createElement(const QString &collectionName, const QString &elementType)
{
Q_UNUSED(elementType);
if (collectionName.compare("series")==0){
SeriesItem* seriesItem = new SeriesItem();
m_series.append(seriesItem);
return seriesItem;
}
return 0;
}
int ChartItem::elementsCount(const QString &collectionName)
{
if (collectionName.compare("series")==0)
return m_series.count();
return 0;
}
QObject *ChartItem::elementAt(const QString &collectionName, int index)
{
if (collectionName.compare("series")==0)
return m_series.at(index);
return 0;
}
void ChartItem::updateItemSize(DataSourceManager *dataManager, RenderPass , int )
{
2020-04-06 19:48:16 +03:00
m_isEmpty = false;
2016-11-02 01:34:45 +03:00
if (dataManager && dataManager->dataSource(m_datasource)){
IDataSource* ds = dataManager->dataSource(m_datasource);
foreach (SeriesItem* series, m_series) {
2020-04-06 19:48:16 +03:00
if (series->isEmpty()){
series->setLabelsColumn(m_labelsField);
series->fillSeriesData(ds);
}
2016-11-02 01:34:45 +03:00
}
fillLabels(ds);
}
}
void ChartItem::fillLabels(IDataSource *dataSource)
{
m_labels.clear();
if (dataSource && !m_labelsField.isEmpty()){
dataSource->first();
while(!dataSource->eof()){
m_labels.append(dataSource->data(m_labelsField).toString());
dataSource->next();
}
}
}
QWidget *ChartItem::defaultEditor()
{
QSettings* l_settings = (page()->settings() != 0) ?
page()->settings() :
(page()->reportEditor()!=0) ? page()->reportEditor()->settings() : 0;
QWidget* editor = new ChartItemEditor(this, page(), l_settings);
2016-11-02 01:34:45 +03:00
editor->setAttribute(Qt::WA_DeleteOnClose);
return editor;
}
2019-11-26 23:40:36 +03:00
bool ChartItem::isNeedUpdateSize(RenderPass pass) const
{
2020-04-06 19:48:16 +03:00
return pass == FirstPass && m_isEmpty;
}
bool ChartItem::showLegend() const
{
return m_showLegend;
}
void ChartItem::setShowLegend(bool showLegend)
{
if (m_showLegend != showLegend){
m_showLegend = showLegend;
notify("showLegend", !m_showLegend, m_showLegend);
update();
}
m_showLegend = showLegend;
2019-11-26 23:40:36 +03:00
}
2016-11-02 01:34:45 +03:00
QList<QString> ChartItem::labels() const
{
return m_labels;
}
void ChartItem::setLabels(const QList<QString> &labels)
{
m_labels = labels;
}
QString ChartItem::labelsField() const
{
return m_labelsField;
}
void ChartItem::setLabelsField(const QString &labelsField)
{
m_labelsField = labelsField;
}
ChartItem::ChartType ChartItem::chartType() const
{
return m_chartType;
}
void ChartItem::setChartType(const ChartType &chartType)
{
if (m_chartType != chartType){
ChartType oldValue = m_chartType;
m_chartType = chartType;
delete m_chart;
switch (m_chartType) {
case Pie:
m_chart = new PieChart(this);
break;
case VerticalBar:
m_chart = new VerticalBarChart(this);
break;
case HorizontalBar:
m_chart = new HorizontalBarChart(this);
break;
2020-01-11 02:11:55 +03:00
case Lines:
m_chart = new LinesChart(this);
2016-11-02 01:34:45 +03:00
}
notify("chartType",oldValue,m_chartType);
update();
}
}
QString ChartItem::datasource() const
{
return m_datasource;
}
void ChartItem::setDatasource(const QString &datasource)
{
m_datasource = datasource;
}
void ChartItem::paintChartTitle(QPainter *painter, QRectF titleRect)
{
painter->save();
QFont tmpFont = painter->font();
QFontMetrics fm(tmpFont);
2021-08-23 08:07:08 +03:00
while ((fm.height()>titleRect.height() || fm.boundingRect(m_title).width()>titleRect.width())
2016-11-02 01:34:45 +03:00
&& tmpFont.pixelSize()>1) {
tmpFont.setPixelSize(tmpFont.pixelSize()-1);
fm = QFontMetrics(tmpFont);
}
painter->setFont(tmpFont);
Qt::AlignmentFlag align = Qt::AlignCenter;
switch (m_titleAlign) {
case TitleAlignLeft:
align = Qt::AlignLeft;
break;
case TitleAlignCenter:
align = Qt::AlignCenter;
break;
case TitleAlignRight:
align = Qt::AlignRight;
break;
}
painter->drawText(titleRect, align, m_title);
painter->restore();
}
ChartItem::LegendAlign ChartItem::legendAlign() const
{
return m_legendAlign;
}
void ChartItem::setLegendAlign(const LegendAlign &legendAlign)
{
if (m_legendAlign != legendAlign){
LegendAlign oldValue = m_legendAlign;
m_legendAlign = legendAlign;
notify("legendAlign",oldValue,m_legendAlign);
update();
}
}
bool ChartItem::drawLegendBorder() const
{
return m_legendBorder;
}
void ChartItem::setDrawLegendBorder(bool legendBorder)
{
if (m_legendBorder!=legendBorder){
m_legendBorder = legendBorder;
notify("legendBorder",!m_legendBorder,m_legendBorder);
update();
}
}
QString ChartItem::chartTitle() const
{
return m_title;
}
void ChartItem::setChartTitle(const QString &title)
{
if (m_title != title){
QString oldValue = m_title;
m_title = title;
update();
notify("chartTitle",oldValue,title);
}
}
QList<SeriesItem *> &ChartItem::series()
{
return m_series;
}
void ChartItem::setSeries(const QList<SeriesItem *> &series)
{
m_series = series;
}
bool ChartItem::isSeriesExists(const QString &name)
{
foreach (SeriesItem* series, m_series) {
if (series->name().compare(name)==0) return true;
}
return false;
}
AbstractChart::AbstractChart(ChartItem *chartItem)
:m_chartItem(chartItem)
{
m_designLabels<<QObject::tr("First")<<QObject::tr("Second")<<QObject::tr("Thrid");
}
QRectF AbstractChart::calcChartLegendRect(const QFont &font, const QRectF &parentRect, bool takeAllRect, qreal borderMargin, qreal titleOffset)
{
QSizeF legendSize = calcChartLegendSize(font);
qreal legendTopMargin = 0;
qreal legendBottomMargin = 0;
switch (m_chartItem->legendAlign()) {
case ChartItem::LegendAlignTop:
legendTopMargin = titleOffset+borderMargin;
legendBottomMargin = parentRect.height()-(legendSize.height()+titleOffset);
break;
case ChartItem::LegendAlignCenter:
legendTopMargin = titleOffset+(parentRect.height()-titleOffset-legendSize.height())/2;
legendBottomMargin = (parentRect.height()-titleOffset-legendSize.height())/2;
break;
case ChartItem::LegendAlignBottom:
legendTopMargin = parentRect.height()-(legendSize.height()+titleOffset);
legendBottomMargin = borderMargin;
break;
}
qreal rightOffset = !takeAllRect?((legendSize.width()>parentRect.width()/2-borderMargin)?
(parentRect.width()/2):
(parentRect.width()-legendSize.width())):0;
QRectF legendRect = parentRect.adjusted(
rightOffset,
(legendSize.height()>(parentRect.height()-titleOffset))?(titleOffset):(legendTopMargin),
-borderMargin,
(legendSize.height()>(parentRect.height()-titleOffset))?(0):(-legendBottomMargin)
);
return legendRect;
}
void AbstractChart::prepareLegendToPaint(QRectF &legendRect, QPainter *painter)
{
QFont tmpFont = painter->font();
QSizeF legendSize = calcChartLegendSize(tmpFont);
if ((legendSize.height()>legendRect.height() || legendSize.width()>legendRect.width())){
while ( (legendSize.height()>legendRect.height() || legendSize.width()>legendRect.width())
&& tmpFont.pixelSize()>1)
{
tmpFont.setPixelSize(tmpFont.pixelSize()-1);
painter->setFont(tmpFont);
legendSize = calcChartLegendSize(tmpFont);
}
painter->setFont(tmpFont);
legendRect = calcChartLegendRect(tmpFont, legendRect, true, 0, 0);
}
}
int genNextValue(int value){
int curValue = value;
2020-01-11 02:11:55 +03:00
while (curValue % 4 != 0){
2016-11-02 01:34:45 +03:00
curValue++;
}
return curValue;
}
AbstractSeriesChart::AbstractSeriesChart(ChartItem *chartItem)
:AbstractChart(chartItem)
{
m_designValues[0] = 10;
m_designValues[1] = 35;
m_designValues[2] = 15;
m_designValues[3] = 5;
m_designValues[4] = 20;
m_designValues[5] = 10;
m_designValues[6] = 40;
m_designValues[7] = 20;
m_designValues[8] = 5;
}
qreal AbstractSeriesChart::maxValue()
{
2020-01-11 02:11:55 +03:00
if (m_chartItem->itemMode() == DesignMode) return 40;
2016-11-02 01:34:45 +03:00
qreal maxValue = 0;
foreach(SeriesItem* series, m_chartItem->series()){
foreach(qreal value, series->data()->values()){
if (value>maxValue) maxValue=value;
}
}
return maxValue;
}
qreal AbstractSeriesChart::minValue()
{
2020-01-11 02:11:55 +03:00
if (m_chartItem->itemMode() == DesignMode) return 0;
2016-11-02 01:34:45 +03:00
qreal minValue = 0;
foreach(SeriesItem* series, m_chartItem->series()){
foreach(qreal value, series->data()->values()){
if (value<minValue) minValue=value;
}
}
return minValue;
}
2020-01-11 02:11:55 +03:00
qreal AbstractSeriesChart::hPadding(QRectF chartRect)
{
return (chartRect.width() * 0.02);
}
qreal AbstractSeriesChart::vPadding(QRectF chartRect)
{
return (chartRect.height() * 0.02);
}
2016-11-02 01:34:45 +03:00
int AbstractSeriesChart::valuesCount()
{
2020-01-11 02:11:55 +03:00
if (m_chartItem->itemMode() == DesignMode) return 3;
return (m_chartItem->series().isEmpty()) ? 0 : m_chartItem->series().at(0)->data()->values().count();
2016-11-02 01:34:45 +03:00
}
int AbstractSeriesChart::seriesCount()
{
2020-01-11 02:11:55 +03:00
if (m_chartItem->itemMode() == DesignMode) return 3;
2016-11-02 01:34:45 +03:00
return m_chartItem->series().count();
}
QSizeF AbstractSeriesChart::calcChartLegendSize(const QFont &font)
{
QFontMetrics fm(font);
qreal cw = 0;
qreal maxWidth = 0;
if (!m_chartItem->series().isEmpty()){
foreach(SeriesItem* series, m_chartItem->series()){
cw += fm.height();
2021-08-23 08:07:08 +03:00
if (maxWidth<fm.boundingRect(series->name()).width())
maxWidth = fm.boundingRect(series->name()).width()+10;
2016-11-02 01:34:45 +03:00
}
} else {
foreach(QString label, m_designLabels){
cw += fm.height();
2021-08-23 08:07:08 +03:00
if (maxWidth<fm.boundingRect(label).width())
maxWidth = fm.boundingRect(label).width()+10;
2016-11-02 01:34:45 +03:00
}
}
cw += fm.height();
return QSizeF(maxWidth+fm.height()*2,cw);
}
2020-05-18 22:12:05 +03:00
bool AbstractSeriesChart::verticalLabels(QPainter* painter, QRectF labelsRect)
{
if (valuesCount() == 0) return false;
2020-01-11 02:11:55 +03:00
qreal hStep = (labelsRect.width() / valuesCount());
QFontMetrics fm = painter->fontMetrics();
foreach(QString label, m_chartItem->labels()){
2021-08-23 08:07:08 +03:00
if (fm.boundingRect(label).width() > hStep){
2020-01-11 02:11:55 +03:00
return true;
}
}
return false;
2016-11-02 01:34:45 +03:00
}
2020-01-11 02:11:55 +03:00
void AbstractSeriesChart::paintHorizontalLabels(QPainter *painter, QRectF labelsRect)
2016-11-02 01:34:45 +03:00
{
2020-05-18 22:12:05 +03:00
if (valuesCount() == 0) return;
2020-01-11 02:11:55 +03:00
painter->save();
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();
2016-11-02 01:34:45 +03:00
}
2020-01-11 02:11:55 +03:00
void AbstractSeriesChart::paintVerticalLabels(QPainter *painter, QRectF labelsRect)
2016-11-02 01:34:45 +03:00
{
2020-05-18 22:12:05 +03:00
if (valuesCount() == 0) return;
2020-01-11 02:11:55 +03:00
painter->save();
painter->setFont(adaptLabelsFont(labelsRect.adjusted(0, 0, -hPadding(m_chartItem->rect()), 0),
painter->font()));
qreal vStep = (labelsRect.height() / valuesCount());
int curLabel = 0;
2016-11-02 01:34:45 +03:00
2020-01-11 02:11:55 +03:00
painter->translate(labelsRect.topLeft());
if (!m_chartItem->labels().isEmpty()){
foreach (QString label, m_chartItem->labels()) {
painter->drawText(QRectF(QPoint(0,vStep*curLabel),
QSize(labelsRect.width()-hPadding(m_chartItem->rect()),vStep)),
Qt::AlignVCenter | Qt::AlignRight | Qt::TextWordWrap,label);
2016-11-02 01:34:45 +03:00
2020-01-11 02:11:55 +03:00
curLabel++;
}
}
painter->restore();
2016-11-02 01:34:45 +03:00
}
2020-01-11 02:11:55 +03:00
void AbstractSeriesChart::paintHorizontalGrid(QPainter *painter, QRectF gridRect)
2016-11-02 01:34:45 +03:00
{
painter->save();
2020-01-11 02:11:55 +03:00
int delta = int(maxValue() - minValue());
2016-11-02 01:34:45 +03:00
delta = genNextValue(delta);
painter->setRenderHint(QPainter::Antialiasing,false);
2021-08-23 08:07:08 +03:00
qreal hStep = (gridRect.width() - painter->fontMetrics().boundingRect(QString::number(maxValue())).width()) / 4;
2016-11-02 01:34:45 +03:00
2020-01-11 02:11:55 +03:00
painter->setFont(adaptValuesFont(hStep-4, painter->font()));
2016-11-02 01:34:45 +03:00
for (int i=0;i<5;i++){
2020-01-11 02:11:55 +03:00
painter->drawText(QRectF(gridRect.left() + 4 + hStep * i, gridRect.bottom() - painter->fontMetrics().height(),
hStep, painter->fontMetrics().height()),
QString::number(minValue() + i * delta / 4));
2016-11-02 01:34:45 +03:00
painter->drawLine( gridRect.left()+hStep*i, gridRect.bottom(),
2020-01-11 02:11:55 +03:00
gridRect.left()+hStep*i, gridRect.top());
2016-11-02 01:34:45 +03:00
}
painter->restore();
}
2020-01-11 02:11:55 +03:00
void AbstractSeriesChart::paintVerticalGrid(QPainter *painter, QRectF gridRect)
2016-11-02 01:34:45 +03:00
{
int delta = int(maxValue()-minValue());
delta = genNextValue(delta);
2020-01-11 02:11:55 +03:00
painter->setRenderHint(QPainter::Antialiasing,false);
qreal vStep = gridRect.height() / 4;
2016-11-02 01:34:45 +03:00
2020-01-11 02:11:55 +03:00
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));
2016-11-02 01:34:45 +03:00
}
2020-01-11 02:11:55 +03:00
painter->setRenderHint(QPainter::Antialiasing,true);
2016-11-02 01:34:45 +03:00
}
2020-01-11 02:11:55 +03:00
void AbstractSeriesChart::drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color)
2016-11-02 01:34:45 +03:00
{
2020-01-11 02:11:55 +03:00
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));
}
2016-11-02 01:34:45 +03:00
2020-01-11 02:11:55 +03:00
qreal AbstractSeriesChart::valuesHMargin(QPainter *painter)
{
int delta = int(maxValue()-minValue());
delta = genNextValue(delta);
2021-08-23 08:07:08 +03:00
return painter->fontMetrics().boundingRect(QString::number(delta)).width()+4;
2020-01-11 02:11:55 +03:00
}
2016-11-02 01:34:45 +03:00
2020-01-11 02:11:55 +03:00
qreal AbstractSeriesChart::valuesVMargin(QPainter *painter)
{
return painter->fontMetrics().height();
2016-11-02 01:34:45 +03:00
}
2020-01-11 02:11:55 +03:00
QFont AbstractSeriesChart::adaptLabelsFont(QRectF rect, QFont font)
2016-11-02 01:34:45 +03:00
{
QString maxWord;
QFontMetrics fm(font);
foreach(QString label, m_chartItem->labels()){
2021-08-23 08:07:08 +03:00
#if QT_VERSION < 0x060000
2016-11-02 01:34:45 +03:00
foreach (QString currentWord, label.split(QRegExp("\\W+"))){
2021-08-23 08:07:08 +03:00
#else
foreach (QString currentWord, label.split(QRegularExpression("\\W+"))){
#endif
if (fm.boundingRect(maxWord).width() < fm.boundingRect(currentWord).width()) maxWord = currentWord;
2016-11-02 01:34:45 +03:00
}
}
2021-08-23 08:07:08 +03:00
qreal curWidth = fm.boundingRect(maxWord).width();
2016-11-02 01:34:45 +03:00
QFont tmpFont = font;
2020-01-11 02:11:55 +03:00
while (curWidth>rect.width() && tmpFont.pixelSize() > 1){
tmpFont.setPixelSize(tmpFont.pixelSize() - 1);
2016-11-02 01:34:45 +03:00
QFontMetricsF tmpFM(tmpFont);
2021-08-23 08:07:08 +03:00
curWidth = tmpFM.boundingRect(maxWord).width();
2016-11-02 01:34:45 +03:00
}
return tmpFont;
}
2020-01-11 02:11:55 +03:00
QFont AbstractSeriesChart::adaptValuesFont(qreal width, QFont font)
2016-11-02 01:34:45 +03:00
{
QString strValue = QString::number(maxValue());
QFont tmpFont = font;
QScopedPointer<QFontMetricsF> fm(new QFontMetricsF(tmpFont));
2021-08-23 08:07:08 +03:00
qreal curWidth = fm->boundingRect(strValue).width();
2020-01-11 02:11:55 +03:00
while (curWidth > width && tmpFont.pixelSize() > 1){
tmpFont.setPixelSize(tmpFont.pixelSize() - 1);
2016-11-02 01:34:45 +03:00
fm.reset(new QFontMetricsF(tmpFont));
2021-08-23 08:07:08 +03:00
curWidth = fm->boundingRect(strValue).width();
2016-11-02 01:34:45 +03:00
}
return tmpFont;
}
void AbstractBarChart::paintChartLegend(QPainter *painter, QRectF legendRect)
{
prepareLegendToPaint(legendRect, painter);
int indicatorSize = painter->fontMetrics().height()/2;
painter->setPen(Qt::black);
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()){
qreal cw = 0;
foreach(SeriesItem* series, m_chartItem->series()){
QString label = series->name();
painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label);
painter->setBrush(series->color());
painter->drawEllipse(
indicatorsRect.adjusted(
0,
cw+indicatorSize/2,
-(indicatorsRect.width()-indicatorSize),
-(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2))
)
);
cw += painter->fontMetrics().height();
}
2020-05-18 22:12:05 +03:00
} else if (m_chartItem->itemMode() == DesignMode){
2016-11-02 01:34:45 +03:00
qreal cw = 0;
for (int i=0;i<m_designLabels.size();++i){
QString label = m_designLabels.at(i);
painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label);
painter->setBrush(color_map[i]);
painter->drawEllipse(
indicatorsRect.adjusted(
0,
cw+indicatorSize/2,
-(indicatorsRect.width()-indicatorSize),
-(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2))
)
);
cw += painter->fontMetrics().height();
}
}
}
2020-01-11 02:11:55 +03:00
QRectF AbstractBarChart::verticalLabelsRect(QPainter *painter, QRectF labelsRect)
{
qreal maxWidth = 0;
foreach (QString label, m_chartItem->labels()) {
2021-08-23 08:07:08 +03:00
if (painter->fontMetrics().boundingRect(label).width()>maxWidth)
maxWidth = painter->fontMetrics().boundingRect(label).width();
2020-01-11 02:11:55 +03:00
}
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()) {
2021-08-23 08:07:08 +03:00
if (painter->fontMetrics().boundingRect(label).width()>maxWidth)
maxWidth = painter->fontMetrics().boundingRect(label).width();
2020-01-11 02:11:55 +03:00
}
if ((maxWidth + vPadding(m_chartItem->rect()) < labelsRect.height()) || !verticalLabels(painter, labelsRect))
return labelsRect;
else
return labelsRect.adjusted(0, (labelsRect.height() - maxWidth), 0, 0);
}
2016-11-02 01:34:45 +03:00
} // namespace LimeReport