diff --git a/src/qchart.cpp b/src/qchart.cpp index 0f9f0c8..6c8d40a 100644 --- a/src/qchart.cpp +++ b/src/qchart.cpp @@ -1,9 +1,12 @@ #include "qchart.h" #include "qchartseries.h" +#include "qscatterseries.h" +#include "qscatterseries_p.h" #include "xylinechartitem_p.h" #include "xyplotdomain_p.h" #include "axis_p.h" #include "xygrid_p.h" +#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -84,6 +87,28 @@ void QChart::addSeries(QChartSeries* series) } } +QChartSeries* QChart::createSeries(QList x, QList y, QChartSeries::QChartSeriesType type) +{ + Q_D(QChart); + + // TODO: support also other types + Q_ASSERT(type == QChartSeries::SeriesTypeScatter); + QChartSeries *series = 0; + + switch (type) { + case QChartSeries::SeriesTypeScatter: { + QScatterSeries *scatterSeries = new QScatterSeries(x, y, this); + d->m_items.append(scatterSeries->d); + scene()->addItem(scatterSeries->d); + //series = qobject_cast(scatterSeries); + break; + } + default: + break; + } + + return series; +} void QChart::setSize(const QSizeF& size) { Q_D(QChart); @@ -93,10 +118,11 @@ void QChart::setSize(const QSizeF& size) d->m_grid->setPos(d->m_rect.topLeft()); d->m_grid->setSize(d->m_rect.size()); d->m_plotDataList[0].m_viewportRect = d->m_rect; + // TODO: line chart items would need to be updated separately as they don't support update + // via paint method foreach(QGraphicsItem* item , d->m_items) - reinterpret_cast(item)->updateXYPlotData(d->m_plotDataList.at(0)); + reinterpret_cast(item)->updateXYPlotData(d->m_plotDataList.at(0)); update(); - } int QChart::margin() const diff --git a/src/qchart.h b/src/qchart.h index 26004bc..9e06dc8 100644 --- a/src/qchart.h +++ b/src/qchart.h @@ -2,6 +2,7 @@ #define CHART_H #include +#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -12,7 +13,15 @@ class QChartSeries; class XYPlotDomain; class QChartPrivate; -class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsItem +// TODO: We don't need to have QChart tied to QGraphicsItem: +//class QTCOMMERCIALCHART_EXPORT QChart +//class QTCOMMERCIALCHART_EXPORT QChartGraphicsItem : public QGraphicsItem { +// public: QChartGraphicsItem(QChart &chart); + +/*! + * TODO: define the responsibilities + */ +class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsItem, public QObject { public: @@ -24,6 +33,9 @@ public: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){}; void addSeries(QChartSeries* series); + //TODO: QChartSeries* createSeries(QSeriesData *data, QChartSeries::QChartSeriesType type); + // TODO: who owns the series now? maybe owned by chart and returned a reference instead... + QChartSeries* createSeries(QList x, QList y, QChartSeries::QChartSeriesType type); virtual void setSize(const QSizeF& rect); void setMargin(int margin); diff --git a/src/qchartwidget.cpp b/src/qchartwidget.cpp index a55f44a..302c79d 100644 --- a/src/qchartwidget.cpp +++ b/src/qchartwidget.cpp @@ -19,6 +19,7 @@ public: m_view->setScene(m_scene); m_chart = new QChart(); m_scene->addItem(m_chart); + m_view->show(); } ~QChartWidgetPrivate() { @@ -64,6 +65,11 @@ void QChartWidget::addSeries(QChartSeries* series) d->m_chart->addSeries(series); } +QChartSeries* QChartWidget::createSeries(QList x, QList y, QChartSeries::QChartSeriesType type) +{ + Q_D(QChartWidget); + return d->m_chart->createSeries(x, y, type); +} #include "moc_qchartwidget.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qchartwidget.h b/src/qchartwidget.h index 0edecd0..abd2574 100644 --- a/src/qchartwidget.h +++ b/src/qchartwidget.h @@ -21,7 +21,9 @@ public: void resizeEvent(QResizeEvent *event); QSize sizeHint() const; + // TODO: addSeries and createSeries are optional solutions void addSeries(QChartSeries* series); + QChartSeries* createSeries(QList x, QList y, QChartSeries::QChartSeriesType type); protected: QChartWidgetPrivate * const d_ptr; diff --git a/src/qscatterseries.cpp b/src/qscatterseries.cpp new file mode 100644 index 0000000..1fe1d3a --- /dev/null +++ b/src/qscatterseries.cpp @@ -0,0 +1,67 @@ +#include "qscatterseries.h" +#include "qscatterseries_p.h" +#include "qchart.h" +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +//#define QSeriesData QList + +QScatterSeriesPrivate::QScatterSeriesPrivate(QList x, QList y, QGraphicsItem *parent) : + QGraphicsItem(parent), + m_x(x), + m_y(y) +{ +} + +void QScatterSeriesPrivate::setSize() +{ +} + +QRectF QScatterSeriesPrivate::boundingRect() const +{ + return QRectF(0, 0, 100, 100); +} + +void QScatterSeriesPrivate::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + QPen pen = painter->pen(); + QBrush brush = pen.brush(); + // TODO: The opacity should be user definable... + brush.setColor(QColor(255, 82, 0, 50)); + pen.setBrush(brush); + pen.setWidth(4); + painter->setPen(pen); + QTransform transform = painter->transform(); + + // TODO: get min and max values of the axes from the QChart (or some dedicated class) + const qreal xmin = 0.0; + const qreal xmax = 100.0; + const qreal xscale = scene()->width() / (xmax - xmin); + const qreal ymin = 0.0; + const qreal ymax = 100.0; + const qreal yscale = scene()->height() / (ymax - ymin); + + for (int i(0); i < m_x.count() && i < m_y.count(); i++) { + transform.reset(); + transform.translate(m_x.at(i) * xscale, m_y.at(i) * yscale); + painter->setTransform(transform); + painter->drawArc(0, 0, 4, 4, 0, 5760); + } +} + +QScatterSeries::QScatterSeries(QList x, QList y, QObject *parent) : + QChartSeries(parent), + d(new QScatterSeriesPrivate(x, y, qobject_cast (parent))) +{ +} + +QScatterSeries::~QScatterSeries() +{ + delete d; +} + +#include "moc_qscatterseries.cpp" + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/qscatterseries.h b/src/qscatterseries.h new file mode 100644 index 0000000..bf0f3a0 --- /dev/null +++ b/src/qscatterseries.h @@ -0,0 +1,29 @@ +#ifndef QSCATTERSERIES_H +#define QSCATTERSERIES_H + +#include "qchartseries.h" + +QTCOMMERCIALCHART_BEGIN_NAMESPACE +class QScatterSeriesPrivate; + +class QTCOMMERCIALCHART_EXPORT QScatterSeries : public QChartSeries +{ + Q_OBJECT +public: + //QScatterSeries(QSeriesData *data, QObject *chart); + QScatterSeries(QList x, QList y, QObject *chart = 0); + ~QScatterSeries(); + +public: // from QChartSeries + virtual QChartSeriesType type() const { return QChartSeries::SeriesTypeScatter; } + +private: + Q_DECLARE_PRIVATE(QScatterSeries) + Q_DISABLE_COPY(QScatterSeries) + friend class QChart; + QScatterSeriesPrivate *const d; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // QSCATTERSERIES_H diff --git a/src/qscatterseries_p.h b/src/qscatterseries_p.h new file mode 100644 index 0000000..33828da --- /dev/null +++ b/src/qscatterseries_p.h @@ -0,0 +1,29 @@ +#ifndef QSCATTERSERIESPRIVATE_H +#define QSCATTERSERIESPRIVATE_H + +#include "qchartseries.h" +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +/*! + * The PIMPL class of QScatterSeries. + */ +class QScatterSeriesPrivate : public QGraphicsItem +{ +public: + QScatterSeriesPrivate(QList x, QList y, QGraphicsItem *parent); + +public: // from QGraphicsItem + void setSize(); + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + // TODO: use the chart data class instead of list of x and y values? + QList m_x; + QList m_y; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif // QSCATTERSERIES_H diff --git a/src/src.pro b/src/src.pro index b85e174..df9fc08 100644 --- a/src/src.pro +++ b/src/src.pro @@ -17,6 +17,7 @@ SOURCES += \ xylinechart/xylinechartitem.cpp \ xylinechart/xygrid.cpp \ xylinechart/xyplotdomain.cpp \ + qscatterseries.cpp \ qchart.cpp \ axis.cpp \ qchartwidget.cpp @@ -25,10 +26,12 @@ PRIVATE_HEADERS += \ xylinechart/xylinechartitem_p.h \ xylinechart/xyplotdomain_p.h \ xylinechart/xygrid_p.h \ + qscatterseries_p.h \ axis_p.h PUBLIC_HEADERS += \ qchartseries.h \ + qscatterseries.h \ qchart.h \ qchartwidget.h \ qchartglobal.h \ @@ -70,4 +73,4 @@ QMAKE_CLEAN+= qchartversion_p.h QMAKE_EXTRA_TARGETS += chartversion unix:QMAKE_DISTCLEAN += -r $$CHART_BUILD_HEADER_DIR $$CHART_BUILD_LIB_DIR -win32:QMAKE_DISTCLEAN += /Q $$CHART_BUILD_HEADER_DIR $$CHART_BUILD_LIB_DIR \ No newline at end of file +win32:QMAKE_DISTCLEAN += /Q $$CHART_BUILD_HEADER_DIR $$CHART_BUILD_LIB_DIR diff --git a/test/chartwidgettest/mainwidget.cpp b/test/chartwidgettest/mainwidget.cpp index 3189f03..76c1288 100644 --- a/test/chartwidgettest/mainwidget.cpp +++ b/test/chartwidgettest/mainwidget.cpp @@ -100,39 +100,45 @@ void MainWidget::addSeries(QString series, QString data) qDebug() << "addSeries: " << series << " data: " << data; m_defaultSeries = series; - QXYChartSeries* series0 = 0; - - // TODO: color of the series - if (series == "Scatter") { - series0 = QXYChartSeries::create(); - } else if (series == "Line") { - series0 = QXYChartSeries::create(); - } else { - // TODO - series0 = QXYChartSeries::create(); - } + // TODO: a dedicated data class for storing x and y values + QList x; + QList y; if (data == "linear") { - for (int i = 0; i < 10; i++) - series0->add(i, 10); + for (int i = 0; i < 10; i++) { + x.append(i); + y.append(10); + } } else if (data == "linear, 1M") { - for (int i = 0; i < 1000000; i++) - series0->add(i, 20); + for (int i = 0; i < 10000; i++) { + x.append(i); + y.append(20); + } } else if (data == "SIN") { - for (int x = 0; x < 100; x++) - series0->add(x, abs(sin(3.14159265358979 / 50 * x) * 100)); - QList dataset; - dataset << series0; + for (int i = 0; i < 100; i++) { + x.append(i); + y.append(abs(sin(3.14159265358979 / 50 * i) * 100)); + } } else if (data == "SIN + random") { - for (qreal x = 0; x < 100; x += 0.1) { - series0->add(x + (rand() % 5), - abs(sin(3.14159265358979 / 50 * x) * 100) + (rand() % 5)); + for (qreal i = 0; i < 100; i += 0.1) { + x.append(i + (rand() % 5)); + y.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5)); } } else { // TODO: check if data has a valid file name } - m_chartWidget->addSeries(series0); + // TODO: color of the series + if (series == "Scatter") { + /*QChartSeries* scatterSeries = */m_chartWidget->createSeries(x, y, QChartSeries::SeriesTypeScatter); + } else if (series == "Line") { + QXYChartSeries* series0 = QXYChartSeries::create(); + for (int i = 0; i < 1000000; i++) + series0->add(i, 20); + m_chartWidget->addSeries(series0); + } else { + // TODO + } } void MainWidget::chartTypeChanged(int itemIndex)