mirror of
				https://github.com/fralx/LimeReport.git
				synced 2025-10-31 21:31:21 +03:00 
			
		
		
		
	Merge pull request #380 from emil-sawicki9/feature/charts-x-axis
Added grid chart with x axis
This commit is contained in:
		
							
								
								
									
										112
									
								
								limereport/items/charts/lrgridlineschart.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								limereport/items/charts/lrgridlineschart.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | #include "lrgridlineschart.h" | ||||||
|  |  | ||||||
|  | namespace LimeReport { | ||||||
|  | void GridLinesChart::paintChart(QPainter *painter, QRectF chartRect) | ||||||
|  | { | ||||||
|  |     updateMinAndMaxValues(); | ||||||
|  |  | ||||||
|  |     const qreal hPadding = this->hPadding(chartRect); | ||||||
|  |     const qreal vPadding = this->vPadding(chartRect); | ||||||
|  |  | ||||||
|  |     const qreal valuesVMargin = this->valuesVMargin(painter); | ||||||
|  |  | ||||||
|  |     QRectF gridRect = chartRect.adjusted( | ||||||
|  |         hPadding, | ||||||
|  |         vPadding + valuesVMargin * 2, | ||||||
|  |         -hPadding * 3, | ||||||
|  |         -vPadding * 3 | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     if (!m_chartItem->horizontalAxisOnTop()) { | ||||||
|  |         // If horizontal axis is on the bottom, move grid a little up | ||||||
|  |         gridRect.adjust(0, -valuesVMargin, 0 , -valuesVMargin); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Adapt font for horizontal axis | ||||||
|  |     painter->setFont(adaptFont((gridRect.width() - this->valuesHMargin(painter)) / xAxisData().segmentCount() * 0.8, | ||||||
|  |                                painter->font(), | ||||||
|  |                                xAxisData())); | ||||||
|  |  | ||||||
|  |     const qreal valuesHMargin = this->valuesHMargin(painter); | ||||||
|  |  | ||||||
|  |     // Adjust vertical axis labels padding | ||||||
|  |     gridRect.adjust(valuesHMargin * 0.2, 0, 0, 0); | ||||||
|  |  | ||||||
|  |     paintGrid(painter, gridRect); | ||||||
|  |  | ||||||
|  |     paintSerialLines( | ||||||
|  |         painter, | ||||||
|  |         gridRect.adjusted(hPadding + valuesHMargin, 0, 0, 0) | ||||||
|  |         ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GridLinesChart::paintSerialLines(QPainter* painter, QRectF barsRect) | ||||||
|  | { | ||||||
|  |     if (valuesCount() == 0) return; | ||||||
|  |  | ||||||
|  |     painter->save(); | ||||||
|  |     painter->setRenderHint(QPainter::Antialiasing,true); | ||||||
|  |  | ||||||
|  |     const AxisData &yAxisData = this->yAxisData(); | ||||||
|  |     const qreal delta = yAxisData.delta(); | ||||||
|  |  | ||||||
|  |     if (m_chartItem->itemMode() == DesignMode){ | ||||||
|  |         const qreal hStep = barsRect.width() / valuesCount(); | ||||||
|  |         const qreal vStep = barsRect.height() / delta; | ||||||
|  |         const qreal topShift = (delta - (maxValue() - minValue())) * vStep + barsRect.top(); | ||||||
|  |         drawDesignMode(painter, hStep, vStep, topShift, barsRect); | ||||||
|  |         painter->restore(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const AxisData &xAxisData = this->xAxisData(); | ||||||
|  |     const qreal hStep = barsRect.width() / (xAxisData.rangeMax() - xAxisData.rangeMin()); | ||||||
|  |  | ||||||
|  |     qreal leftMargin = 0; | ||||||
|  |     const qreal topMargin = barsRect.top(); | ||||||
|  |  | ||||||
|  |     for (SeriesItem* series : m_chartItem->series()) { | ||||||
|  |         QPen pen(series->color()); | ||||||
|  |         pen.setWidth(m_chartItem->seriesLineWidth()); | ||||||
|  |         painter->setPen(pen); | ||||||
|  |  | ||||||
|  |         const QList<qreal> &xAxisValues = series->data()->xAxisValues(); | ||||||
|  |         const QList<qreal> &values = series->data()->values(); | ||||||
|  |         const int xAxisValuesSize = xAxisValues.size(); | ||||||
|  |         qreal lastXPos = 0; | ||||||
|  |         qreal lastYPos = 0; | ||||||
|  |         if (!values.isEmpty()) { | ||||||
|  |             // Calculate first point position on plot before loop | ||||||
|  |             lastYPos = calculatePos(yAxisData, values.first(), barsRect.height()); | ||||||
|  |         } | ||||||
|  |         if (xAxisValues.isEmpty()) { | ||||||
|  |             leftMargin = barsRect.left(); | ||||||
|  |         } else { | ||||||
|  |             leftMargin = barsRect.left(); | ||||||
|  |             lastXPos = calculatePos(xAxisData, xAxisValues.first(), barsRect.width()); | ||||||
|  |         } | ||||||
|  |         for (int i = 0; i < values.count() - 1; ++i ) { | ||||||
|  |             const qreal startY = lastYPos; | ||||||
|  |             const qreal endY = calculatePos(yAxisData, values.at(i+1), barsRect.height()); | ||||||
|  |             // Record last used Y position to only calculate new one | ||||||
|  |             lastYPos = endY; | ||||||
|  |  | ||||||
|  |             qreal startX = lastXPos; | ||||||
|  |             qreal endX = 0; | ||||||
|  |             if (i + 1 < xAxisValuesSize) { | ||||||
|  |                 endX = calculatePos(xAxisData, xAxisValues.at(i+1), barsRect.width()); | ||||||
|  |             } else { | ||||||
|  |                 endX = startX + hStep; | ||||||
|  |             } | ||||||
|  |             // Record last used X position to only calculate new one | ||||||
|  |             lastXPos = endX; | ||||||
|  |  | ||||||
|  |             QPoint startPoint = QPoint(startX + leftMargin, startY + topMargin); | ||||||
|  |             QPoint endPoint = QPoint(endX + leftMargin, endY + topMargin); | ||||||
|  |             drawSegment(painter, startPoint, endPoint, series->color()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     painter->restore(); | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								limereport/items/charts/lrgridlineschart.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								limereport/items/charts/lrgridlineschart.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #ifndef GRIDLINESCHART_H | ||||||
|  | #define GRIDLINESCHART_H | ||||||
|  |  | ||||||
|  | #include "lrlineschart.h" | ||||||
|  |  | ||||||
|  | namespace LimeReport { | ||||||
|  | class GridLinesChart : public LinesChart{ | ||||||
|  | public: | ||||||
|  |     GridLinesChart(ChartItem* chartItem):LinesChart(chartItem){} | ||||||
|  |     void paintChart(QPainter *painter, QRectF chartRect); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     void paintSerialLines(QPainter *painter, QRectF barsRect); | ||||||
|  | }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif // GRIDLINESCHART_H | ||||||
| @@ -20,7 +20,9 @@ void HorizontalBarChart::paintChart(QPainter *painter, QRectF chartRect) | |||||||
|     paintHorizontalGrid(painter, chartRect.adjusted( |     paintHorizontalGrid(painter, chartRect.adjusted( | ||||||
|                                      hPadding(chartRect) + barsShift, |                                      hPadding(chartRect) + barsShift, | ||||||
|                                      vPadding(chartRect), |                                      vPadding(chartRect), | ||||||
|                                      -(hPadding(chartRect)),-vPadding(chartRect))); |                                      -(hPadding(chartRect)), | ||||||
|  |                                      -vPadding(chartRect))); | ||||||
|  |  | ||||||
|     paintHorizontalBars(painter, chartRect.adjusted( |     paintHorizontalBars(painter, chartRect.adjusted( | ||||||
|                                      hPadding(chartRect) + barsShift, |                                      hPadding(chartRect) + barsShift, | ||||||
|                                      vPadding(chartRect) * 2, |                                      vPadding(chartRect) * 2, | ||||||
| @@ -36,25 +38,33 @@ void HorizontalBarChart::paintHorizontalBars(QPainter *painter, QRectF barsRect) | |||||||
|  |  | ||||||
|     painter->save(); |     painter->save(); | ||||||
|     painter->setRenderHint(QPainter::Antialiasing,false); |     painter->setRenderHint(QPainter::Antialiasing,false); | ||||||
|  |  | ||||||
|     const AxisData &yAxisData = this->yAxisData(); |     const AxisData &yAxisData = this->yAxisData(); | ||||||
|     const qreal delta = yAxisData.delta(); |     const qreal delta = yAxisData.delta(); | ||||||
|  |  | ||||||
|     qreal vStep = (barsRect.height()-painter->fontMetrics().height()) / valuesCount() / seriesCount(); |     const qreal verticalOffset = painter->fontMetrics().height(); | ||||||
|  |     qreal vStep = (barsRect.height() - verticalOffset) / valuesCount() / seriesCount(); | ||||||
|     qreal hStep = (barsRect.width()-painter->fontMetrics().boundingRect(QString::number(maxValue())).width()) / delta; |     qreal hStep = (barsRect.width()-painter->fontMetrics().boundingRect(QString::number(maxValue())).width()) / delta; | ||||||
|  |  | ||||||
|     if (!m_chartItem->series().isEmpty() && (m_chartItem->itemMode() != DesignMode)){ |     if (!m_chartItem->series().isEmpty() && (m_chartItem->itemMode() != DesignMode)){ | ||||||
|         int curSeries = 0; |         qreal curVOffset = barsRect.top(); | ||||||
|  |         if (m_chartItem->horizontalAxisOnTop()) { | ||||||
|  |             curVOffset += verticalOffset; | ||||||
|  |         } | ||||||
|         foreach (SeriesItem* series, m_chartItem->series()) { |         foreach (SeriesItem* series, m_chartItem->series()) { | ||||||
|             qreal curVOffset = curSeries*vStep+barsRect.top(); |  | ||||||
|             painter->setBrush(series->color()); |             painter->setBrush(series->color()); | ||||||
|  |             qreal y = curVOffset; | ||||||
|             foreach (qreal value, series->data()->values()) { |             foreach (qreal value, series->data()->values()) { | ||||||
|                 painter->drawRect(QRectF((-minValue()*hStep)+barsRect.left(), curVOffset, value*hStep, vStep)); |                 painter->drawRect(QRectF((-minValue()*hStep)+barsRect.left(), y, value*hStep, vStep)); | ||||||
|                 curVOffset+=vStep*seriesCount(); |                 y+=vStep*seriesCount(); | ||||||
|             } |             } | ||||||
|             curSeries++; |             curVOffset += vStep; | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         qreal curVOffset = barsRect.top(); |         qreal curVOffset = barsRect.top(); | ||||||
|  |         if (m_chartItem->horizontalAxisOnTop()) { | ||||||
|  |             curVOffset += verticalOffset; | ||||||
|  |         } | ||||||
|         int curColor = 0; |         int curColor = 0; | ||||||
|         for (int i=0; i<9; ++i){ |         for (int i=0; i<9; ++i){ | ||||||
|             if (curColor==3) curColor=0; |             if (curColor==3) curColor=0; | ||||||
|   | |||||||
| @@ -68,17 +68,18 @@ 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; |     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 AxisData &xAxisData = this->xAxisData(); | ||||||
|  |  | ||||||
|     const qreal hStep = barsRect.width() / valuesCount(); |     const qreal xAxisDiff = std::max(1.0, xAxisData.maxValue() - xAxisData.minValue()); | ||||||
|  |     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 +92,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: | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ | |||||||
| #include "charts/lrverticalbarchart.h" | #include "charts/lrverticalbarchart.h" | ||||||
| #include "charts/lrhorizontalbarchart.h" | #include "charts/lrhorizontalbarchart.h" | ||||||
| #include "charts/lrlineschart.h" | #include "charts/lrlineschart.h" | ||||||
|  | #include "charts/lrgridlineschart.h" | ||||||
|  |  | ||||||
| namespace{ | namespace{ | ||||||
|  |  | ||||||
| @@ -79,6 +80,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 +109,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 +143,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_gridChartLines(AllLines) | ||||||
| { | { | ||||||
|     m_labels<<"First"<<"Second"<<"Thrid"; |     m_labels<<"First"<<"Second"<<"Thrid"; | ||||||
|     m_chart = new PieChart(this); |     m_chart = new PieChart(this); | ||||||
| @@ -235,6 +249,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); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -327,6 +342,10 @@ void ChartItem::setChartType(const ChartType &chartType) | |||||||
|             break; |             break; | ||||||
|         case Lines: |         case Lines: | ||||||
|             m_chart = new LinesChart(this); |             m_chart = new LinesChart(this); | ||||||
|  |             break; | ||||||
|  |         case GridLines: | ||||||
|  |             m_chart = new GridLinesChart(this); | ||||||
|  |             break; | ||||||
|         } |         } | ||||||
|         notify("chartType",oldValue,m_chartType); |         notify("chartType",oldValue,m_chartType); | ||||||
|         update(); |         update(); | ||||||
| @@ -464,6 +483,50 @@ 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ChartItem::GridChartLines ChartItem::gridChartLines() const | ||||||
|  | { | ||||||
|  |     return m_gridChartLines; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ChartItem::setGridChartLines(GridChartLines flags) | ||||||
|  | { | ||||||
|  |     if (m_gridChartLines == flags) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     GridChartLines oldValue = m_gridChartLines; | ||||||
|  |     m_gridChartLines = flags; | ||||||
|  |     if (isLoading()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     update(rect()); | ||||||
|  |     notify("gridChartLines",QVariant(oldValue),QVariant(flags)); | ||||||
|  | } | ||||||
|  |  | ||||||
| AbstractChart::AbstractChart(ChartItem *chartItem) | AbstractChart::AbstractChart(ChartItem *chartItem) | ||||||
|     :m_chartItem(chartItem) |     :m_chartItem(chartItem) | ||||||
| { | { | ||||||
| @@ -552,22 +615,43 @@ AxisData AbstractSeriesChart::yAxisData() | |||||||
|     return m_yAxisData; |     return m_yAxisData; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | AxisData AbstractSeriesChart::xAxisData() | ||||||
|  | { | ||||||
|  |     return m_xAxisData; | ||||||
|  | } | ||||||
|  |  | ||||||
| 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); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     m_yAxisData = AxisData(minYValue, maxYValue); |     m_yAxisData = AxisData(minYValue, maxYValue); | ||||||
|  |     m_xAxisData = AxisData(minXValue, maxXValue); | ||||||
| } | } | ||||||
|  |  | ||||||
| qreal AbstractSeriesChart::hPadding(QRectF chartRect) | qreal AbstractSeriesChart::hPadding(QRectF chartRect) | ||||||
| @@ -686,7 +770,6 @@ void AbstractSeriesChart::paintHorizontalGrid(QPainter *painter, QRectF gridRect | |||||||
|     painter->save(); |     painter->save(); | ||||||
|  |  | ||||||
|     const AxisData &yAxisData = this->yAxisData(); |     const AxisData &yAxisData = this->yAxisData(); | ||||||
|     const qreal delta = yAxisData.delta(); |  | ||||||
|  |  | ||||||
|     const int segmentCount = yAxisData.segmentCount(); |     const int segmentCount = yAxisData.segmentCount(); | ||||||
|     const int lineCount = segmentCount + 1; |     const int lineCount = segmentCount + 1; | ||||||
| @@ -694,15 +777,20 @@ void AbstractSeriesChart::paintHorizontalGrid(QPainter *painter, QRectF gridRect | |||||||
|     painter->setRenderHint(QPainter::Antialiasing,false); |     painter->setRenderHint(QPainter::Antialiasing,false); | ||||||
|     qreal hStep = (gridRect.width() - painter->fontMetrics().boundingRect(QString::number(maxValue())).width()) / segmentCount; |     qreal hStep = (gridRect.width() - painter->fontMetrics().boundingRect(QString::number(maxValue())).width()) / segmentCount; | ||||||
|  |  | ||||||
|     painter->setFont(adaptValuesFont(hStep-4, painter->font())); |     painter->setFont(adaptFont(hStep-4, painter->font(), yAxisData)); | ||||||
|  |  | ||||||
|  |     QPointF textPos; | ||||||
|  |     if (m_chartItem->horizontalAxisOnTop()) { | ||||||
|  |         textPos.setY(gridRect.top()); | ||||||
|  |     } else { | ||||||
|  |         textPos.setY(gridRect.bottom() - painter->fontMetrics().height()); | ||||||
|  |     } | ||||||
|     for (int i = 0 ; i < lineCount ; i++ ) { |     for (int i = 0 ; i < lineCount ; i++ ) { | ||||||
|         painter->drawText(QRectF(gridRect.left() + 4 + hStep * i, gridRect.bottom() - painter->fontMetrics().height(), |         const qreal x = gridRect.left() + hStep * i; | ||||||
|                                  hStep, painter->fontMetrics().height()), |         textPos.setX(x + 4); | ||||||
|                           QString::number(minValue() + i * delta / segmentCount)); |         painter->drawText(QRectF(textPos, QSizeF(hStep, painter->fontMetrics().height())), | ||||||
|         painter->drawLine( gridRect.left()+hStep*i, gridRect.bottom(), |                           axisLabel(i, yAxisData)); | ||||||
|                           gridRect.left()+hStep*i, gridRect.top()); |         painter->drawLine(x, gridRect.bottom(), x, gridRect.top()); | ||||||
|  |  | ||||||
|     } |     } | ||||||
|     painter->restore(); |     painter->restore(); | ||||||
| } | } | ||||||
| @@ -727,7 +815,7 @@ void AbstractSeriesChart::paintVerticalGrid(QPainter *painter, QRectF gridRect) | |||||||
|         const qreal y = vStep * i; |         const qreal y = vStep * i; | ||||||
|         painter->drawText(QRectF(gridRect.bottomLeft()-QPointF(textPositionOffset,y+halfFontHeight), |         painter->drawText(QRectF(gridRect.bottomLeft()-QPointF(textPositionOffset,y+halfFontHeight), | ||||||
|                                  QSizeF(valuesHMargin,fontHeight)), |                                  QSizeF(valuesHMargin,fontHeight)), | ||||||
|                           verticalLabel(i, yAxisData.step(), yAxisData.rangeMin()), |                           axisLabel(i, yAxisData), | ||||||
|                           verticalTextOption); |                           verticalTextOption); | ||||||
|         painter->drawLine(gridRect.bottomLeft()-QPointF(-valuesHMargin,y), |         painter->drawLine(gridRect.bottomLeft()-QPointF(-valuesHMargin,y), | ||||||
|                           gridRect.bottomRight()-QPointF(0,y)); |                           gridRect.bottomRight()-QPointF(0,y)); | ||||||
| @@ -736,6 +824,73 @@ void AbstractSeriesChart::paintVerticalGrid(QPainter *painter, QRectF gridRect) | |||||||
|     painter->setRenderHint(QPainter::Antialiasing,true); |     painter->setRenderHint(QPainter::Antialiasing,true); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void AbstractSeriesChart::paintGrid(QPainter *painter, QRectF gridRect) | ||||||
|  | { | ||||||
|  |     painter->save(); | ||||||
|  |  | ||||||
|  |     const AxisData &yAxisData = this->yAxisData(); | ||||||
|  |     const AxisData &xAxisData = this->xAxisData(); | ||||||
|  |  | ||||||
|  |     painter->setRenderHint(QPainter::Antialiasing,false); | ||||||
|  |  | ||||||
|  |     const int xAxisSegmentCount = xAxisData.segmentCount(); | ||||||
|  |     const int xAxisLineCount = xAxisSegmentCount + 1; | ||||||
|  |     const int yAxisSegmentCount = yAxisData.segmentCount(); | ||||||
|  |     const int yAxisLineCount = yAxisSegmentCount + 1; | ||||||
|  |  | ||||||
|  |     const int fontHeight = painter->fontMetrics().height(); | ||||||
|  |     const int halfFontHeight = fontHeight / 2; | ||||||
|  |     const QSizeF gridOffset = QSizeF(hPadding(gridRect), vPadding(gridRect)); | ||||||
|  |     const qreal valuesHMargin = this->valuesHMargin(painter); | ||||||
|  |     const qreal vStep = gridRect.height() / yAxisSegmentCount; | ||||||
|  |     const qreal hStep = (gridRect.width() - valuesHMargin - gridOffset.width()) / xAxisSegmentCount; | ||||||
|  |     const qreal textPositionHOffset = valuesHMargin * 0.1; | ||||||
|  |  | ||||||
|  |     // Vertical axis lines | ||||||
|  |     const QTextOption verticalTextOption(Qt::AlignRight); | ||||||
|  |     for (int i = 0 ; i < yAxisLineCount ; i++ ) { | ||||||
|  |         const qreal y = vStep * i; | ||||||
|  |         const bool drawFullLine = m_chartItem->gridChartLines() & ChartItem::HorizontalLine | ||||||
|  |                                   || i == 0 || i == xAxisSegmentCount; | ||||||
|  |         painter->drawText(QRectF(gridRect.bottomLeft()-QPointF(textPositionHOffset, y + halfFontHeight), | ||||||
|  |                                  QSizeF(valuesHMargin,fontHeight)), | ||||||
|  |                           axisLabel(i, yAxisData), | ||||||
|  |                           verticalTextOption); | ||||||
|  |  | ||||||
|  |         QPointF lineEndPos = gridRect.bottomRight() - QPointF(0, y); | ||||||
|  |         if (!drawFullLine) { | ||||||
|  |             lineEndPos.setX(gridRect.left() + valuesHMargin + gridOffset.width()); | ||||||
|  |         } | ||||||
|  |         painter->drawLine(gridRect.bottomLeft() - QPointF(-valuesHMargin, y), lineEndPos); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Horizontal axis lines | ||||||
|  |     for (int i = 0 ; i < xAxisLineCount ; i++) { | ||||||
|  |         const qreal x = gridRect.left() + hStep * i + valuesHMargin + gridOffset.width(); | ||||||
|  |         const bool drawFullLine = m_chartItem->gridChartLines() & ChartItem::VerticalLine | ||||||
|  |                                   || i == 0 || i == xAxisSegmentCount; | ||||||
|  |         const QString text = axisLabel(i, xAxisData); | ||||||
|  |  | ||||||
|  |         if (m_chartItem->horizontalAxisOnTop()) { | ||||||
|  |             painter->drawLine(x, gridRect.top() - gridOffset.height(), | ||||||
|  |                               x, (drawFullLine ? gridRect.bottom() : gridRect.top())); | ||||||
|  |             painter->drawText(QRectF(x - painter->fontMetrics().width(text) / 2, | ||||||
|  |                                      gridRect.top() - (fontHeight + gridOffset.height()), | ||||||
|  |                                      hStep, fontHeight), | ||||||
|  |                               text); | ||||||
|  |         } else { | ||||||
|  |             painter->drawLine(x, gridRect.bottom() + gridOffset.height(), | ||||||
|  |                               x, (drawFullLine ? gridRect.top() : gridRect.bottom())); | ||||||
|  |             painter->drawText(QRectF(x - painter->fontMetrics().width(text) / 2, | ||||||
|  |                                      gridRect.bottom() + halfFontHeight * 0 + gridOffset.height(), | ||||||
|  |                                      hStep, fontHeight), | ||||||
|  |                               text); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     painter->restore(); | ||||||
|  | } | ||||||
|  |  | ||||||
| void AbstractSeriesChart::drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color) | void AbstractSeriesChart::drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color) | ||||||
| { | { | ||||||
|     int radius = m_chartItem->seriesLineWidth(); |     int radius = m_chartItem->seriesLineWidth(); | ||||||
| @@ -761,7 +916,7 @@ qreal AbstractSeriesChart::valuesHMargin(QPainter *painter) | |||||||
|     const int yAxisLineCount = yAxisData.segmentCount() + 1; |     const int yAxisLineCount = yAxisData.segmentCount() + 1; | ||||||
|  |  | ||||||
|     for (int i = 0 ; i < yAxisLineCount ; i++) { |     for (int i = 0 ; i < yAxisLineCount ; i++) { | ||||||
|         const QString label = verticalLabel(i, yAxisData.step(), yAxisData.rangeMin()); |         const QString label = axisLabel(i, yAxisData); | ||||||
|         max = std::max(max, (qreal)painter->fontMetrics().boundingRect(label).width()+offset); |         max = std::max(max, (qreal)painter->fontMetrics().boundingRect(label).width()+offset); | ||||||
|     } |     } | ||||||
|     return max; |     return max; | ||||||
| @@ -797,28 +952,33 @@ QFont AbstractSeriesChart::adaptLabelsFont(QRectF rect, QFont font) | |||||||
|     return tmpFont; |     return tmpFont; | ||||||
| } | } | ||||||
|  |  | ||||||
| QFont AbstractSeriesChart::adaptValuesFont(qreal width, QFont font) | QFont AbstractSeriesChart::adaptFont(qreal width, QFont font, const AxisData &axisData) | ||||||
| { | { | ||||||
|     QString strValue = QString::number(maxValue()); |  | ||||||
|     QFont tmpFont = font; |     QFont tmpFont = font; | ||||||
|  |     const int axisLineCount = axisData.segmentCount() + 1; | ||||||
|     QScopedPointer<QFontMetricsF> fm(new QFontMetricsF(tmpFont)); |     QScopedPointer<QFontMetricsF> fm(new QFontMetricsF(tmpFont)); | ||||||
|     qreal curWidth = fm->boundingRect(strValue).width(); |     for (int i = 0 ; i < axisLineCount ; i++) { | ||||||
|     while (curWidth > width && tmpFont.pixelSize() > 1){ |         QString strValue = axisLabel(i, axisData); | ||||||
|         tmpFont.setPixelSize(tmpFont.pixelSize() - 1); |         qreal curWidth = fm->boundingRect(strValue).width(); | ||||||
|         fm.reset(new QFontMetricsF(tmpFont)); |         while (curWidth > width && tmpFont.pixelSize() > 1){ | ||||||
|         curWidth = fm->boundingRect(strValue).width(); |             tmpFont.setPixelSize(tmpFont.pixelSize() - 1); | ||||||
|  |             fm.reset(new QFontMetricsF(tmpFont)); | ||||||
|  |             curWidth = fm->boundingRect(strValue).width(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     return tmpFont; |     return tmpFont; | ||||||
| } | } | ||||||
|  |  | ||||||
| QString AbstractSeriesChart::verticalLabel(int i, qreal step, qreal min) | QString AbstractSeriesChart::axisLabel(int i, const AxisData &axisData) | ||||||
| { | { | ||||||
|  |     const qreal min = axisData.rangeMin(); | ||||||
|  |     const qreal step = axisData.step(); | ||||||
|     qreal value = min + i * step; |     qreal value = min + i * step; | ||||||
|     if (std::floor(step) == step) { |     if (std::floor(step) == step) { | ||||||
|         return QString::number(value); |         return QString::number(value); | ||||||
|     } |     } | ||||||
|     // For float round numbers to small precision |     // For float round numbers to small precision | ||||||
|     return QString::number(value, 'g', 2); |     return QString::number(round(value * 100.0) / 100.0); | ||||||
| } | } | ||||||
|  |  | ||||||
| void AbstractBarChart::paintChartLegend(QPainter *painter, QRectF legendRect) | void AbstractBarChart::paintChartLegend(QPainter *painter, QRectF legendRect) | ||||||
| @@ -897,4 +1057,5 @@ QRectF AbstractBarChart::horizontalLabelsRect(QPainter *painter, QRectF labelsRe | |||||||
|     else |     else | ||||||
|         return labelsRect.adjusted(0, (labelsRect.height() - maxWidth), 0, 0); |         return labelsRect.adjusted(0, (labelsRect.height() - maxWidth), 0, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace LimeReport | } // namespace LimeReport | ||||||
|   | |||||||
| @@ -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; | ||||||
| @@ -84,9 +89,10 @@ class AbstractSeriesChart: public AbstractChart{ | |||||||
| public: | public: | ||||||
|     AbstractSeriesChart(ChartItem* chartItem); |     AbstractSeriesChart(ChartItem* chartItem); | ||||||
| protected: | protected: | ||||||
|  |     AxisData yAxisData(); | ||||||
|  |     AxisData xAxisData(); | ||||||
|     qreal maxValue(); |     qreal maxValue(); | ||||||
|     qreal minValue(); |     qreal minValue(); | ||||||
|     AxisData yAxisData(); |  | ||||||
|     void updateMinAndMaxValues(); |     void updateMinAndMaxValues(); | ||||||
|     int valuesCount(); |     int valuesCount(); | ||||||
|     int seriesCount(); |     int seriesCount(); | ||||||
| @@ -98,16 +104,17 @@ protected: | |||||||
|     virtual void paintHorizontalLabels(QPainter *painter, QRectF labelsRect); |     virtual void paintHorizontalLabels(QPainter *painter, QRectF labelsRect); | ||||||
|     virtual void paintVerticalLabels(QPainter *painter, QRectF labelsRect); |     virtual void paintVerticalLabels(QPainter *painter, QRectF labelsRect); | ||||||
|     virtual void paintHorizontalGrid(QPainter *painter, QRectF gridRect); |     virtual void paintHorizontalGrid(QPainter *painter, QRectF gridRect); | ||||||
|  |     virtual void paintGrid(QPainter *painter, QRectF gridRect); | ||||||
|     virtual void paintVerticalGrid(QPainter *painter, QRectF gridRect); |     virtual void paintVerticalGrid(QPainter *painter, QRectF gridRect); | ||||||
|     virtual void drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color); |     virtual void drawSegment(QPainter *painter, QPoint startPoint, QPoint endPoint, QColor color); | ||||||
|     virtual qreal valuesHMargin(QPainter *painter); |     virtual qreal valuesHMargin(QPainter *painter); | ||||||
|     virtual qreal valuesVMargin(QPainter *painter); |     virtual qreal valuesVMargin(QPainter *painter); | ||||||
|     virtual QFont adaptLabelsFont(QRectF rect, QFont font); |     virtual QFont adaptLabelsFont(QRectF rect, QFont font); | ||||||
|     virtual QFont adaptValuesFont(qreal width, QFont font); |     virtual QFont adaptFont(qreal width, QFont font, const AxisData &axisData); | ||||||
|     virtual QString verticalLabel(int i, qreal step, qreal min); |     virtual QString axisLabel(int i, const AxisData &axisData); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     AxisData m_yAxisData; |     AxisData m_yAxisData, m_xAxisData; | ||||||
|     qreal m_designValues [9]; |     qreal m_designValues [9]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -136,21 +143,37 @@ 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) | ||||||
|  |  | ||||||
|  |     //gridChart | ||||||
|  |     Q_FLAGS(GridChartLines) | ||||||
|  |     Q_PROPERTY(QString xAxisField READ xAxisField WRITE setXAxisField) | ||||||
|  |     Q_PROPERTY(GridChartLines gridChartLines READ gridChartLines WRITE setGridChartLines) | ||||||
|     friend class AbstractChart; |     friend class AbstractChart; | ||||||
| public: | public: | ||||||
|  |  | ||||||
|     enum LegendAlign{LegendAlignTop,LegendAlignCenter,LegendAlignBottom}; |     enum LegendAlign{LegendAlignTop,LegendAlignCenter,LegendAlignBottom}; | ||||||
|  |     enum LegendStyle{LegendPoints, LegendLines}; | ||||||
|     enum TitleAlign{TitleAlignLeft, TitleAlignCenter, TitleAlignRight}; |     enum TitleAlign{TitleAlignLeft, TitleAlignCenter, TitleAlignRight}; | ||||||
|     enum ChartType{Pie, VerticalBar, HorizontalBar, Lines}; |     enum ChartType{Pie, VerticalBar, HorizontalBar, Lines, GridLines}; | ||||||
|  |     enum LineType { | ||||||
|  |         NoLine = 0, | ||||||
|  |         HorizontalLine = 1, | ||||||
|  |         VerticalLine = 2, | ||||||
|  |         AllLines = 3 | ||||||
|  |     }; | ||||||
| #if QT_VERSION >= 0x050500 | #if QT_VERSION >= 0x050500 | ||||||
|     Q_ENUM(LegendAlign) |     Q_ENUM(LegendAlign) | ||||||
|     Q_ENUM(TitleAlign) |     Q_ENUM(TitleAlign) | ||||||
|     Q_ENUM(ChartType) |     Q_ENUM(ChartType) | ||||||
|  |     Q_ENUM(LineType) | ||||||
| #else | #else | ||||||
|     Q_ENUMS(LegendAlign) |     Q_ENUMS(LegendAlign) | ||||||
|     Q_ENUMS(TitleAlign) |     Q_ENUMS(TitleAlign) | ||||||
|     Q_ENUMS(ChartType) |     Q_ENUMS(ChartType) | ||||||
|  |     Q_ENUMS(LineType) | ||||||
| #endif | #endif | ||||||
|  |     Q_DECLARE_FLAGS(GridChartLines, LineType) | ||||||
|  |  | ||||||
|     ChartItem(QObject* owner, QGraphicsItem* parent); |     ChartItem(QObject* owner, QGraphicsItem* parent); | ||||||
|     ~ChartItem(); |     ~ChartItem(); | ||||||
| @@ -194,6 +217,15 @@ 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); | ||||||
|  |  | ||||||
|  |     GridChartLines gridChartLines() const; | ||||||
|  |     void setGridChartLines(GridChartLines flags); | ||||||
|  |  | ||||||
| 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 +254,9 @@ 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; | ||||||
|  |     GridChartLines m_gridChartLines; | ||||||
| }; | }; | ||||||
| } //namespace LimeReport | } //namespace LimeReport | ||||||
| #endif // LRCHARTITEM_H | #endif // LRCHARTITEM_H | ||||||
|   | |||||||
| @@ -106,6 +106,7 @@ void ChartItemEditor::init() | |||||||
|                 for (int i=0;i<ds->columnCount();++i){ |                 for (int i=0;i<ds->columnCount();++i){ | ||||||
|                    ui->valuesFieldComboBox->addItem(ds->columnNameByIndex(i)); |                    ui->valuesFieldComboBox->addItem(ds->columnNameByIndex(i)); | ||||||
|                    ui->labelsFieldComboBox->addItem(ds->columnNameByIndex(i)); |                    ui->labelsFieldComboBox->addItem(ds->columnNameByIndex(i)); | ||||||
|  |                    ui->xAxisFieldComboBox->addItem(ds->columnNameByIndex(i)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -120,8 +121,10 @@ void ChartItemEditor::init() | |||||||
|  |  | ||||||
| #if QT_VERSION < 0x050000 | #if QT_VERSION < 0x050000 | ||||||
|     ui->labelsFieldComboBox->setCurrentIndex(ui->labelsFieldComboBox->findText( m_charItem->labelsField())); |     ui->labelsFieldComboBox->setCurrentIndex(ui->labelsFieldComboBox->findText( m_charItem->labelsField())); | ||||||
|  |     ui->xAxisFieldComboBox->setCurrentIndex(ui->xAxisFieldComboBox->findText( m_charItem->xAxisField())); | ||||||
| #else | #else | ||||||
|     ui->labelsFieldComboBox->setCurrentText(m_charItem->labelsField()); |     ui->labelsFieldComboBox->setCurrentText(m_charItem->labelsField()); | ||||||
|  |     ui->xAxisFieldComboBox->setCurrentText(m_charItem->xAxisField()); | ||||||
| #endif | #endif | ||||||
|     if (!m_charItem->series().isEmpty()){ |     if (!m_charItem->series().isEmpty()){ | ||||||
|         enableSeriesEditor(); |         enableSeriesEditor(); | ||||||
| @@ -287,3 +290,9 @@ void ChartItemEditor::on_seriesTypeComboBox_currentIndexChanged(const QString &a | |||||||
|         currentSeries()->setPreferredType(static_cast<LimeReport::SeriesItem::SeriesItemPreferredType>(enumerator.keysToValue(arg1.toLatin1()))); |         currentSeries()->setPreferredType(static_cast<LimeReport::SeriesItem::SeriesItemPreferredType>(enumerator.keysToValue(arg1.toLatin1()))); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void ChartItemEditor::on_xAxisFieldComboBox_currentTextChanged(const QString &arg1) | ||||||
|  | { | ||||||
|  |     if (!m_initing) | ||||||
|  |         m_charItem->setXAxisField(arg1); | ||||||
|  | } | ||||||
| @@ -41,6 +41,8 @@ private slots: | |||||||
|     void slotChangeSeriesColor(); |     void slotChangeSeriesColor(); | ||||||
|     void on_seriesTypeComboBox_currentIndexChanged(const QString &arg1); |     void on_seriesTypeComboBox_currentIndexChanged(const QString &arg1); | ||||||
|  |  | ||||||
|  |     void on_xAxisFieldComboBox_currentTextChanged(const QString &arg1); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     void readSetting(); |     void readSetting(); | ||||||
|     void writeSetting(); |     void writeSetting(); | ||||||
|   | |||||||
| @@ -144,16 +144,30 @@ | |||||||
|     </widget> |     </widget> | ||||||
|    </item> |    </item> | ||||||
|    <item> |    <item> | ||||||
|     <layout class="QHBoxLayout" name="horizontalLayout_2"> |     <layout class="QGridLayout" name="gridLayout"> | ||||||
|      <item> |      <item row="0" column="1"> | ||||||
|  |       <widget class="QComboBox" name="labelsFieldComboBox"> | ||||||
|  |        <property name="editable"> | ||||||
|  |         <bool>true</bool> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item row="0" column="0"> | ||||||
|       <widget class="QLabel" name="labelsFieldLabel"> |       <widget class="QLabel" name="labelsFieldLabel"> | ||||||
|        <property name="text"> |        <property name="text"> | ||||||
|         <string>Labels field</string> |         <string>Labels field</string> | ||||||
|        </property> |        </property> | ||||||
|       </widget> |       </widget> | ||||||
|      </item> |      </item> | ||||||
|      <item> |      <item row="1" column="0"> | ||||||
|       <widget class="QComboBox" name="labelsFieldComboBox"> |       <widget class="QLabel" name="xAxisFieldLabel"> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>X data field</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item row="1" column="1"> | ||||||
|  |       <widget class="QComboBox" name="xAxisFieldComboBox"> | ||||||
|        <property name="editable"> |        <property name="editable"> | ||||||
|         <bool>true</bool> |         <bool>true</bool> | ||||||
|        </property> |        </property> | ||||||
|   | |||||||
| @@ -49,6 +49,7 @@ SOURCES += \ | |||||||
|     $$REPORT_PATH/items/lrchartitemeditor.cpp \ |     $$REPORT_PATH/items/lrchartitemeditor.cpp \ | ||||||
|     $$REPORT_PATH/items/charts/lrhorizontalbarchart.cpp \ |     $$REPORT_PATH/items/charts/lrhorizontalbarchart.cpp \ | ||||||
|     $$REPORT_PATH/items/charts/lrlineschart.cpp \ |     $$REPORT_PATH/items/charts/lrlineschart.cpp \ | ||||||
|  |     $$REPORT_PATH/items/charts/lrgridlineschart.cpp \ | ||||||
|     $$REPORT_PATH/items/charts/lrpiechart.cpp \ |     $$REPORT_PATH/items/charts/lrpiechart.cpp \ | ||||||
|     $$REPORT_PATH/items/charts/lrverticalbarchart.cpp \ |     $$REPORT_PATH/items/charts/lrverticalbarchart.cpp \ | ||||||
|     $$REPORT_PATH/lrbanddesignintf.cpp \ |     $$REPORT_PATH/lrbanddesignintf.cpp \ | ||||||
| @@ -132,6 +133,7 @@ HEADERS += \ | |||||||
|     $$REPORT_PATH/items/lrchartitemeditor.h \ |     $$REPORT_PATH/items/lrchartitemeditor.h \ | ||||||
|     $$REPORT_PATH/items/charts/lrhorizontalbarchart.h \ |     $$REPORT_PATH/items/charts/lrhorizontalbarchart.h \ | ||||||
|     $$REPORT_PATH/items/charts/lrlineschart.h \ |     $$REPORT_PATH/items/charts/lrlineschart.h \ | ||||||
|  |     $$REPORT_PATH/items/charts/lrgridlineschart.h \ | ||||||
|     $$REPORT_PATH/items/charts/lrpiechart.h \ |     $$REPORT_PATH/items/charts/lrpiechart.h \ | ||||||
|     $$REPORT_PATH/items/charts/lrverticalbarchart.h \ |     $$REPORT_PATH/items/charts/lrverticalbarchart.h \ | ||||||
|     $$REPORT_PATH/lrbanddesignintf.h \ |     $$REPORT_PATH/lrbanddesignintf.h \ | ||||||
|   | |||||||
| @@ -20,9 +20,9 @@ public: | |||||||
|     qreal step() const; |     qreal step() const; | ||||||
|  |  | ||||||
|     qreal delta() const; |     qreal delta() const; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     void calculateValuesAboveMax(qreal minValue, qreal maxValue, int segments); |     void calculateValuesAboveMax(qreal minValue, qreal maxValue, int segments); | ||||||
|     qreal calculateNiceNum(qreal range, bool round); |  | ||||||
|  |  | ||||||
|     qreal m_rangeMin; |     qreal m_rangeMin; | ||||||
|     qreal m_rangeMax; |     qreal m_rangeMax; | ||||||
|   | |||||||
| @@ -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"); | ||||||
| @@ -170,6 +171,8 @@ void QObjectPropertyModel::translatePropertyName() | |||||||
|     tr("removeGap"); |     tr("removeGap"); | ||||||
|     tr("dropPrinterMargins"); |     tr("dropPrinterMargins"); | ||||||
|     tr("notPrintIfEmpty"); |     tr("notPrintIfEmpty"); | ||||||
|  |     tr("gridChartLines"); | ||||||
|  |     tr("horizontalAxisOnTop"); | ||||||
|     tr("mixWithPriorPage"); |     tr("mixWithPriorPage"); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user