diff --git a/example/colorlinechart/colorlinechart.pro b/example/colorlinechart/colorlinechart.pro new file mode 100644 index 0000000..784936a --- /dev/null +++ b/example/colorlinechart/colorlinechart.pro @@ -0,0 +1,15 @@ +!include( ../../common.pri ) { + error( "Couldn't find the common.pri file!" ) +} + +!include( ../../integrated.pri ) { + error( "Couldn't find the integrated.pri file !") +} + +TARGET = colorlineChart +TEMPLATE = app +QT += core gui +SOURCES += main.cpp + + + diff --git a/example/colorlinechart/main.cpp b/example/colorlinechart/main.cpp new file mode 100644 index 0000000..5b8a53b --- /dev/null +++ b/example/colorlinechart/main.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include + +QTCOMMERCIALCHART_USE_NAMESPACE + +#define PI 3.14159265358979 + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QMainWindow window; + + QXYChartSeries* series0 = QXYChartSeries::create(); + series0->setColor(Qt::blue); + QXYChartSeries* series1 = QXYChartSeries::create(); + series1->setColor(Qt::red); + + int numPoints = 100; + + for (int x = 0; x <= numPoints; ++x) { + series0->add(x, abs(sin(PI/50*x)*100)); + series1->add(x, abs(cos(PI/50*x)*100)); + } + + QChartView* chartView = new QChartView(&window); + chartView->addSeries(series0); + chartView->addSeries(series1); + chartView->setBackgroundColor(Qt::yellow); + + window.setCentralWidget(chartView); + window.resize(400, 300); + window.show(); + + return a.exec(); +} diff --git a/example/example.pro b/example/example.pro index 2d04f82..c358c53 100644 --- a/example/example.pro +++ b/example/example.pro @@ -1,2 +1,4 @@ TEMPLATE = subdirs -SUBDIRS += linechart +SUBDIRS += linechart \ + zoomlinechart \ + colorlinechart diff --git a/example/linechart/main.cpp b/example/linechart/main.cpp index b9b914f..aea986b 100644 --- a/example/linechart/main.cpp +++ b/example/linechart/main.cpp @@ -19,33 +19,17 @@ int main(int argc, char *argv[]) series0->setColor(Qt::blue); QXYChartSeries* series1 = QXYChartSeries::create(); series1->setColor(Qt::red); - QXYChartSeries* series2 = QXYChartSeries::create(); - series2->setColor(Qt::gray); - QXYChartSeries* series3 = QXYChartSeries::create(); - series3->setColor(Qt::green); int numPoints = 100; - for (int x = 0; x < numPoints; ++x) { - series0->add(x,0); - series1->add(x, abs(sin(PI/50*x)*100)); - series2->add(x, abs(cos(PI/50*x)*100)); - series3->add(x,100); - } - - QList dataset; - - //qDebug()<<"Series 1:" << *series1; - //qDebug()<<"Series 2:" << *series2; - - dataset << series0; - dataset << series1; - dataset << series2; - dataset << series3; + for (int x = 0; x <= numPoints; ++x) { + series0->add(x, abs(sin(PI/50*x)*100)); + series1->add(x, abs(cos(PI/50*x)*100)); + } QChartView* chartView = new QChartView(&window); + chartView->addSeries(series0); chartView->addSeries(series1); - chartView->addSeries(series2); window.setCentralWidget(chartView); window.resize(400, 300); diff --git a/example/zoomlinechart/chartwidget.cpp b/example/zoomlinechart/chartwidget.cpp new file mode 100644 index 0000000..316aded --- /dev/null +++ b/example/zoomlinechart/chartwidget.cpp @@ -0,0 +1,63 @@ +#include "chartwidget.h" +#include + +ChartWidget::ChartWidget(QWidget *parent) + : QChartView(parent), + m_rubberBand(QRubberBand::Rectangle,this) +{ +} + +void ChartWidget::mousePressEvent(QMouseEvent *event) +{ + if(event->button()!=Qt::LeftButton) return; + + int margin = this->margin(); + + QRect rect(margin,margin,width()-2*margin,height()-2*margin); + + m_origin = event->pos(); + + if (!rect.contains(m_origin)) return; + + m_rubberBand.setGeometry(QRect(m_origin, QSize())); + m_rubberBand.show(); + + event->accept(); +} + +void ChartWidget::mouseMoveEvent(QMouseEvent *event) +{ + if(m_rubberBand.isVisible()) + m_rubberBand.setGeometry(QRect(m_origin, event->pos()).normalized()); +} + +void ChartWidget::mouseReleaseEvent(QMouseEvent *event) +{ + if( event->button()==Qt::LeftButton && m_rubberBand.isVisible()) { + m_rubberBand.hide(); + + QRect rect = m_rubberBand.geometry(); + zoomInToRect(rect); + event->accept(); + } + + if(event->button()==Qt::RightButton) { + zoomOut(); + } +} + + +void ChartWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Plus: + zoomIn(); + break; + case Qt::Key_Minus: + zoomOut(); + break; + default: + QGraphicsView::keyPressEvent(event); + break; + } +} diff --git a/example/zoomlinechart/chartwidget.h b/example/zoomlinechart/chartwidget.h new file mode 100644 index 0000000..b696287 --- /dev/null +++ b/example/zoomlinechart/chartwidget.h @@ -0,0 +1,28 @@ +#ifndef CHARTWIDGET_H +#define CHARTWIDGET_H +#include +#include + +QTCOMMERCIALCHART_USE_NAMESPACE + +class ChartWidget : public QChartView +{ + Q_OBJECT + +public: + ChartWidget(QWidget *parent = 0); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + +private: + bool rubberBandIsShown; + QRubberBand m_rubberBand; + QPoint m_origin; + +}; + +#endif diff --git a/example/zoomlinechart/main.cpp b/example/zoomlinechart/main.cpp new file mode 100644 index 0000000..1067080 --- /dev/null +++ b/example/zoomlinechart/main.cpp @@ -0,0 +1,38 @@ +#include "chartwidget.h" +#include +#include +#include +#include + +QTCOMMERCIALCHART_USE_NAMESPACE + +#define PI 3.14159265358979 + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QMainWindow window; + + QXYChartSeries* series0 = QXYChartSeries::create(); + series0->setColor(Qt::blue); + QXYChartSeries* series1 = QXYChartSeries::create(); + series1->setColor(Qt::red); + + int numPoints = 100; + + for (int x = 0; x <= numPoints; ++x) { + series0->add(x, abs(sin(PI/50*x)*100)); + series1->add(x, abs(cos(PI/50*x)*100)); + } + + ChartWidget* chartWidget = new ChartWidget(&window); + chartWidget->addSeries(series0); + chartWidget->addSeries(series1); + + window.setCentralWidget(chartWidget); + window.resize(400, 300); + window.show(); + + return a.exec(); +} diff --git a/example/zoomlinechart/zoomlinechart.pro b/example/zoomlinechart/zoomlinechart.pro new file mode 100644 index 0000000..e7062fe --- /dev/null +++ b/example/zoomlinechart/zoomlinechart.pro @@ -0,0 +1,17 @@ +!include( ../../common.pri ) { + error( "Couldn't find the common.pri file!" ) +} + +!include( ../../integrated.pri ) { + error( "Couldn't find the integrated.pri file !") +} + +TARGET = zoomLineChart +TEMPLATE = app +QT += core gui +HEADERS += chartwidget.h +SOURCES += main.cpp chartwidget.cpp + + + + diff --git a/src/axis.cpp b/src/axis.cpp deleted file mode 100644 index 65a31f0..0000000 --- a/src/axis.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "axis_p.h" -#include -#include - -QTCOMMERCIALCHART_BEGIN_NAMESPACE - -Axis::Axis(QGraphicsItem* parent): QGraphicsItem(parent) -{ -} - -Axis::~Axis() -{ -} - -void Axis::setLength(int length) -{ - QPainterPath path; - path.moveTo(QPointF(0,0)); - path.lineTo(length,0); - // path.lineTo(length-4,0); - // path.lineTo(length,3); - // path.lineTo(length-4,6); - // path.lineTo(length-4,4); - // path.lineTo(0,4); - // path.lineTo(0,2); - m_path=path; - update(); -} - -QRectF Axis::boundingRect() const -{ - return m_path.boundingRect(); -} - -QPainterPath Axis::shape() const -{ - return m_path; -} - -void Axis::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) -{ - painter->save(); - QPen pen(Qt::black); - //pen.setWidth(10); - painter->setPen(pen); - painter->drawPath(m_path); - painter->restore(); -} - -QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/axis_p.h b/src/axis_p.h deleted file mode 100644 index 028b768..0000000 --- a/src/axis_p.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef AXIS_H_ -#define AXIS_H_ - -#include -#include - -QTCOMMERCIALCHART_BEGIN_NAMESPACE - -class Axis: public QGraphicsItem -{ -public: - Axis(QGraphicsItem* parent = 0); - virtual ~Axis(); - - //from QGraphicsItem - virtual QPainterPath shape() const; - virtual QRectF boundingRect() const; - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - - void setLength(int length); - void setWidth(int width); - -private: - QPainterPath m_path; -}; - -QTCOMMERCIALCHART_END_NAMESPACE - -#endif /* AXIS_H_ */ diff --git a/src/xylinechart/xygrid.cpp b/src/axisitem.cpp similarity index 54% rename from src/xylinechart/xygrid.cpp rename to src/axisitem.cpp index a5d2446..a87a286 100644 --- a/src/xylinechart/xygrid.cpp +++ b/src/axisitem.cpp @@ -1,70 +1,95 @@ -#include "xygrid_p.h" +#include "axisitem_p.h" #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE -XYGrid::XYGrid(QGraphicsItem* parent):QGraphicsItem(parent) +AxisItem::AxisItem(AxisType type,QGraphicsItem* parent): ChartItem(parent), +m_ticks(4), +m_type(type) { } -XYGrid::~XYGrid() +AxisItem::~AxisItem() { - // TODO Auto-generated destructor stub } -void XYGrid::setSize(const QSizeF& size) +void AxisItem::setSize(const QSize& size) { - m_rect.setSize(size.toSize()); + m_rect = QRectF(QPoint(0,0),size); } -void XYGrid::setXYPlotData(const XYPlotDomain& xyPlotData) +void AxisItem::setLength(int length) { - m_xyPlotData = xyPlotData; + QPainterPath path; + path.moveTo(QPointF(0,0)); + path.lineTo(length,0); + // path.lineTo(length-4,0); + // path.lineTo(length,3); + // path.lineTo(length-4,6); + // path.lineTo(length-4,4); + // path.lineTo(0,4); + // path.lineTo(0,2); + m_path=path; + update(); } -QRectF XYGrid::boundingRect() const +QRectF AxisItem::boundingRect() const { - return m_rect; + return m_rect; } -void XYGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) +void AxisItem::setPlotDomain(const PlotDomain& plotDomain) { + m_plotDomain = plotDomain; +} +void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) +{ if (!m_rect.isValid()) - return; + return; - const qreal deltaX = (m_rect.width() -1) / m_xyPlotData.ticksX(); - const qreal deltaY = (m_rect.height() - 1) / m_xyPlotData.ticksY(); + if(m_type==X_AXIS) { - for (int i = 0; i <= m_xyPlotData.ticksX(); ++i) { + const qreal deltaX = (m_rect.width() -1) / m_ticks; - int x = i * deltaX + m_rect.left(); - qreal label = m_xyPlotData.m_minX + (i * m_xyPlotData.spanX() - / m_xyPlotData.ticksX()); - painter->drawLine(x, m_rect.top()+1, x, m_rect.bottom()); - //painter->drawLine(x, m_rect.bottom(), x, m_rect.bottom() + 5); + for (int i = 0; i <= m_ticks; ++i) { - painter->drawText(x - 50, m_rect.bottom() + 5, 100, 20, - Qt::AlignHCenter | Qt::AlignTop, - QString::number(label)); + int x = i * deltaX + m_rect.left(); + qreal label = m_plotDomain.m_minX + (i * m_plotDomain.spanX() + / m_ticks); + painter->drawLine(x, m_rect.top()+1, x, m_rect.bottom()); + //painter->drawLine(x, m_rect.bottom(), x, m_rect.bottom() + 5); + + painter->drawText(x - 50, m_rect.bottom() + 5, 100, 20, + Qt::AlignHCenter | Qt::AlignTop, + QString::number(label)); + } } - for (int j = 0; j <= m_xyPlotData.ticksY(); ++j) { + if(m_type==Y_AXIS) { + + const qreal deltaY = (m_rect.height() - 1) / m_ticks; - int y = j * -deltaY + m_rect.bottom(); - qreal label = m_xyPlotData.m_minY + (j * m_xyPlotData.spanY() - / m_xyPlotData.ticksY()); + for (int j = 0; j <= m_ticks; ++j) { - painter->drawLine(m_rect.left(), y, m_rect.right()-1, y); - //painter->drawLine(m_rect.left() - 5, y, m_rect.left(), y); - //TODO : margin = 50 ; - painter->drawText(m_rect.left() - 50, y - 10, 50 - 5, 20, - Qt::AlignRight | Qt::AlignVCenter, - QString::number(label)); + int y = j * -deltaY + m_rect.bottom(); + qreal label = m_plotDomain.m_minY + (j * m_plotDomain.spanY() + / m_ticks); + + painter->drawLine(m_rect.left(), y, m_rect.right()-1, y); + //painter->drawLine(m_rect.left() - 5, y, m_rect.left(), y); + //TODO : margin = 50 ; + painter->drawText(m_rect.left() - 50, y - 10, 50 - 5, 20, + Qt::AlignRight | Qt::AlignVCenter, + QString::number(label)); + } } //painter->drawRect(m_rect.adjusted(0, 0, -1, -1)); + } +//TODO "nice numbers algorithm" + QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/axisitem_p.h b/src/axisitem_p.h new file mode 100644 index 0000000..645330a --- /dev/null +++ b/src/axisitem_p.h @@ -0,0 +1,40 @@ +#ifndef AXISITEM_H_ +#define AXISITEM_H_ + +#include "chartitem_p.h" +#include "plotdomain_p.h" +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class AxisItem: public ChartItem +{ +public: + enum AxisType{X_AXIS,Y_AXIS}; + + AxisItem(AxisType type = X_AXIS,QGraphicsItem* parent = 0); + ~AxisItem(); + + //from QGraphicsItem + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + //from ChartItem + void setSize(const QSize& size); + void setPlotDomain(const PlotDomain& data); + + void setLength(int length); + void setWidth(int width); + AxisType axisType() const {return m_type;}; + +private: + QRectF m_rect; + int m_ticks; + PlotDomain m_plotDomain; + QPainterPath m_path; + AxisType m_type; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif /* AXISITEM_H_ */ diff --git a/src/chartitem_p.h b/src/chartitem_p.h new file mode 100644 index 0000000..97b928e --- /dev/null +++ b/src/chartitem_p.h @@ -0,0 +1,22 @@ +#ifndef CHARTITEM_H_ +#define CHARTITEM_H_ + +#include "plotdomain_p.h" +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class ChartItem : public QGraphicsItem +{ + enum ChartItemTypes{ AXIS_ITEM = UserType+1, XYLINE_ITEM}; +public: + ChartItem(QGraphicsItem* parent = 0):QGraphicsItem(parent){}; + virtual ~ChartItem(){}; + + virtual void setSize(const QSize& size) = 0; + virtual void setPlotDomain(const PlotDomain& data) = 0; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif /* CHARTITEM_H_ */ diff --git a/src/xylinechart/xyplotdomain.cpp b/src/plotdomain.cpp similarity index 76% rename from src/xylinechart/xyplotdomain.cpp rename to src/plotdomain.cpp index 8759054..1fe5001 100644 --- a/src/xylinechart/xyplotdomain.cpp +++ b/src/plotdomain.cpp @@ -1,10 +1,8 @@ -#include "xyplotdomain_p.h" +#include "plotdomain_p.h" QTCOMMERCIALCHART_BEGIN_NAMESPACE -XYPlotDomain::XYPlotDomain(): -m_ticksX(0), -m_ticksY(0), +PlotDomain::PlotDomain(): m_minX(0), m_maxX(0), m_minY(0), @@ -13,18 +11,18 @@ m_maxY(0) } -XYPlotDomain::~XYPlotDomain() +PlotDomain::~PlotDomain() { // TODO Auto-generated destructor stub } -qreal XYPlotDomain::spanX() const +qreal PlotDomain::spanX() const { Q_ASSERT(m_maxX >= m_minX); return m_maxX - m_minX; } -qreal XYPlotDomain::spanY() const +qreal PlotDomain::spanY() const { Q_ASSERT(m_maxY >= m_minY); return m_maxY - m_minY; diff --git a/src/xylinechart/xyplotdomain_p.h b/src/plotdomain_p.h similarity index 74% rename from src/xylinechart/xyplotdomain_p.h rename to src/plotdomain_p.h index 2b30674..74a1e1d 100644 --- a/src/xylinechart/xyplotdomain_p.h +++ b/src/plotdomain_p.h @@ -5,24 +5,19 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -class XYPlotDomain { +class PlotDomain { public: - XYPlotDomain(); - virtual ~XYPlotDomain(); + PlotDomain(); + virtual ~PlotDomain(); qreal spanX() const; qreal spanY() const; - int ticksX() const { return m_ticksX; } - int ticksY() const { return m_ticksY; } public: - int m_ticksX; - int m_ticksY; qreal m_minX; qreal m_maxX; qreal m_minY; qreal m_maxY; - QRect m_viewportRect; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qchart.cpp b/src/qchart.cpp index 4ba4f6f..c16e0f0 100644 --- a/src/qchart.cpp +++ b/src/qchart.cpp @@ -9,26 +9,29 @@ #include "bargroup.h" #include "xylinechartitem_p.h" -#include "xyplotdomain_p.h" -#include "axis_p.h" -#include "xygrid_p.h" +#include "plotdomain_p.h" +#include "axisitem_p.h" #include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE QChart::QChart(QGraphicsObject* parent) : QGraphicsObject(parent), - m_axisX(new Axis(this)), - m_axisY(new Axis(this)), - m_grid(new XYGrid(this)), + m_background(new QGraphicsRectItem(this)), + m_title(new QGraphicsTextItem(this)), + m_axisX(new AxisItem(AxisItem::X_AXIS,this)), + m_axisY(new AxisItem(AxisItem::Y_AXIS,this)), m_plotDataIndex(0), m_marginSize(0) { // TODO: the default theme? setTheme(QChart::ChartThemeVanilla); // setFlags(QGraphicsItem::ItemClipsChildrenToShape); - // set axis - m_axisY->rotate(90); + PlotDomain domain; + m_plotDomainList<color().isValid() && m_themeColors.count()) xyseries->setColor(m_themeColors.takeFirst()); - XYPlotDomain domain; - //TODO "nice numbers algorithm" - domain.m_ticksX=4; - domain.m_ticksY=4; + m_plotDataIndex = 0 ; + m_plotDomainList.resize(1); + + PlotDomain& domain = m_plotDomainList[m_plotDataIndex]; for (int i = 0 ; i < xyseries->count() ; i++) { @@ -69,9 +72,12 @@ void QChart::addSeries(QChartSeries* series) } XYLineChartItem* item = new XYLineChartItem(xyseries,this); - item->updateXYPlotDomain(domain); - m_plotDomainList<setPlotDomain(m_plotDomainList.at(m_plotDataIndex)); + break; } case QChartSeries::SeriesTypeBar: { @@ -137,32 +143,44 @@ QChartSeries* QChart::createSeries(QChartSeries::QChartSeriesType type) return series; } -void QChart::setSize(const QSizeF& size) +void QChart::setSize(const QSize& size) { - m_rect = QRect(QPoint(0,0),size.toSize()); - m_rect.adjust(margin(),margin(), -margin(), -margin()); - m_grid->setPos(m_rect.topLeft()); - m_grid->setSize(m_rect.size()); + m_rect = QRect(QPoint(0,0),size); + QRect rect = m_rect.adjusted(margin(),margin(), -margin(), -margin()); + + //recalculate background gradient + m_background->setRect(rect); + m_backgroundGradient.setFinalStop(0,m_background->rect().height()); + m_background->setBrush(m_backgroundGradient); + + //resize elements + foreach (ChartItem* item ,m_chartItems) { + item->setPos(rect.topLeft()); + item->setSize(rect.size()); + + } // TODO: TTD for setting scale //emit scaleChanged(100, 100); // TODO: calculate the origo // TODO: not sure if emitting a signal here is the best from performance point of view emit sizeChanged(QRectF(0, 0, size.width(), size.height())); - for (int i(0); i < m_plotDomainList.size(); i++) - m_plotDomainList[i].m_viewportRect = m_rect; - - // TODO: line chart items are updated separately as they don't support update - // via sizeChanged signal - foreach(XYLineChartItem* item ,m_xyLineChartItems) - item->updateXYPlotDomain(m_plotDomainList.at(m_plotDataIndex)); - + update(); +} - if (m_plotDomainList.count()) - m_grid->setXYPlotData(m_plotDomainList.at(m_plotDataIndex)); +void QChart::setBackgroundColor(const QColor& color) +{ + m_backgroundGradient.setColorAt( 0.0, Qt::white); + m_backgroundGradient.setColorAt( 1.0, color); + m_background->setBrush(m_backgroundGradient); + m_background->setPen(Qt::NoPen); + m_background->update(); +} - update(); +void QChart::setTitle(const QString& title) +{ + m_title->setPlainText(title); } int QChart::margin() const @@ -208,6 +226,62 @@ void QChart::setTheme(QChart::ChartTheme theme) // TODO: update coloring of different elements to match the selected theme } +void QChart::zoomInToRect(const QRect& rectangle) +{ + + if(!rectangle.isValid()) return; + + qreal margin = this->margin(); + + QRect rect = rectangle.normalized(); + rect.translate(-margin, -margin); + + PlotDomain& oldDomain = m_plotDomainList[m_plotDataIndex]; + PlotDomain newDomain; + + qreal dx = oldDomain.spanX() / (m_rect.width() - 2 * margin); + qreal dy = oldDomain.spanY() / (m_rect.height() - 2 * margin); + + newDomain.m_minX = oldDomain.m_minX + dx * rect.left(); + newDomain.m_maxX = oldDomain.m_minX + dx * rect.right(); + newDomain.m_minY = oldDomain.m_maxY - dy * rect.bottom(); + newDomain.m_maxY = oldDomain.m_maxY - dy * rect.top(); + + m_plotDomainList.resize(m_plotDataIndex + 1); + m_plotDomainList<setPlotDomain(m_plotDomainList[m_plotDataIndex]); + update(); +} + +void QChart::zoomIn() +{ + if (m_plotDataIndex < m_plotDomainList.count() - 1) { + m_plotDataIndex++; + foreach (ChartItem* item ,m_chartItems) + item->setPlotDomain(m_plotDomainList[m_plotDataIndex]); + update(); + }else{ + QRect rect = m_rect.adjusted(margin(),margin(), -margin(), -margin()); + rect.setWidth(rect.width()/2); + rect.setHeight(rect.height()/2); + rect.moveCenter(m_rect.center()); + zoomInToRect(rect); + } +} + +void QChart::zoomOut() +{ + if (m_plotDataIndex > 0) { + m_plotDataIndex--; + foreach (ChartItem* item ,m_chartItems) + item->setPlotDomain(m_plotDomainList[m_plotDataIndex]); + update(); + } +} + #include "moc_qchart.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qchart.h b/src/qchart.h index 9a70953..a2a85dc 100644 --- a/src/qchart.h +++ b/src/qchart.h @@ -4,14 +4,14 @@ #include #include #include +#include QTCOMMERCIALCHART_BEGIN_NAMESPACE -class Axis; -class XYGrid; +class AxisItem; class QChartSeries; -class XYPlotDomain; -class XYLineChartItem; +class PlotDomain; +class ChartItem; class BarGroup; // TODO: We don't need to have QChart tied to QGraphicsItem: @@ -45,29 +45,39 @@ public: // TODO: who owns the series now? maybe owned by chart and returned a reference instead... QChartSeries* createSeries(QChartSeries::QChartSeriesType type); - virtual void setSize(const QSizeF& rect); + void setSize(const QSize& size); void setMargin(int margin); int margin() const; void setTheme(QChart::ChartTheme theme); + void setTitle(const QString& title); + void setBackgroundColor(const QColor& color); + + void zoomInToRect(const QRect& rectangle); + void zoomIn(); + void zoomOut(); + signals: + //TODO chage to const QSize& size void sizeChanged(QRectF rect); void scaleChanged(qreal xscale, qreal yscale); private: Q_DISABLE_COPY(QChart) - Axis* m_axisX; - Axis* m_axisY; - XYGrid* m_grid; + QGraphicsRectItem* m_background; + QLinearGradient m_backgroundGradient; + QGraphicsTextItem* m_title; + AxisItem* m_axisX; + AxisItem* m_axisY; QRect m_rect; QList m_series; - QList m_plotDomainList; - QList m_xyLineChartItems; + QVector m_plotDomainList; + QList m_chartItems; + //TODO: remove QList m_items; int m_plotDataIndex; int m_marginSize; QList m_themeColors; - QList m_BarGroupItems; }; diff --git a/src/qchartview.cpp b/src/qchartview.cpp index f99d881..5ec3e58 100644 --- a/src/qchartview.cpp +++ b/src/qchartview.cpp @@ -11,9 +11,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE QChartView::QChartView(QWidget *parent) : QGraphicsView(parent), m_scene(new QGraphicsScene()), - m_chart(new QChart()), - m_rubberBand(0), - m_showRubberBand(false) + m_chart(new QChart()) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -46,36 +44,34 @@ QChartSeries* QChartView::createSeries(QChartSeries::QChartSeriesType type) return m_chart->createSeries(type); } -void QChartView::mousePressEvent(QMouseEvent *event) +void QChartView::zoomInToRect(const QRect& rectangle) { - int margin = m_chart->margin(); - - QRect rect(margin,margin,width()-2*margin,height()-2*margin); - - m_origin = event->pos(); + m_chart->zoomInToRect(rectangle); +} - if (!rect.contains(m_origin)) return; +void QChartView::zoomIn() +{ + m_chart->zoomIn(); +} - if (!m_rubberBand) - m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this); - m_rubberBand->setGeometry(QRect(m_origin, QSize())); - m_showRubberBand=true; - m_rubberBand->show(); +void QChartView::zoomOut() +{ + m_chart->zoomOut(); +} +int QChartView::margin() const +{ + return m_chart->margin(); } - void QChartView::mouseMoveEvent(QMouseEvent *event) +void QChartView::setTitle(const QString& title) { - if(m_showRubberBand) - m_rubberBand->setGeometry(QRect(m_origin, event->pos()).normalized()); + m_chart->setTitle(title); } - void QChartView::mouseReleaseEvent(QMouseEvent *event) +void QChartView::setBackgroundColor(const QColor& color) { - if(m_showRubberBand) { - m_rubberBand->hide(); - m_showRubberBand=false; - } + m_chart->setBackgroundColor(color); } QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qchartview.h b/src/qchartview.h index 275eaff..68cde12 100644 --- a/src/qchartview.h +++ b/src/qchartview.h @@ -6,7 +6,6 @@ #include class QGraphicsScene; -class QRubberBand; QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -25,17 +24,17 @@ public: // Convenience function QChartSeries* createSeries(QChartSeries::QChartSeriesType type); -protected: - void mouseMoveEvent (QMouseEvent *event); - void mousePressEvent (QMouseEvent *event); - void mouseReleaseEvent (QMouseEvent *event); + int margin() const; + void setTitle(const QString& title); + void setBackgroundColor(const QColor& color); + void zoomInToRect(const QRect& rectangle); + void zoomIn(); + void zoomOut(); private: QGraphicsScene *m_scene; QChart* m_chart; - QRubberBand *m_rubberBand; QPoint m_origin; - bool m_showRubberBand; Q_DISABLE_COPY(QChartView) diff --git a/src/src.pro b/src/src.pro index 56f75ae..7aaf3a4 100644 --- a/src/src.pro +++ b/src/src.pro @@ -17,12 +17,11 @@ SOURCES += \ barchart/bar.cpp \ xylinechart/qxychartseries.cpp \ xylinechart/xylinechartitem.cpp \ - xylinechart/xygrid.cpp \ - xylinechart/xyplotdomain.cpp \ + plotdomain.cpp \ qscatterseries.cpp \ qpieseries.cpp \ qchart.cpp \ - axis.cpp \ + axisitem.cpp \ qchartwidget.cpp \ pieslice.cpp \ qchartview.cpp \ @@ -30,11 +29,11 @@ SOURCES += \ PRIVATE_HEADERS += \ xylinechart/xylinechartitem_p.h \ - xylinechart/xyplotdomain_p.h \ - xylinechart/xygrid_p.h \ + plotdomain_p.h \ qscatterseries_p.h \ pieslice.h \ - axis_p.h + axisitem_p.h \ + chartitem_p.h PUBLIC_HEADERS += \ qchartseries.h \ diff --git a/src/xylinechart/xygrid_p.h b/src/xylinechart/xygrid_p.h deleted file mode 100644 index becd9f6..0000000 --- a/src/xylinechart/xygrid_p.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef XYGRID_H_ -#define XYGRID_H_ - -#include -#include -#include - -QTCOMMERCIALCHART_BEGIN_NAMESPACE - -class XYGrid : public QGraphicsItem -{ -public: - XYGrid(QGraphicsItem* parent = 0); - virtual ~XYGrid(); - - //from QGraphicsItem - virtual QRectF boundingRect() const; - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - - //TODO: this is just temporary interface - void setXYPlotData(const XYPlotDomain& xyPlotData); - void setSize(const QSizeF& rect); - -private: - QRectF m_rect; - XYPlotDomain m_xyPlotData; -}; - -QTCOMMERCIALCHART_END_NAMESPACE - -#endif /* XYGRID_H_ */ diff --git a/src/xylinechart/xylinechartitem.cpp b/src/xylinechart/xylinechartitem.cpp index 752e1b3..f5ef4dc 100644 --- a/src/xylinechart/xylinechartitem.cpp +++ b/src/xylinechart/xylinechartitem.cpp @@ -1,6 +1,5 @@ #include "xylinechartitem_p.h" -#include "axis_p.h" -#include "xygrid_p.h" +#include "axisitem_p.h" #include "qxychartseries.h" #include #include @@ -8,49 +7,61 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE -XYLineChartItem::XYLineChartItem(QXYChartSeries* series,QGraphicsItem *parent):QGraphicsItem(parent), -m_series(series) +XYLineChartItem::XYLineChartItem(QXYChartSeries* series,QGraphicsItem *parent):ChartItem(parent), +m_series(series), +m_dirty(false) { } -void XYLineChartItem::updateXYPlotDomain(const XYPlotDomain& data) +void XYLineChartItem::setSize(const QSize& size) { - m_xyPlotData=data; + m_rect=QRect(0,0,size.width(),size.height()); + m_dirty=true; +} - if (!m_xyPlotData.m_viewportRect.isValid()) - return; +void XYLineChartItem::setPlotDomain(const PlotDomain& data) +{ + m_plotDomain=data; + m_dirty=true; +} - const QRect& rect = m_xyPlotData.m_viewportRect; +QRectF XYLineChartItem::boundingRect() const +{ + return m_polyline.boundingRect(); +} - const qreal deltaX = (rect.width()-1)/m_xyPlotData.spanX(); - const qreal deltaY = (rect.height()-1)/m_xyPlotData.spanY(); +void XYLineChartItem::updateGeometry() +{ + if (!m_rect.isValid()) return; - m_polyline.clear(); - m_polyline.resize(m_series->count()); + const qreal deltaX = (m_rect.width()-1)/m_plotDomain.spanX(); + const qreal deltaY = (m_rect.height()-1)/m_plotDomain.spanY(); - for (int j = 0; j < m_series->count(); ++j) { - qreal dx = m_series->x(j) - m_xyPlotData.m_minX; - qreal dy = m_series->y(j) - m_xyPlotData.m_minY; - qreal x = (dx * deltaX) + rect.left(); - qreal y = - (dy * deltaY) + rect.bottom(); - m_polyline[j] = QPointF(x, y); - } + m_polyline.clear(); + m_polyline.resize(m_series->count()); -} + for (int j = 0; j < m_series->count(); ++j) { + qreal dx = m_series->x(j) - m_plotDomain.m_minX; + qreal dy = m_series->y(j) - m_plotDomain.m_minY; + qreal x = (dx * deltaX) + m_rect.left(); + qreal y = - (dy * deltaY) + m_rect.bottom(); + m_polyline[j] = QPointF(x, y); + } -QRectF XYLineChartItem::boundingRect() const -{ - return m_polyline.boundingRect(); } void XYLineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) { - painter->setClipRect(m_xyPlotData.m_viewportRect.adjusted(+1, +1, -1, -1)); + //TODO: remove it + if (m_dirty) { + updateGeometry(); + m_dirty=false; + } + painter->setClipRect(m_rect.adjusted(+1, +1, -1, -1)); painter->setPen(m_series->color()); painter->drawPolyline(m_polyline); - } QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/xylinechart/xylinechartitem_p.h b/src/xylinechart/xylinechartitem_p.h index 9f96058..34de143 100644 --- a/src/xylinechart/xylinechartitem_p.h +++ b/src/xylinechart/xylinechartitem_p.h @@ -2,30 +2,35 @@ #define XYLINECHARTITEM_H #include "qchartglobal.h" -#include -#include "xyplotdomain_p.h" +#include "chartitem_p.h" QTCOMMERCIALCHART_BEGIN_NAMESPACE class QXYChartSeries; -class XYLineChartItem : public QGraphicsItem +class XYLineChartItem : public ChartItem { public: XYLineChartItem(QXYChartSeries* m_series,QGraphicsItem *parent = 0); - virtual ~ XYLineChartItem(){}; + ~ XYLineChartItem(){}; //from QGraphicsItem - virtual QRectF boundingRect() const; - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + //from ChartItem + void setSize(const QSize& size); + void setPlotDomain(const PlotDomain& data); - void updateXYPlotDomain(const XYPlotDomain& data); +private: + void updateGeometry(); private: + QRect m_rect; QPolygonF m_polyline; QXYChartSeries* m_series; - XYPlotDomain m_xyPlotData; + PlotDomain m_plotDomain; + bool m_dirty; }; QTCOMMERCIALCHART_END_NAMESPACE