mirror of
https://github.com/python-LimeReport/LimeReport.git
synced 2024-12-24 12:34:39 +03:00
Add x axis
This commit is contained in:
parent
fdf7807cfb
commit
a3ffc08d49
@ -68,17 +68,22 @@ void LinesChart::drawDesignMode(QPainter* painter, qreal hStep, qreal vStep, qre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal LinesChart::calculateValueYPos(qreal, qreal max, qreal value, qreal delta, qreal height)
|
qreal LinesChart::calculatePos(const AxisData &data, qreal value, qreal rectSize) const
|
||||||
{
|
{
|
||||||
return (max - value) / delta * height;
|
if (data.reverseDirection() && data.rangeMin() >= 0) {
|
||||||
|
// Not flipping for minimum less than 0 because lower number is at the bottom.
|
||||||
|
return (1 - (data.rangeMax() - value) / data.delta()) * rectSize;
|
||||||
|
} else {
|
||||||
|
return (data.rangeMax() - value) / data.delta() * rectSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinesChart::paintSeries(QPainter *painter, SeriesItem *series, QRectF barsRect)
|
void LinesChart::paintSeries(QPainter *painter, SeriesItem *series, QRectF barsRect)
|
||||||
{
|
{
|
||||||
const AxisData &yAxisData = this->yAxisData();
|
const AxisData &yAxisData = this->yAxisData();
|
||||||
const qreal delta = yAxisData.delta();
|
|
||||||
|
|
||||||
const qreal hStep = barsRect.width() / valuesCount();
|
const qreal xAxisDiff = std::max(1.0, maxXValue() - minXValue());
|
||||||
|
const qreal hStep = barsRect.width() / xAxisDiff;
|
||||||
const qreal topMargin = barsRect.top();
|
const qreal topMargin = barsRect.top();
|
||||||
|
|
||||||
QPen pen(series->color());
|
QPen pen(series->color());
|
||||||
@ -91,11 +96,11 @@ void LinesChart::paintSeries(QPainter *painter, SeriesItem *series, QRectF barsR
|
|||||||
qreal lastXValue = barsRect.left() + hStep/2;
|
qreal lastXValue = barsRect.left() + hStep/2;
|
||||||
if (!values.isEmpty()) {
|
if (!values.isEmpty()) {
|
||||||
// Calculate first point position on plot before loop
|
// Calculate first point position on plot before loop
|
||||||
lastYValue = calculateValueYPos(yAxisData.rangeMin(), yAxisData.rangeMax(), values.first(), delta, barsRect.height());
|
lastYValue = calculatePos(yAxisData, values.first(), barsRect.height());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < values.count()-1; ++i ){
|
for (int i = 0; i < values.count()-1; ++i ){
|
||||||
const qreal startY = lastYValue;
|
const qreal startY = lastYValue;
|
||||||
const qreal endY = calculateValueYPos(yAxisData.rangeMin(), yAxisData.rangeMax(), values.at(i+1), delta, barsRect.height());
|
const qreal endY = calculatePos(yAxisData, values.at(i+1), barsRect.height());
|
||||||
// Record last used Y position to only calculate new one
|
// Record last used Y position to only calculate new one
|
||||||
lastYValue = endY;
|
lastYValue = endY;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ public:
|
|||||||
void paintChart(QPainter *painter, QRectF chartRect);
|
void paintChart(QPainter *painter, QRectF chartRect);
|
||||||
protected:
|
protected:
|
||||||
void drawDesignMode(QPainter *painter, qreal hStep, qreal vStep, qreal topShift, QRectF barsRect);
|
void drawDesignMode(QPainter *painter, qreal hStep, qreal vStep, qreal topShift, QRectF barsRect);
|
||||||
qreal calculateValueYPos(qreal min, qreal max, qreal value, qreal delta, qreal height);
|
qreal calculatePos(const AxisData &data, qreal value, qreal rectSize) const;
|
||||||
void paintSeries(QPainter *painter, SeriesItem *series, QRectF barsRect);
|
void paintSeries(QPainter *painter, SeriesItem *series, QRectF barsRect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -79,6 +79,16 @@ void SeriesItem::setLabelsColumn(const QString &labelsColumn)
|
|||||||
m_labelsColumn = labelsColumn;
|
m_labelsColumn = labelsColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SeriesItem::xAxisColumn() const
|
||||||
|
{
|
||||||
|
return m_xAxisColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeriesItem::setXAxisColumn(const QString &xAxisColumn)
|
||||||
|
{
|
||||||
|
m_xAxisColumn = xAxisColumn;
|
||||||
|
}
|
||||||
|
|
||||||
SeriesItem *SeriesItem::clone()
|
SeriesItem *SeriesItem::clone()
|
||||||
{
|
{
|
||||||
SeriesItem* result = new SeriesItem();
|
SeriesItem* result = new SeriesItem();
|
||||||
@ -98,6 +108,8 @@ void SeriesItem::fillSeriesData(IDataSource *dataSource)
|
|||||||
while(!dataSource->eof()){
|
while(!dataSource->eof()){
|
||||||
if (!m_labelsColumn.isEmpty())
|
if (!m_labelsColumn.isEmpty())
|
||||||
m_data.labels().append(dataSource->data(m_labelsColumn).toString());
|
m_data.labels().append(dataSource->data(m_labelsColumn).toString());
|
||||||
|
if (!m_xAxisColumn.isEmpty())
|
||||||
|
m_data.xAxisValues().append(dataSource->data(m_xAxisColumn).toDouble());
|
||||||
m_data.values().append(dataSource->data(m_valuesColumn).toDouble());
|
m_data.values().append(dataSource->data(m_valuesColumn).toDouble());
|
||||||
m_data.colors().append((currentColorIndex<32)?color_map[currentColorIndex]:generateColor());
|
m_data.colors().append((currentColorIndex<32)?color_map[currentColorIndex]:generateColor());
|
||||||
dataSource->next();
|
dataSource->next();
|
||||||
@ -130,7 +142,8 @@ ChartItem::ChartItem(QObject *owner, QGraphicsItem *parent)
|
|||||||
: ItemDesignIntf(xmlTag, owner, parent), m_legendBorder(true),
|
: ItemDesignIntf(xmlTag, owner, parent), m_legendBorder(true),
|
||||||
m_legendAlign(LegendAlignCenter), m_titleAlign(TitleAlignCenter),
|
m_legendAlign(LegendAlignCenter), m_titleAlign(TitleAlignCenter),
|
||||||
m_chartType(Pie), m_labelsField(""), m_isEmpty(true),
|
m_chartType(Pie), m_labelsField(""), m_isEmpty(true),
|
||||||
m_showLegend(true), m_drawPoints(true), m_seriesLineWidth(4)
|
m_showLegend(true), m_drawPoints(true), m_seriesLineWidth(4),
|
||||||
|
m_horizontalAxisOnTop(false), m_legendStyle(LegendPoints)
|
||||||
{
|
{
|
||||||
m_labels<<"First"<<"Second"<<"Thrid";
|
m_labels<<"First"<<"Second"<<"Thrid";
|
||||||
m_chart = new PieChart(this);
|
m_chart = new PieChart(this);
|
||||||
@ -235,6 +248,7 @@ void ChartItem::updateItemSize(DataSourceManager *dataManager, RenderPass , int
|
|||||||
foreach (SeriesItem* series, m_series) {
|
foreach (SeriesItem* series, m_series) {
|
||||||
if (series->isEmpty()){
|
if (series->isEmpty()){
|
||||||
series->setLabelsColumn(m_labelsField);
|
series->setLabelsColumn(m_labelsField);
|
||||||
|
series->setXAxisColumn(m_xAxisField);
|
||||||
series->fillSeriesData(ds);
|
series->fillSeriesData(ds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,6 +478,31 @@ void ChartItem::setSeriesLineWidth(int newSeriesLineWidth)
|
|||||||
m_seriesLineWidth = newSeriesLineWidth;
|
m_seriesLineWidth = newSeriesLineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ChartItem::xAxisField() const
|
||||||
|
{
|
||||||
|
return m_xAxisField;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChartItem::setXAxisField(const QString &xAxisField)
|
||||||
|
{
|
||||||
|
m_xAxisField = xAxisField;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChartItem::horizontalAxisOnTop() const
|
||||||
|
{
|
||||||
|
return m_horizontalAxisOnTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChartItem::setHorizontalAxisOnTop(bool horizontalAxisOnTop)
|
||||||
|
{
|
||||||
|
if (m_horizontalAxisOnTop != horizontalAxisOnTop){
|
||||||
|
m_horizontalAxisOnTop = horizontalAxisOnTop;
|
||||||
|
notify("horizontalAxisOnTop", !m_horizontalAxisOnTop, m_horizontalAxisOnTop);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
m_horizontalAxisOnTop = horizontalAxisOnTop;
|
||||||
|
}
|
||||||
|
|
||||||
AbstractChart::AbstractChart(ChartItem *chartItem)
|
AbstractChart::AbstractChart(ChartItem *chartItem)
|
||||||
:m_chartItem(chartItem)
|
:m_chartItem(chartItem)
|
||||||
{
|
{
|
||||||
@ -550,20 +589,40 @@ qreal AbstractSeriesChart::minValue()
|
|||||||
AxisData AbstractSeriesChart::yAxisData()
|
AxisData AbstractSeriesChart::yAxisData()
|
||||||
{
|
{
|
||||||
return m_yAxisData;
|
return m_yAxisData;
|
||||||
|
qreal AbstractSeriesChart::minXValue()
|
||||||
|
{
|
||||||
|
return m_chartItem->xAxisData()->minValue();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractSeriesChart::updateMinAndMaxValues()
|
void AbstractSeriesChart::updateMinAndMaxValues()
|
||||||
{
|
{
|
||||||
qreal maxYValue = 0;
|
qreal maxYValue = 0;
|
||||||
qreal minYValue = 0;
|
qreal minYValue = 0;
|
||||||
|
qreal maxXValue = 0;
|
||||||
|
qreal minXValue = 0;
|
||||||
if (m_chartItem->itemMode() == DesignMode) {
|
if (m_chartItem->itemMode() == DesignMode) {
|
||||||
maxYValue = 40;
|
maxYValue = 40;
|
||||||
|
maxXValue = 40;
|
||||||
} else {
|
} else {
|
||||||
for (SeriesItem* series : m_chartItem->series()){
|
for (SeriesItem* series : m_chartItem->series()){
|
||||||
for (qreal value : series->data()->values()){
|
for (qreal value : series->data()->values()){
|
||||||
minYValue = std::min(minYValue, value);
|
minYValue = std::min(minYValue, value);
|
||||||
maxYValue = std::max(maxYValue, value);
|
maxYValue = std::max(maxYValue, value);
|
||||||
}
|
}
|
||||||
|
if (series->data()->xAxisValues().isEmpty()) {
|
||||||
|
// Grid plot starts from 0 on x axis so x range must be decresed by 1
|
||||||
|
const bool startingFromZero = m_chartItem->chartType() == ChartItem::GridLines;
|
||||||
|
const qreal valuesCount = this->valuesCount() - (startingFromZero ? 1 : 0);
|
||||||
|
minXValue = std::min(0.0, minXValue);
|
||||||
|
maxXValue = std::max(valuesCount, maxXValue);
|
||||||
|
} else {
|
||||||
|
for (qreal value : series->data()->xAxisValues()){
|
||||||
|
minXValue = std::min(value, minXValue);
|
||||||
|
maxXValue = std::max(value, maxXValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,12 @@ class SeriesItemData : public QObject{
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QList<qreal>& values(){ return m_values;}
|
QList<qreal>& values(){ return m_values;}
|
||||||
|
QList<qreal>& xAxisValues(){ return m_xAxisValues;}
|
||||||
QList<QString>& labels(){ return m_labels;}
|
QList<QString>& labels(){ return m_labels;}
|
||||||
QList<QColor>& colors() { return m_colors;}
|
QList<QColor>& colors() { return m_colors;}
|
||||||
void clear(){ m_values.clear(); m_labels.clear(); m_colors.clear(); }
|
void clear(){ m_values.clear(); m_labels.clear(); m_colors.clear(); }
|
||||||
private:
|
private:
|
||||||
QList<qreal> m_values;
|
QList<qreal> m_values, m_xAxisValues;
|
||||||
QList<QString> m_labels;
|
QList<QString> m_labels;
|
||||||
QList<QColor> m_colors;
|
QList<QColor> m_colors;
|
||||||
};
|
};
|
||||||
@ -30,6 +31,7 @@ class SeriesItem : public QObject{
|
|||||||
Q_PROPERTY(QString name READ name WRITE setName)
|
Q_PROPERTY(QString name READ name WRITE setName)
|
||||||
Q_PROPERTY(QString valuesColumn READ valuesColumn WRITE setValuesColumn)
|
Q_PROPERTY(QString valuesColumn READ valuesColumn WRITE setValuesColumn)
|
||||||
Q_PROPERTY(QString labelsColumn READ labelsColumn WRITE setLabelsColumn)
|
Q_PROPERTY(QString labelsColumn READ labelsColumn WRITE setLabelsColumn)
|
||||||
|
Q_PROPERTY(QString xAxisColumn READ xAxisColumn WRITE setXAxisColumn)
|
||||||
Q_PROPERTY(QColor color READ color WRITE setColor)
|
Q_PROPERTY(QColor color READ color WRITE setColor)
|
||||||
Q_PROPERTY(SeriesItemPreferredType preferredType READ preferredType WRITE setPreferredType)
|
Q_PROPERTY(SeriesItemPreferredType preferredType READ preferredType WRITE setPreferredType)
|
||||||
public:
|
public:
|
||||||
@ -46,6 +48,8 @@ public:
|
|||||||
void setValuesColumn(const QString &valuesColumn);
|
void setValuesColumn(const QString &valuesColumn);
|
||||||
QString labelsColumn() const;
|
QString labelsColumn() const;
|
||||||
void setLabelsColumn(const QString &labelsColumn);
|
void setLabelsColumn(const QString &labelsColumn);
|
||||||
|
QString xAxisColumn() const;
|
||||||
|
void setXAxisColumn(const QString &xAxisColumn);
|
||||||
SeriesItem* clone();
|
SeriesItem* clone();
|
||||||
void fillSeriesData(IDataSource* dataSource);
|
void fillSeriesData(IDataSource* dataSource);
|
||||||
SeriesItemData* data(){ return &m_data;}
|
SeriesItemData* data(){ return &m_data;}
|
||||||
@ -58,6 +62,7 @@ private:
|
|||||||
QString m_name;
|
QString m_name;
|
||||||
QString m_valuesColumn;
|
QString m_valuesColumn;
|
||||||
QString m_labelsColumn;
|
QString m_labelsColumn;
|
||||||
|
QString m_xAxisColumn;
|
||||||
SeriesItemData m_data;
|
SeriesItemData m_data;
|
||||||
QColor m_color;
|
QColor m_color;
|
||||||
SeriesItemPreferredType m_preferredType;
|
SeriesItemPreferredType m_preferredType;
|
||||||
@ -86,7 +91,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
qreal maxValue();
|
qreal maxValue();
|
||||||
qreal minValue();
|
qreal minValue();
|
||||||
AxisData yAxisData();
|
qreal maxXValue();
|
||||||
|
qreal minXValue();
|
||||||
void updateMinAndMaxValues();
|
void updateMinAndMaxValues();
|
||||||
int valuesCount();
|
int valuesCount();
|
||||||
int seriesCount();
|
int seriesCount();
|
||||||
@ -136,6 +142,8 @@ class ChartItem : public LimeReport::ItemDesignIntf
|
|||||||
//linesChart
|
//linesChart
|
||||||
Q_PROPERTY(bool drawPoints READ drawPoints WRITE setDrawPoints)
|
Q_PROPERTY(bool drawPoints READ drawPoints WRITE setDrawPoints)
|
||||||
Q_PROPERTY(int seriesLineWidth READ seriesLineWidth WRITE setSeriesLineWidth)
|
Q_PROPERTY(int seriesLineWidth READ seriesLineWidth WRITE setSeriesLineWidth)
|
||||||
|
Q_PROPERTY(bool horizontalAxisOnTop READ horizontalAxisOnTop WRITE setHorizontalAxisOnTop)
|
||||||
|
Q_PROPERTY(QString xAxisField READ xAxisField WRITE setXAxisField)
|
||||||
friend class AbstractChart;
|
friend class AbstractChart;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -194,6 +202,12 @@ public:
|
|||||||
int seriesLineWidth() const;
|
int seriesLineWidth() const;
|
||||||
void setSeriesLineWidth(int newSeriesLineWidth);
|
void setSeriesLineWidth(int newSeriesLineWidth);
|
||||||
|
|
||||||
|
QString xAxisField() const;
|
||||||
|
void setXAxisField(const QString &xAxisField);
|
||||||
|
|
||||||
|
bool horizontalAxisOnTop() const;
|
||||||
|
void setHorizontalAxisOnTop(bool horizontalAxisOnTop);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintChartTitle(QPainter* painter, QRectF titleRect);
|
void paintChartTitle(QPainter* painter, QRectF titleRect);
|
||||||
virtual BaseDesignIntf* createSameTypeItem(QObject *owner, QGraphicsItem *parent);
|
virtual BaseDesignIntf* createSameTypeItem(QObject *owner, QGraphicsItem *parent);
|
||||||
@ -222,6 +236,8 @@ private:
|
|||||||
bool m_showLegend;
|
bool m_showLegend;
|
||||||
bool m_drawPoints;
|
bool m_drawPoints;
|
||||||
int m_seriesLineWidth;
|
int m_seriesLineWidth;
|
||||||
|
QString m_xAxisField;
|
||||||
|
bool m_horizontalAxisOnTop;
|
||||||
};
|
};
|
||||||
} //namespace LimeReport
|
} //namespace LimeReport
|
||||||
#endif // LRCHARTITEM_H
|
#endif // LRCHARTITEM_H
|
||||||
|
@ -144,6 +144,7 @@ void QObjectPropertyModel::translatePropertyName()
|
|||||||
tr("chartType");
|
tr("chartType");
|
||||||
tr("drawLegendBorder");
|
tr("drawLegendBorder");
|
||||||
tr("labelsField");
|
tr("labelsField");
|
||||||
|
tr("xAxisField");
|
||||||
tr("legendAlign");
|
tr("legendAlign");
|
||||||
tr("series");
|
tr("series");
|
||||||
tr("titleAlign");
|
tr("titleAlign");
|
||||||
|
Loading…
Reference in New Issue
Block a user