diff --git a/limereport/items/images/pie_chart2.png b/limereport/items/images/pie_chart2.png
new file mode 100644
index 0000000..f4f788d
Binary files /dev/null and b/limereport/items/images/pie_chart2.png differ
diff --git a/limereport/items/items.qrc b/limereport/items/items.qrc
index 86b8d74..44004cd 100644
--- a/limereport/items/items.qrc
+++ b/limereport/items/items.qrc
@@ -33,5 +33,6 @@
images/GroupFooter16.png
images/GroupHeader16.png
images/ReportPage16.png
+ images/pie_chart2.png
diff --git a/limereport/items/lrchartitem.cpp b/limereport/items/lrchartitem.cpp
new file mode 100644
index 0000000..28c2218
--- /dev/null
+++ b/limereport/items/lrchartitem.cpp
@@ -0,0 +1,1062 @@
+#include "lrchartitem.h"
+#include
+#include
+
+#include "lrdesignelementsfactory.h"
+#include "lrchartitemeditor.h"
+#include "lrdatasourcemanager.h"
+#include "lrpagedesignintf.h"
+#include "lrreportengine_p.h"
+#include "lrdatadesignintf.h"
+
+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()
+{
+ int red = (qrand()%(256 - 1)) + 1;
+ int green = (qrand()%(256 - 1)) + 1;
+ int blue = (qrand()%(256 - 1)) + 1;;
+ return QColor(red,green,blue);
+}
+
+QColor color_map[39] = {
+ QColor(51,102,204), QColor(220,57,18), QColor(225, 153, 0), QColor(16, 150, 24), QColor(153,0,153),
+ QColor(0,153,198), QColor(221, 68, 119),
+ QColor(255,0,0), QColor(0,0,139), QColor(0,205,0), QColor(233,30,99), QColor(255,255,0), QColor(244,67,54),
+ QColor(156,39,176), QColor(103,58,183), QColor(63,81,181), QColor(33,153,243),
+ QColor(0,150,136), QColor(78,175,80), QColor(139,195,74), QColor(205,228,57),
+ QColor(0,139,0), QColor(0,0,255), QColor(255,235,59), QColor(255,193,7),
+ QColor(255,152,0), QColor(255,87,34), QColor(121,85,72), QColor(158,158,158),
+ QColor(96,125,139), QColor(241,153,185), QColor(64,64,64),
+ QColor(188,229,218), QColor(139,0,0), QColor(139,139,0), QColor(171, 130, 255),
+ QColor(139, 123, 139), QColor(255, 0, 255), QColor(139, 69, 19)
+ };
+//QColor color_map1[55] = {
+// QColor(245,147,51), QColor(244,89,73), QColor(0,142,195), QColor(1,107,159),
+// QColor(242,219,127), QColor(1,127,111), QColor(143,149,166), QColor(1,173,235),
+// QColor(35,63,142), QColor(121,78,38), QColor(254,195,115), QColor(237,38,110),
+// QColor(240,102,125), QColor(92,97,98), QColor(0,101,94), QColor(239,59,31),
+// QColor(1,73,133), QColor(0,89,151), QColor(237,27,35), QColor(219,3,107),
+// QColor(0,173,239), QColor(167,138,117), QColor(0,134,124), QColor(0,110,68),
+// QColor(242,199,17), QColor(247,168,114), QColor(65,174,74), QColor(1,142,76),
+// QColor(1,82,165), QColor(0,111,134), QColor(69,128,43), QColor(254,222,86),
+// QColor(152,262,59), QColor(237,0,137), QColor(188,26,141), QColor(0,57,115),
+// QColor(150,180,127), QColor(146,154,160), QColor(1,82,132), QColor(23,97,134),
+// QColor(95,194,171), QColor(0,114,187), QColor(200,133,183), QColor(81,33,127),
+// QColor(0,254,0), QColor(0,0,254), QColor(254,254,0),
+// QColor(254,0,254),QColor(0,254,254), QColor(0,80,0), QColor(80,0,0),
+// QColor(0,0,80), QColor(80,80,0), QColor(80,0,80),
+// QColor(0,80,80),
+//};
+
+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();
+ result->setName(name());
+ result->setLabelsColumn(labelsColumn());
+ result->setValuesColumn(valuesColumn());
+ result->setColor(color());
+ return result;
+}
+
+void SeriesItem::fillSeriesData(IDataSource *dataSource)
+{
+ 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;
+}
+
+ChartItem::ChartItem(QObject *owner, QGraphicsItem *parent)
+ : ItemDesignIntf(xmlTag, owner, parent), m_legendBorder(true),
+ m_legendAlign(LegendAlignCenter), m_titleAlign(TitleAlignCenter),
+ m_chartType(Pie), m_labelsField("")
+{
+ 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)fontMetrics().height()+borderMargin*2):
+ (maxTitleHeight)):0;
+
+ QRectF titleRect = QRectF(borderMargin,borderMargin,rect().width()-borderMargin*2,titleOffset);
+ QRectF legendRect = m_chart->calcChartLegendRect(painter->font(), rect(), false, borderMargin, titleOffset);
+ QRectF diagramRect = rect().adjusted(borderMargin,titleOffset+borderMargin,
+ -(legendRect.width()+borderMargin*2),-borderMargin);
+
+ paintChartTitle(painter, titleRect);
+ m_chart->paintChartLegend(painter,legendRect);
+ 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 )
+{
+ if (dataManager && dataManager->dataSource(m_datasource)){
+ IDataSource* ds = dataManager->dataSource(m_datasource);
+ foreach (SeriesItem* series, m_series) {
+ series->fillSeriesData(ds);
+ }
+ 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);
+ editor->setAttribute(Qt::WA_DeleteOnClose);
+ return editor;
+}
+
+QList ChartItem::labels() const
+{
+ return m_labels;
+}
+
+void ChartItem::setLabels(const QList &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;
+ }
+ 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);
+ while ((fm.height()>titleRect.height() || fm.width(m_title)>titleRect.width())
+ && 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 &ChartItem::series()
+{
+ return m_series;
+}
+
+void ChartItem::setSeries(const QList &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<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);
+ }
+}
+
+void PieChart::drawPercent(QPainter *painter, QRectF chartRect, qreal startAngle, qreal angle)
+{
+ painter->save();
+
+ QPointF center(chartRect.left()+chartRect.width()/2,chartRect.top()+chartRect.height()/2);
+ qreal percent = angle/3.6;
+ qreal radAngle = qDegreesToRadians(angle/2+startAngle);
+ qreal radius = painter->fontMetrics().width("99,9%");
+ qreal border = chartRect.height()*0.02;
+ qreal length = (chartRect.height())/2-(radius/2+border);
+ qreal x,y;
+ x = length*qCos(radAngle);
+ y = length*qSin(radAngle);
+ QPointF endPoint(center.x()+x,center.y()-y);
+ painter->setPen(Qt::white);
+ QRectF textRect(endPoint.x()-(radius/2),endPoint.y()-(radius/2),radius,radius);
+
+ qreal arcLength = 3.14 * length * angle / 180;
+ if (arcLength >= radius)
+ painter->drawText(textRect,Qt::AlignCenter,QString::number(percent,'f',1)+"%");
+ painter->restore();
+
+}
+
+void PieChart::paintChart(QPainter *painter, QRectF chartRect)
+{
+ painter->save();
+ QPen pen(Qt::white);
+ pen.setWidthF(2);
+ painter->setPen(pen);
+
+ QBrush brush(Qt::transparent);
+ painter->setBrush(brush);
+ painter->setBackground(QBrush(Qt::NoBrush));
+
+ QRectF tmpRect = chartRect;
+ if (chartRect.height()>chartRect.width()){
+ tmpRect.setHeight(chartRect.width());
+ tmpRect.adjust(0,(chartRect.bottom()-tmpRect.bottom())/2,
+ 0,(chartRect.bottom()-tmpRect.bottom())/2);
+ } else {
+ tmpRect.setWidth(chartRect.height());
+ }
+
+ chartRect = tmpRect;
+ painter->drawRect(chartRect);
+
+ if (!m_chartItem->series().isEmpty()&&!m_chartItem->series().at(0)->data()->values().isEmpty()){
+ SeriesItem* si = m_chartItem->series().at(0);
+ qreal sum = 0;
+ foreach(qreal value, si->data()->values()){
+ sum+=value;
+ }
+ qreal onePercent = sum / 100;
+ qreal currentDegree = 0;
+ int currentColor = 0;
+ for(int i=0; idata()->values().count();++i){
+ qreal value = si->data()->values().at(i);
+ qreal sectorDegree = (value/onePercent)*3.6;
+ painter->setBrush(si->data()->colors().at(i));
+ painter->drawPie(chartRect,currentDegree*16,sectorDegree*16);
+ drawPercent(painter, chartRect, currentDegree, sectorDegree);
+ currentDegree += sectorDegree;
+ currentColor++;
+ }
+ } else {
+ painter->setBrush(color_map[0]);
+ painter->drawPie(chartRect,0,260*16);
+ drawPercent(painter, chartRect, 0, 260);
+ painter->setBrush(color_map[1]);
+ painter->drawPie(chartRect,260*16,40*16);
+ drawPercent(painter, chartRect, 260, 40);
+ painter->setBrush(color_map[2]);
+ painter->drawPie(chartRect,300*16,60*16);
+ drawPercent(painter, chartRect, 300, 60);
+ }
+
+ pen.setWidthF(1);
+ pen.setColor(Qt::gray);
+ painter->setPen(pen);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(chartRect);
+ painter->restore();
+}
+
+void PieChart::paintChartLegend(QPainter *painter, QRectF legendRect)
+{
+ prepareLegendToPaint(legendRect, painter);
+
+ int indicatorSize = painter->fontMetrics().height()/2;
+ painter->setRenderHint(QPainter::Antialiasing,false);
+
+ if (m_chartItem->drawLegendBorder())
+ painter->drawRect(legendRect);
+
+ painter->setRenderHint(QPainter::Antialiasing,true);
+ QRectF indicatorsRect = legendRect.adjusted(painter->fontMetrics().height()/2,painter->fontMetrics().height()/2,0,0);
+
+ if (!m_chartItem->series().isEmpty() && !m_chartItem->series().at(0)->data()->labels().isEmpty()){
+ qreal cw = 0;
+ SeriesItem* si = m_chartItem->series().at(0);
+ for (int i=0;idata()->labels().count();++i){
+ QString label = si->data()->labels().at(i);
+ painter->setPen(Qt::black);
+ painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label);
+ painter->setPen(si->data()->colors().at(i));
+ painter->setBrush(si->data()->colors().at(i));
+ painter->drawEllipse(
+ indicatorsRect.adjusted(
+ 0,
+ cw+indicatorSize/2,
+ -(indicatorsRect.width()-indicatorSize),
+ -(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2))
+ )
+ );
+ cw += painter->fontMetrics().height();
+ }
+ } else {
+ qreal cw = 0;
+ for (int i=0;isetPen(Qt::black);
+ painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label);
+ painter->setBrush(color_map[i]);
+ painter->setPen(color_map[i]);
+ painter->drawEllipse(
+ indicatorsRect.adjusted(
+ 0,
+ cw+indicatorSize/2,
+ -(indicatorsRect.width()-indicatorSize),
+ -(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2))
+ )
+ );
+ cw += painter->fontMetrics().height();
+ }
+
+ }
+}
+
+QSizeF PieChart::calcChartLegendSize(const QFont &font)
+{
+ QFontMetrics fm(font);
+
+ qreal cw = 0;
+ qreal maxWidth = 0;
+
+ if (!m_chartItem->series().isEmpty() && !m_chartItem->series().at(0)->data()->labels().isEmpty()){
+ SeriesItem* si = m_chartItem->series().at(0);
+ foreach(QString label, si->data()->labels()){
+ cw += fm.height();
+ if (maxWidthfontMetrics().width(QString::number(delta))+4;
+}
+
+qreal VerticalBarChart::valuesVMargin(QPainter *painter)
+{
+ return painter->fontMetrics().height();
+}
+
+QRectF VerticalBarChart::labelsRect(QPainter *painter, QRectF labelsRect)
+{
+ qreal maxWidth = 0;
+
+ foreach (QString label, m_chartItem->labels()) {
+ if (painter->fontMetrics().width(label)>maxWidth)
+ maxWidth = painter->fontMetrics().width(label);
+ }
+
+ if (maxWidth+vPadding(m_chartItem->rect())> labelsRect.height())
+ return labelsRect;
+ else
+ return labelsRect.adjusted(0,(labelsRect.height()-(maxWidth+vPadding(m_chartItem->rect()))),0,0);
+}
+
+void VerticalBarChart::paintChart(QPainter *painter, QRectF chartRect)
+{
+ QRectF calcRect = labelsRect(painter, chartRect.adjusted(
+ hPadding(chartRect)*2+valuesHMargin(painter),
+ chartRect.height()*0.5,
+ -(hPadding(chartRect)*2),
+ -vPadding(chartRect)
+ ));
+
+ qreal barsShift = calcRect.height();
+ paintVerticalGrid(painter, chartRect.adjusted(
+ hPadding(chartRect),
+ vPadding(chartRect)+valuesVMargin(painter),
+ -hPadding(chartRect),-(vPadding(chartRect)+barsShift) ));
+
+ paintVerticalBars(painter, chartRect.adjusted(
+ hPadding(chartRect)*2+valuesHMargin(painter),
+ vPadding(chartRect)+valuesVMargin(painter),
+ -(hPadding(chartRect)*2),
+ -(vPadding(chartRect)+barsShift) ));
+ paintLabels(painter,calcRect);
+}
+
+
+void VerticalBarChart::paintVerticalGrid(QPainter *painter, QRectF gridRect)
+{
+ int delta = int(maxValue()-minValue());
+ delta = genNextValue(delta);
+
+ painter->setRenderHint(QPainter::Antialiasing,false);
+ qreal vStep = gridRect.height() / 4;
+
+ for (int i=0;i<5;i++){
+ painter->drawText(QRectF(gridRect.bottomLeft()-QPointF(0,vStep*i+painter->fontMetrics().height()),
+ QSizeF(valuesHMargin(painter),painter->fontMetrics().height())),
+ QString::number(minValue()+i*delta/4));
+ painter->drawLine(gridRect.bottomLeft()-QPointF(-valuesHMargin(painter),vStep*i),
+ gridRect.bottomRight()-QPointF(0,vStep*i));
+ }
+
+ painter->setRenderHint(QPainter::Antialiasing,true);
+}
+
+
+
+void VerticalBarChart::paintVerticalBars(QPainter *painter, QRectF barsRect)
+{
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing,false);
+ int delta = int(maxValue()-minValue());
+ delta = genNextValue(delta);
+
+ qreal vStep = barsRect.height() / delta;
+ qreal hStep = (barsRect.width() / valuesCount()) / seriesCount();
+ qreal topShift = (delta - (maxValue()-minValue())) * vStep +barsRect.top();
+
+ if (!m_chartItem->series().isEmpty() && !m_chartItem->series().at(0)->data()->labels().isEmpty()){
+ int curSeries = 0;
+ foreach (SeriesItem* series, m_chartItem->series()) {
+ qreal curHOffset = curSeries*hStep+barsRect.left();
+ painter->setBrush(series->color());
+ foreach (qreal value, series->data()->values()) {
+ painter->drawRect(QRectF(curHOffset, maxValue()*vStep+topShift, hStep, -value*vStep));
+ curHOffset+=hStep*seriesCount();
+ }
+ curSeries++;
+ }
+ } else {
+ qreal curHOffset = barsRect.left();
+ int curColor = 0;
+ for (int i=0; i<9; ++i){
+ if (curColor==3) curColor=0;
+ painter->setBrush(color_map[curColor]);
+ painter->drawRect(QRectF(curHOffset, maxValue()*vStep+barsRect.top(), hStep, -designValues()[i]*vStep));
+ curHOffset+=hStep;
+ curColor++;
+ }
+ }
+ painter->restore();
+}
+
+
+
+void VerticalBarChart::paintLabels(QPainter *painter, QRectF labelsRect)
+{
+ painter->save();
+ qreal hStep = (labelsRect.width() / valuesCount());
+ int curLabel = 0;
+
+ if (!m_chartItem->labels().isEmpty()){
+ 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);
+ curLabel++;
+ painter->translate(0,hStep);
+ }
+ painter->rotate(-270);
+ }
+ painter->restore();
+}
+
+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()
+{
+ if (m_chartItem->itemMode()==DesignMode) return 40;
+ 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()
+{
+ if (m_chartItem->itemMode()==DesignMode) return 0;
+ qreal minValue = 0;
+ foreach(SeriesItem* series, m_chartItem->series()){
+ foreach(qreal value, series->data()->values()){
+ if (valueitemMode()==DesignMode) return 3;
+ return (m_chartItem->series().isEmpty())?(0):(m_chartItem->series().at(0)->data()->labels().count());
+}
+
+int AbstractSeriesChart::seriesCount()
+{
+ if (m_chartItem->itemMode()==DesignMode) return 3;
+ 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();
+ if (maxWidthname()))
+ maxWidth = fm.width(series->name())+10;
+ }
+ } else {
+ foreach(QString label, m_designLabels){
+ cw += fm.height();
+ if (maxWidthfontMetrics().width(QString::number(delta))+4;
+}
+
+qreal HorizontalBarChart::valuesVMargin(QPainter *painter)
+{
+ return painter->fontMetrics().height();
+}
+
+void HorizontalBarChart::paintChart(QPainter *painter, QRectF chartRect)
+{
+ QRectF calcRect = labelsRect(painter, chartRect.adjusted(
+ hPadding(chartRect),
+ vPadding(chartRect)*2,
+ -(chartRect.width()*0.5),
+ -(vPadding(chartRect)*2+valuesVMargin(painter))
+ ));
+
+ qreal barsShift = calcRect.width();
+
+ paintHorizontalGrid(painter, chartRect.adjusted(
+ hPadding(chartRect)+barsShift,
+ vPadding(chartRect),
+ -(hPadding(chartRect)),-vPadding(chartRect)));
+ paintHorizontalBars(painter, chartRect.adjusted(
+ hPadding(chartRect)+barsShift,
+ vPadding(chartRect)*2,
+ -(hPadding(chartRect)),
+ -(vPadding(chartRect)*2) ));
+
+ paintLabels(painter,calcRect);
+}
+
+void HorizontalBarChart::paintHorizontalGrid(QPainter *painter, QRectF gridRect)
+{
+ painter->save();
+ int delta = int(maxValue()-minValue());
+ delta = genNextValue(delta);
+
+ painter->setRenderHint(QPainter::Antialiasing,false);
+ qreal hStep = (gridRect.width()-painter->fontMetrics().width(QString::number(maxValue()))) / 4;
+
+ painter->setFont(adaptValuesFont(hStep-4,painter->font()));
+
+ for (int i=0;i<5;i++){
+ painter->drawText(QRectF(gridRect.left()+4+hStep*i,gridRect.bottom()-painter->fontMetrics().height(),
+ hStep,painter->fontMetrics().height()),
+ QString::number(minValue()+i*delta/4));
+ painter->drawLine( gridRect.left()+hStep*i, gridRect.bottom(),
+ gridRect.left()+hStep*i, gridRect.top());
+
+ }
+ painter->restore();
+}
+
+void HorizontalBarChart::paintHorizontalBars(QPainter *painter, QRectF barsRect)
+{
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing,false);
+ int delta = int(maxValue()-minValue());
+ delta = genNextValue(delta);
+
+ qreal vStep = (barsRect.height()-painter->fontMetrics().height()) / valuesCount() / seriesCount();
+ qreal hStep = (barsRect.width()-painter->fontMetrics().width(QString::number(maxValue()))) / delta;
+
+ if (!m_chartItem->series().isEmpty() && !m_chartItem->series().at(0)->data()->labels().isEmpty()){
+ int curSeries = 0;
+ foreach (SeriesItem* series, m_chartItem->series()) {
+ qreal curVOffset = curSeries*vStep+barsRect.top();
+ painter->setBrush(series->color());
+ foreach (qreal value, series->data()->values()) {
+ painter->drawRect(QRectF((-minValue()*hStep)+barsRect.left(), curVOffset, value*hStep, vStep));
+ curVOffset+=vStep*seriesCount();
+ }
+ curSeries++;
+ }
+ } else {
+ qreal curVOffset = barsRect.top();
+ int curColor = 0;
+ for (int i=0; i<9; ++i){
+ if (curColor==3) curColor=0;
+ painter->setBrush(color_map[curColor]);
+ painter->drawRect(QRectF(barsRect.left(), curVOffset, designValues()[i]*hStep, vStep));
+ curVOffset+=vStep;
+ curColor++;
+ }
+ }
+ painter->restore();
+}
+
+QRectF HorizontalBarChart::labelsRect(QPainter *painter, QRectF labelsRect)
+{
+ qreal maxWidth = 0;
+
+ foreach (QString label, m_chartItem->labels()) {
+ if (painter->fontMetrics().width(label)>maxWidth)
+ maxWidth = painter->fontMetrics().width(label);
+ }
+
+ if (maxWidth+hPadding(m_chartItem->rect())*2> labelsRect.width())
+ return labelsRect;
+ else
+ return labelsRect.adjusted(0,0,-(labelsRect.width()-(maxWidth+hPadding(m_chartItem->rect())*2)),0);
+}
+
+QFont HorizontalBarChart::adaptLabelsFont(QRectF rect, QFont font)
+{
+ QString maxWord;
+ QFontMetrics fm(font);
+
+ foreach(QString label, m_chartItem->labels()){
+ foreach (QString currentWord, label.split(QRegExp("\\W+"))){
+ if (fm.width(maxWord)rect.width() && tmpFont.pixelSize()>1){
+ tmpFont.setPixelSize(tmpFont.pixelSize()-1);
+ QFontMetricsF tmpFM(tmpFont);
+ curWidth = tmpFM.width(maxWord);
+ }
+ return tmpFont;
+}
+
+QFont HorizontalBarChart::adaptValuesFont(qreal width, QFont font)
+{
+ QString strValue = QString::number(maxValue());
+ QFont tmpFont = font;
+ QScopedPointer fm(new QFontMetricsF(tmpFont));
+ qreal curWidth = fm->width(strValue);
+ while (curWidth>width && tmpFont.pixelSize()>1){
+ tmpFont.setPixelSize(tmpFont.pixelSize()-1);
+ fm.reset(new QFontMetricsF(tmpFont));
+ curWidth = fm->width(strValue);
+ }
+ return tmpFont;
+}
+
+void HorizontalBarChart::paintLabels(QPainter *painter, QRectF labelsRect)
+{
+ painter->save();
+ painter->setFont(adaptLabelsFont(labelsRect.adjusted(0,0,-hPadding(m_chartItem->rect()),0),
+ painter->font()));
+ qreal vStep = (labelsRect.height() / valuesCount());
+ int curLabel = 0;
+
+ 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);
+
+ curLabel++;
+ }
+ }
+ painter->restore();
+}
+
+qreal AbstractBarChart::hPadding(QRectF chartRect)
+{
+ return (chartRect.width()*0.02);
+}
+
+qreal AbstractBarChart::vPadding(QRectF chartRect)
+{
+ return (chartRect.height()*0.02);
+}
+
+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();
+ }
+ } else {
+ qreal cw = 0;
+ for (int i=0;idrawText(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();
+ }
+
+ }
+}
+
+} // namespace LimeReport
diff --git a/limereport/items/lrchartitem.h b/limereport/items/lrchartitem.h
new file mode 100644
index 0000000..c89ea76
--- /dev/null
+++ b/limereport/items/lrchartitem.h
@@ -0,0 +1,208 @@
+#ifndef LRCHARTITEM_H
+#define LRCHARTITEM_H
+#include "lritemdesignintf.h"
+
+namespace LimeReport{
+
+QColor generateColor();
+extern QColor color_map[39];
+
+class IDataSource;
+
+class SeriesItemData : public QObject{
+ Q_OBJECT
+public:
+ QList& values(){ return m_values;}
+ QList& labels(){ return m_labels;}
+ QList& colors() { return m_colors;}
+private:
+ QList m_values;
+ QList m_labels;
+ QList m_colors;
+};
+
+class SeriesItem : public QObject{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString valuesColumn READ valuesColumn WRITE setValuesColumn )
+ Q_PROPERTY(QString labelsColumn READ labelsColumn WRITE setLabelsColumn )
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+public:
+ SeriesItem(QObject* parent = 0):QObject(parent){}
+ QString name() const;
+ void setName(const QString &name);
+ QString valuesColumn() const;
+ void setValuesColumn(const QString &valuesColumn);
+ QString labelsColumn() const;
+ void setLabelsColumn(const QString &labelsColumn);
+ SeriesItem* clone();
+ void fillSeriesData(IDataSource* dataSource);
+ SeriesItemData* data(){ return &m_data;}
+ QColor color() const;
+ void setColor(const QColor &color);
+private:
+ QString m_name;
+ QString m_valuesColumn;
+ QString m_labelsColumn;
+ SeriesItemData m_data;
+ QColor m_color;
+};
+
+class ChartItem;
+
+class AbstractChart {
+public:
+ AbstractChart(ChartItem* chartItem);
+ virtual ~AbstractChart(){}
+ virtual void paintChart(QPainter *painter, QRectF rect) = 0;
+ virtual void paintChartLegend(QPainter *painter, QRectF legendRect) =0;
+ virtual QSizeF calcChartLegendSize(const QFont &font) = 0;
+ virtual QRectF calcChartLegendRect(const QFont& font, const QRectF& parentRect, bool takeAllRect, qreal borderMargin, qreal titleOffset);
+protected:
+ virtual void prepareLegendToPaint(QRectF& legendRect, QPainter *painter);
+protected:
+ ChartItem* m_chartItem;
+ QList m_designLabels;
+};
+
+class AbstractSeriesChart: public AbstractChart{
+public:
+ AbstractSeriesChart(ChartItem* chartItem);
+protected:
+ qreal maxValue();
+ qreal minValue();
+ int valuesCount();
+ int seriesCount();
+ QSizeF calcChartLegendSize(const QFont &font);
+ qreal* designValues(){ return m_designValues;}
+private:
+ qreal m_designValues [9];
+};
+
+class PieChart : public AbstractChart{
+public:
+ PieChart(ChartItem* chartItem):AbstractChart(chartItem){}
+ QSizeF calcChartLegendSize(const QFont &font);
+ void paintChart(QPainter *painter, QRectF chartRect);
+ void paintChartLegend(QPainter *painter, QRectF legendRect);
+protected:
+ void drawPercent(QPainter *painter, QRectF chartRect, qreal startAngle, qreal angle);
+};
+
+class AbstractBarChart: public AbstractSeriesChart{
+public:
+ AbstractBarChart(ChartItem* chartItem):AbstractSeriesChart(chartItem){}
+ qreal hPadding(QRectF chartRect);
+ qreal vPadding(QRectF chartRect);
+ void paintChartLegend(QPainter *painter, QRectF legendRect);
+};
+
+class HorizontalBarChart: public AbstractBarChart{
+public:
+ HorizontalBarChart(ChartItem* chartItem):AbstractBarChart(chartItem){}
+ qreal valuesHMargin(QPainter *painter);
+ qreal valuesVMargin(QPainter *painter);
+ void paintChart(QPainter *painter, QRectF chartRect);
+ void paintHorizontalGrid(QPainter *painter, QRectF gridRect);
+ void paintHorizontalBars(QPainter *painter, QRectF barsRect);
+ QRectF labelsRect(QPainter* painter, QRectF labelsRect);
+ void paintLabels(QPainter *painter, QRectF labelsRect);
+protected:
+ QFont adaptLabelsFont(QRectF rect, QFont font);
+ QFont adaptValuesFont(qreal width, QFont font);
+};
+
+class VerticalBarChart: public AbstractBarChart{
+public:
+ VerticalBarChart(ChartItem* chartItem):AbstractBarChart(chartItem){}
+ qreal valuesHMargin(QPainter *painter);
+ qreal valuesVMargin(QPainter *painter);
+ QRectF labelsRect(QPainter* painter, QRectF labelsRect);
+ void paintChart(QPainter *painter, QRectF chartRect);
+ void paintVerticalGrid(QPainter *painter, QRectF gridRect);
+ void paintVerticalBars(QPainter *painter, QRectF barsRect);
+ void paintLabels(QPainter *painter, QRectF labelsRect);
+};
+
+class ChartItem : public LimeReport::ItemDesignIntf
+{
+ Q_OBJECT
+ Q_ENUMS(LegendAlign)
+ Q_ENUMS(TitleAlign)
+ Q_ENUMS(ChartType)
+ Q_PROPERTY(ACollectionProperty series READ fakeCollectionReader)
+ Q_PROPERTY(QString datasource READ datasource WRITE setDatasource)
+ Q_PROPERTY(QString chartTitle READ chartTitle WRITE setChartTitle)
+ Q_PROPERTY(bool drawLegendBorder READ drawLegendBorder WRITE setDrawLegendBorder)
+ Q_PROPERTY(LegendAlign legendAlign READ legendAlign WRITE setLegendAlign)
+ Q_PROPERTY(TitleAlign titleAlign READ titleAlign WRITE setTitleAlign)
+ Q_PROPERTY(ChartType chartType READ chartType WRITE setChartType)
+ Q_PROPERTY(QString labelsField READ labelsField WRITE setLabelsField)
+ friend class AbstractChart;
+public:
+
+ enum LegendAlign{LegendAlignTop,LegendAlignCenter,LegendAlignBottom};
+ enum TitleAlign{TitleAlignLeft, TitleAlignCenter, TitleAlignRight};
+ enum ChartType{Pie, VerticalBar, HorizontalBar};
+
+ ChartItem(QObject* owner, QGraphicsItem* parent);
+ ~ChartItem();
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+ QList &series();
+ void setSeries(const QList &series);
+ bool isSeriesExists(const QString& name);
+
+ QString datasource() const;
+ void setDatasource(const QString &datasource);
+
+ QString chartTitle() const;
+ void setChartTitle(const QString &chartTitle);
+
+ bool drawLegendBorder() const;
+ void setDrawLegendBorder(bool drawLegendBorder);
+
+ LegendAlign legendAlign() const;
+ void setLegendAlign(const LegendAlign &legendAlign);
+
+ TitleAlign titleAlign() const;
+ void setTitleAlign(const TitleAlign &titleAlign);
+
+ ChartType chartType() const;
+ void setChartType(const ChartType &chartType);
+
+ QString labelsField() const;
+ void setLabelsField(const QString &labelsField);
+
+ QList labels() const;
+ void setLabels(const QList &labels);
+
+protected:
+ void paintChartTitle(QPainter* painter, QRectF titleRect);
+ virtual BaseDesignIntf* createSameTypeItem(QObject *owner, QGraphicsItem *parent);
+ //ICollectionContainer
+ QObject* createElement(const QString& collectionName,const QString& elementType);
+ int elementsCount(const QString& collectionName);
+ QObject* elementAt(const QString& collectionName,int index);
+ void collectionLoadFinished(const QString& collectionName){Q_UNUSED(collectionName)}
+ void updateItemSize(DataSourceManager *dataManager, RenderPass, int);
+ void fillLabels(IDataSource* dataSource);
+ QWidget* defaultEditor();
+
+private:
+ QList m_series;
+// QList< QPointer > m_series;
+ QString m_datasource;
+ QPixmap m_chartImage;
+ QString m_title;
+ AbstractChart* m_chart;
+ bool m_legendBorder;
+ LegendAlign m_legendAlign;
+ TitleAlign m_titleAlign;
+ ChartType m_chartType;
+ QString m_labelsField;
+ QList m_labels;
+};
+
+} //namespace LimeReport
+#endif // LRCHARTITEM_H
diff --git a/limereport/items/lrchartitemeditor.cpp b/limereport/items/lrchartitemeditor.cpp
new file mode 100644
index 0000000..cfb9761
--- /dev/null
+++ b/limereport/items/lrchartitemeditor.cpp
@@ -0,0 +1,249 @@
+#include "lrchartitemeditor.h"
+#include "ui_lrchartitemeditor.h"
+#include "lrchartitem.h"
+#include "lrpagedesignintf.h"
+#include
+
+ChartItemEditor::ChartItemEditor(LimeReport::ChartItem *item, LimeReport::PageDesignIntf *page, QSettings *settings, QWidget *parent):
+ QWidget(parent), ui(new Ui::ChartItemEditor), m_charItem(item), m_page(page),
+ m_settings(settings), m_ownedSettings(false), m_isReadingSetting(false)
+{
+ ui->setupUi(this);
+ QHBoxLayout* colorLayout = new QHBoxLayout();
+ colorLayout->setMargin(0);
+ m_colorButton = new QToolButton();
+ m_colorButton->setText("...");
+ m_colorButton->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
+ m_colorIndicator = new ColorIndicator();
+ m_colorIndicator->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
+ ui->colorWidget->setLayout(colorLayout);
+ colorLayout->addWidget(m_colorIndicator);
+ colorLayout->addWidget(m_colorButton);
+ colorLayout->insertStretch(0);
+ readSetting();
+ init();
+
+ connect(m_colorButton, SIGNAL(clicked(bool)), this, SLOT(slotChangeSeriesColor()));
+}
+
+ChartItemEditor::~ChartItemEditor()
+{
+#ifdef Q_OS_WIN
+ writeSetting();
+#endif
+#ifdef Q_OS_MAC
+ writeSetting();
+#endif
+ delete ui;
+}
+
+QSettings* ChartItemEditor::settings()
+{
+ if (m_settings){
+ return m_settings;
+ } else {
+ m_settings = new QSettings("LimeReport",QApplication::applicationName());
+ m_ownedSettings = true;
+ return m_settings;
+ }
+}
+
+void ChartItemEditor::readSetting()
+{
+ if (settings()==0) return;
+
+ m_isReadingSetting = true;
+
+ settings()->beginGroup("ChartItemEditor");
+ QVariant v = settings()->value("Geometry");
+ if (v.isValid()){
+ restoreGeometry(v.toByteArray());
+ }
+ v = settings()->value("State");
+ if (v.isValid()){
+ ui->splitter->restoreState(v.toByteArray());
+ }
+
+ settings()->endGroup();
+
+ m_isReadingSetting = false;
+}
+
+void ChartItemEditor::writeSetting()
+{
+ if (settings()!=0){
+ settings()->beginGroup("ChartItemEditor");
+ settings()->setValue("Geometry",saveGeometry());
+ settings()->setValue("State",ui->splitter->saveState());
+ settings()->endGroup();
+ }
+}
+
+void ChartItemEditor::rebuildTable()
+{
+ ui->tableWidget->clearContents();
+ ui->tableWidget->setRowCount(m_charItem->series().count());
+ for( int i=0;iseries().count();++i){
+ QTableWidgetItem* newRow = new QTableWidgetItem(m_charItem->series().at(i)->name());
+ ui->tableWidget->setItem(i,0,newRow);
+ }
+}
+
+void ChartItemEditor::init()
+{
+ m_initing = true;
+
+ ui->tableWidget->setColumnCount(1);
+ ui->tableWidget->setRowCount(m_charItem->series().count());
+ ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
+ ui->tableWidget->setHorizontalHeaderItem(0,new QTableWidgetItem("Series name"));
+
+ rebuildTable();
+
+ if (!m_charItem->datasource().isEmpty()){
+ if (m_page && m_page->datasourceManager()){
+ LimeReport::IDataSource* ds = m_page->datasourceManager()->dataSource(m_charItem->datasource());
+ if (ds){
+ for (int i=0;icolumnCount();++i){
+ ui->valuesFieldComboBox->addItem(ds->columnNameByIndex(i));
+ ui->labelsFieldComboBox->addItem(ds->columnNameByIndex(i));
+ }
+ }
+ }
+
+ }
+ ui->labelsFieldComboBox->setCurrentText(m_charItem->labelsField());
+ if (!m_charItem->series().isEmpty()){
+ enableSeriesEditor();
+ ui->tableWidget->selectRow(0);
+ } else {
+ disableSeriesEditor();
+ }
+
+ m_initing = false;
+}
+
+void ChartItemEditor::enableSeriesEditor()
+{
+ ui->seriesNameLineEdit->setEnabled(true);
+ ui->valuesFieldComboBox->setEnabled(true);
+ m_colorButton->setEnabled(true);
+ m_colorIndicator->setEnabled(true);
+}
+
+void ChartItemEditor::disableSeriesEditor()
+{
+ ui->seriesNameLineEdit->setText("");
+ ui->seriesNameLineEdit->setDisabled(true);
+ ui->valuesFieldComboBox->setDisabled(true);
+ m_colorButton->setDisabled(true);
+ m_colorIndicator->setDisabled(true);
+ ui->valuesFieldComboBox->setCurrentText("");
+}
+
+LimeReport::SeriesItem *ChartItemEditor::currentSeries()
+{
+ int curRow = ui->tableWidget->currentRow();
+ if ((curRow>-1) && !m_charItem->series().isEmpty() && m_charItem->series().count()>curRow){
+ return m_charItem->series().at(curRow);
+ }
+ return 0;
+}
+
+void ChartItemEditor::resizeEvent(QResizeEvent *)
+{
+#ifdef Q_OS_UNIX
+ writeSetting();
+#endif
+}
+
+void ChartItemEditor::moveEvent(QMoveEvent *)
+{
+#ifdef Q_OS_UNIX
+ writeSetting();
+#endif
+}
+
+void ChartItemEditor::on_splitter_splitterMoved(int , int )
+{
+#ifdef Q_OS_UNIX
+ writeSetting();
+#endif
+}
+
+
+void ChartItemEditor::on_pbOk_clicked()
+{
+ close();
+}
+
+void ChartItemEditor::slotAddSeries()
+{
+ LimeReport::SeriesItem* series = new LimeReport::SeriesItem();
+ int curSeriesNumber = m_charItem->series().count();
+ while (m_charItem->isSeriesExists("Series"+QString::number(curSeriesNumber))) curSeriesNumber++;
+ series->setName("Series"+QString::number(curSeriesNumber));
+ series->setValuesColumn("");
+ series->setLabelsColumn("");
+ series->setColor((m_charItem->series().count()<32)?LimeReport::color_map[m_charItem->series().count()]:LimeReport::generateColor());
+ m_charItem->series().append(series);
+ ui->tableWidget->setRowCount(m_charItem->series().count());
+ ui->tableWidget->setItem(m_charItem->series().count()-1, 0, new QTableWidgetItem(series->name()));
+ ui->tableWidget->selectRow(m_charItem->series().count()-1);
+ ui->valuesFieldComboBox->setCurrentText("");
+}
+
+void ChartItemEditor::slotDeleteSeries()
+{
+ QList itemsToRemove;
+ foreach(QModelIndex index,ui->tableWidget->selectionModel()->selectedRows()){
+ itemsToRemove.append(m_charItem->series().at(index.row()));
+ };
+ foreach (LimeReport::SeriesItem* series, itemsToRemove){
+ m_charItem->series().removeOne(series);
+ delete series;
+ }
+ rebuildTable();
+ disableSeriesEditor();
+}
+
+void ChartItemEditor::on_tableWidget_itemSelectionChanged()
+{
+ if (ui->tableWidget->selectionModel()->hasSelection()){
+ LimeReport::SeriesItem* series = m_charItem->series().at(ui->tableWidget->selectionModel()->currentIndex().row());
+ ui->seriesNameLineEdit->setText(series->name());
+ ui->valuesFieldComboBox->setCurrentText(series->valuesColumn());
+ m_colorIndicator->setColor(series->color());
+ enableSeriesEditor();
+ }
+}
+
+void ChartItemEditor::on_seriesNameLineEdit_textChanged(const QString &arg1)
+{
+ if (currentSeries()){
+ currentSeries()->setName(arg1);
+ ui->tableWidget->currentItem()->setText(arg1);
+ }
+}
+
+void ChartItemEditor::on_valuesFieldComboBox_currentTextChanged(const QString &arg1)
+{
+ if (currentSeries()){
+ currentSeries()->setValuesColumn(arg1);
+ }
+}
+
+void ChartItemEditor::on_labelsFieldComboBox_currentTextChanged(const QString &arg1)
+{
+ if (!m_initing)
+ m_charItem->setLabelsField(arg1);
+}
+
+void ChartItemEditor::slotChangeSeriesColor()
+{
+ QColorDialog colorDialog;
+ if (colorDialog.exec()){
+ currentSeries()->setColor(colorDialog.selectedColor());
+ m_colorIndicator->setColor(colorDialog.selectedColor());
+ }
+}
diff --git a/limereport/items/lrchartitemeditor.h b/limereport/items/lrchartitemeditor.h
new file mode 100644
index 0000000..4e3d699
--- /dev/null
+++ b/limereport/items/lrchartitemeditor.h
@@ -0,0 +1,57 @@
+#ifndef CHARITEMEDITOR_H
+#define CHARITEMEDITOR_H
+
+#include
+#include "lrchartitem.h"
+#include "lrcolorindicator.h"
+#include
+#include
+
+namespace Ui {
+class ChartItemEditor;
+}
+
+class ChartItemEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ ChartItemEditor(LimeReport::ChartItem* item, LimeReport::PageDesignIntf* page,
+ QSettings* settings=0, QWidget *parent = 0);
+ ~ChartItemEditor();
+public:
+ QSettings *settings();
+ void rebuildTable();
+
+protected:
+ void resizeEvent(QResizeEvent *);
+ void moveEvent(QMoveEvent *);
+private slots:
+ void on_splitter_splitterMoved(int, int);
+ void on_pbOk_clicked();
+ void slotAddSeries();
+ void slotDeleteSeries();
+ void on_tableWidget_itemSelectionChanged();
+ void on_seriesNameLineEdit_textChanged(const QString &arg1);
+ void on_valuesFieldComboBox_currentTextChanged(const QString &arg1);
+ void on_labelsFieldComboBox_currentTextChanged(const QString &arg1);
+ void slotChangeSeriesColor();
+private:
+ void readSetting();
+ void writeSetting();
+ void init();
+ void enableSeriesEditor();
+ void disableSeriesEditor();
+ LimeReport::SeriesItem* currentSeries();
+private:
+ Ui::ChartItemEditor *ui;
+ LimeReport::ChartItem* m_charItem;
+ LimeReport::PageDesignIntf* m_page;
+ QSettings* m_settings;
+ bool m_ownedSettings;
+ bool m_isReadingSetting;
+ QToolButton* m_colorButton;
+ ColorIndicator* m_colorIndicator;
+ bool m_initing;
+};
+
+#endif // CHARITEMEDITOR_H
diff --git a/limereport/items/lrchartitemeditor.ui b/limereport/items/lrchartitemeditor.ui
new file mode 100644
index 0000000..8e21a59
--- /dev/null
+++ b/limereport/items/lrchartitemeditor.ui
@@ -0,0 +1,223 @@
+
+
+ ChartItemEditor
+
+
+
+ 0
+ 0
+ 380
+ 268
+
+
+
+ Form
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Series
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+
+ 4
+
+
-
+
+
+ -
+
+
-
+
+
+ Add
+
+
+
+ -
+
+
+ Delete
+
+
+
+
+
+
+
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
+ 4
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+ -
+
+
+ Name
+
+
+
+ -
+
+
+ -
+
+
+ Values field
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Color
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 16777215
+ 10
+
+
+
+ QFrame::HLine
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Labels field
+
+
+
+ -
+
+
+ true
+
+
+
+
+
+ -
+
+
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Ok
+
+
+
+
+
+
+
+
+
+
+
+
+ pbAddSeries
+ clicked()
+ ChartItemEditor
+ slotAddSeries()
+
+
+ 57
+ 136
+
+
+ 8
+ 75
+
+
+
+
+ pbDeleteSeries
+ clicked()
+ ChartItemEditor
+ slotDeleteSeries()
+
+
+ 142
+ 136
+
+
+ 372
+ 137
+
+
+
+
+
+ slotAddSeries()
+ slotDeleteSeries()
+
+
diff --git a/limereport/limereport.pri b/limereport/limereport.pri
index f7efc40..613ea8e 100644
--- a/limereport/limereport.pri
+++ b/limereport/limereport.pri
@@ -89,7 +89,10 @@ SOURCES += \
$$REPORT_PATH/lrsimplecrypt.cpp \
$$REPORT_PATH/lraboutdialog.cpp \
$$REPORT_PATH/lrsettingdialog.cpp \
- $$REPORT_PATH/scriptbrowser/lrscriptbrowser.cpp
+ $$REPORT_PATH/scriptbrowser/lrscriptbrowser.cpp \
+ $$REPORT_PATH/lrcolorindicator.cpp \
+ $$REPORT_PATH/items/lrchartitem.cpp \
+ $$REPORT_PATH/items/lrchartitemeditor.cpp
contains(CONFIG, zint){
SOURCES += $$REPORT_PATH/items/lrbarcodeitem.cpp
@@ -188,8 +191,11 @@ HEADERS += \
$$REPORT_PATH/lrcallbackdatasourceintf.h \
$$REPORT_PATH/lrsettingdialog.h \
$$REPORT_PATH/lrpreviewreportwidget_p.h \
- $$REPORT_PATH/scriptbrowser/lrscriptbrowser.h
-
+ $$REPORT_PATH/scriptbrowser/lrscriptbrowser.h \
+ $$REPORT_PATH/lrcolorindicator.h \
+ $$REPORT_PATH/items/lrchartitem.h \
+ $$REPORT_PATH/items/lrchartitemeditor.h
+
contains(CONFIG,zint){
HEADERS += $$REPORT_PATH/items/lrbarcodeitem.h
}
@@ -206,6 +212,7 @@ FORMS += \
$$REPORT_PATH/lraboutdialog.ui \
$$REPORT_PATH/lrsettingdialog.ui \
$$REPORT_PATH/scriptbrowser/lrscriptbrowser.ui \
+ $$REPORT_PATH/items/lrchartitemeditor.ui
RESOURCES += \
diff --git a/limereport/lrcolorindicator.cpp b/limereport/lrcolorindicator.cpp
new file mode 100644
index 0000000..73662f1
--- /dev/null
+++ b/limereport/lrcolorindicator.cpp
@@ -0,0 +1,38 @@
+#include "lrcolorindicator.h"
+#include
+
+void ColorIndicator::paintEvent(QPaintEvent* event)
+{
+ QPainter painter(this);
+ painter.save();
+ painter.setBrush(m_color);
+ painter.setPen(Qt::gray);
+ QRect rect = event->rect().adjusted(3,3,-4,-4);
+ rect.setWidth(rect.height());
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.drawEllipse(rect);
+ painter.restore();
+}
+
+ColorIndicator::ColorIndicator(QWidget *parent)
+ :QWidget(parent), m_color(Qt::white){
+ setAttribute(Qt::WA_StaticContents);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+ setFocusPolicy(Qt::NoFocus);
+}
+
+QColor ColorIndicator::color() const
+{
+ return m_color;
+}
+
+void ColorIndicator::setColor(const QColor &color)
+{
+ m_color = color;
+ update();
+}
+
+QSize ColorIndicator::sizeHint() const
+{
+ return QSize(20,20);
+}
diff --git a/limereport/lrcolorindicator.h b/limereport/lrcolorindicator.h
new file mode 100644
index 0000000..5ed1754
--- /dev/null
+++ b/limereport/lrcolorindicator.h
@@ -0,0 +1,20 @@
+#ifndef COLORINDICATOR_H
+#define COLORINDICATOR_H
+
+#include
+#include
+
+class ColorIndicator : public QWidget{
+ Q_OBJECT
+public:
+ ColorIndicator(QWidget* parent = 0);
+ QColor color() const;
+ void setColor(const QColor &color);
+ QSize sizeHint() const;
+protected:
+ void paintEvent(QPaintEvent *event);
+private:
+ QColor m_color;
+};
+
+#endif // COLORINDICATOR_H