diff --git a/examples/examples.pro b/examples/examples.pro index 93d795f..5dbbc0c 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -18,6 +18,5 @@ SUBDIRS += linechart \ splinechart \ areachart \ stackedbarchartdrilldown \ - customcolors - - + customcolors \ + tablemodelchart diff --git a/examples/tablemodelchart/customtablemodel.cpp b/examples/tablemodelchart/customtablemodel.cpp new file mode 100644 index 0000000..08c3048 --- /dev/null +++ b/examples/tablemodelchart/customtablemodel.cpp @@ -0,0 +1,123 @@ +#include "customtablemodel.h" + +CustomTableModel::CustomTableModel(QObject *parent) : + QAbstractTableModel(parent) +{ + m_points.append(QPointF(10, 50)); + m_labels.append("Apples"); + m_points.append(QPointF(60, 70)); + m_labels.append("Oranges"); + m_points.append(QPointF(110, 50)); + m_labels.append("Bananas"); + m_points.append(QPointF(140, 40)); + m_labels.append("Lemons"); + m_points.append(QPointF(200, 150)); + m_labels.append("Plums"); +} + +int CustomTableModel::rowCount(const QModelIndex & parent) const +{ + return m_points.count(); +} + +int CustomTableModel::columnCount(const QModelIndex & parent) const +{ + return 3; +} + +QVariant CustomTableModel::headerData (int section, Qt::Orientation orientation, int role ) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch(section) + { + case 0: + return "x"; + case 1: + return "y"; + case 2: + return "Fruit"; + default: "What?"; + } + } + else + return QString("%1").arg(section + 1); +} + +QVariant CustomTableModel::data(const QModelIndex & index, int role) const +{ + if (role == Qt::DisplayRole) + { + switch(index.column()) + { + case 0: + return m_points[index.row()].x(); + case 1: + return m_points[index.row()].y(); + case 2: + return m_labels[index.row()]; + default: + return QVariant(); + } + } + else if (role == Qt::EditRole) + { + switch(index.column()) + { + case 0: + return m_points[index.row()].x(); + case 1: + return m_points[index.row()].y(); + case 2: + return m_labels[index.row()]; + default: + return QVariant(); + } + } +} + +bool CustomTableModel::setData ( const QModelIndex & index, const QVariant & value, int role) +{ + if (index.isValid() && role == Qt::EditRole) + { + switch(index.column()) + { + case 0: + m_points[index.row()].setX(value.toDouble()); + break; + case 1: + m_points[index.row()].setY(value.toDouble()); + break; + case 2: + m_labels.replace(index.row(), value.toString()); + break; + default: + return false; + } + emit dataChanged(index, index); + return true; + } + return false; +} + +Qt::ItemFlags CustomTableModel::flags ( const QModelIndex & index ) const +{ + if (!index.isValid()) + return Qt::ItemIsEnabled; + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +} + +bool CustomTableModel::insertRows ( int row, int count, const QModelIndex & parent) +{ + beginInsertRows(QModelIndex(), row /*dataTable.count()*/, row + count - 1); + for (int i = 0; i < count; i++) + { + m_points.append(QPointF()); + m_labels.append(""); + } + endInsertRows(); + return true; +} diff --git a/examples/tablemodelchart/customtablemodel.h b/examples/tablemodelchart/customtablemodel.h new file mode 100644 index 0000000..aa978a0 --- /dev/null +++ b/examples/tablemodelchart/customtablemodel.h @@ -0,0 +1,32 @@ +#ifndef XYPOINTSMODEL_H +#define XYPOINTSMODEL_H + +#include +#include +#include + +class CustomTableModel : public QAbstractTableModel +{ + Q_OBJECT +public: + explicit CustomTableModel(QObject *parent = 0); + + int rowCount ( const QModelIndex & parent = QModelIndex() ) const; + int columnCount ( const QModelIndex & parent = QModelIndex() ) const; + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); + Qt::ItemFlags flags ( const QModelIndex & index ) const; + bool insertRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); + + //signals: + + //public slots: +private: + QList m_points; + QStringList m_labels; + + +}; + +#endif // XYPOINTSMODEL_H diff --git a/examples/tablemodelchart/main.cpp b/examples/tablemodelchart/main.cpp new file mode 100644 index 0000000..20f9d10 --- /dev/null +++ b/examples/tablemodelchart/main.cpp @@ -0,0 +1,11 @@ +#include +#include "tablewidget.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + TableWidget w; + w.show(); + + return a.exec(); +} diff --git a/examples/tablemodelchart/tablemodelchart.pro b/examples/tablemodelchart/tablemodelchart.pro new file mode 100644 index 0000000..242bfbb --- /dev/null +++ b/examples/tablemodelchart/tablemodelchart.pro @@ -0,0 +1,22 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-03-08T14:30:24 +# +#------------------------------------------------- + +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +QT += core gui + +TARGET = tablemodelchart +TEMPLATE = app + + +SOURCES += main.cpp\ + tablewidget.cpp \ + customtablemodel.cpp + +HEADERS += tablewidget.h \ + customtablemodel.h diff --git a/examples/tablemodelchart/tablewidget.cpp b/examples/tablemodelchart/tablewidget.cpp new file mode 100644 index 0000000..53e183f --- /dev/null +++ b/examples/tablemodelchart/tablewidget.cpp @@ -0,0 +1,54 @@ +#include "tablewidget.h" +#include +#include +#include +#include "qlineseries.h" +#include "qsplineseries.h" +#include "customtablemodel.h" +#include "qpieseries.h" + +TableWidget::TableWidget(QWidget *parent) + : QWidget(parent) +{ + + + // create simple model for storing data + // user's table data model + CustomTableModel* model = new CustomTableModel; + QTableView* tableView = new QTableView; + tableView->setModel(model); + tableView->setMinimumSize(340, 480); +// tableView->setItemDelegate(new QStyledItemDelegate); + chartView = new QChartView; + chartView->setMinimumSize(640, 480); + + // create +// QLineSeries* series = new QLineSeries; + QSplineSeries* series = new QSplineSeries; + series->setModel(model); + series->setModelMappingX(0); + series->setModelMappingY(1); + +// series->add(QPointF(150, 100)); +// series->add(QPointF(200, 130)); +// series->add(QPointF(250, 120)); +// series->add(QPointF(300, 140)); +// series->add(QPointF(350, 160)); + +// QPieSeries* pieSeries = new QPieSeries; +// pieSeries->setModel(model); +// pieSeries + + chartView->addSeries(series); + + // create main layout + QGridLayout* mainLayout = new QGridLayout; + mainLayout->addWidget(tableView, 1, 1); + mainLayout->addWidget(chartView, 1, 2); + setLayout(mainLayout); +} + +TableWidget::~TableWidget() +{ + +} diff --git a/examples/tablemodelchart/tablewidget.h b/examples/tablemodelchart/tablewidget.h new file mode 100644 index 0000000..feae5ca --- /dev/null +++ b/examples/tablemodelchart/tablewidget.h @@ -0,0 +1,23 @@ +#ifndef TABLEWIDGET_H +#define TABLEWIDGET_H + +#include +#include "qchartview.h" + +QTCOMMERCIALCHART_USE_NAMESPACE + +class TableWidget : public QWidget +{ + Q_OBJECT + +public: + TableWidget(QWidget *parent = 0); + ~TableWidget(); + + + + private: + QChartView* chartView; +}; + +#endif // TABLEWIDGET_H diff --git a/src/splinechart/qsplineseries.cpp b/src/splinechart/qsplineseries.cpp index 5c7bfa2..ca3679e 100644 --- a/src/splinechart/qsplineseries.cpp +++ b/src/splinechart/qsplineseries.cpp @@ -43,15 +43,15 @@ void QSplineSeries::calculateControlPoints() // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit // CPOL License - int n = m_x.size() - 1; + int n = count() - 1; if (n == 1) { // Special case: Bezier curve should be a straight line. // firstControlPoints = new Point[1]; // 3P1 = 2P0 + P3 - m_controlPoints.append(QPointF((2 * m_x[0] + m_x[1]) / 3, (2 * m_y[0] + m_y[1]) / 3)); + m_controlPoints.append(QPointF((2 * x(0) + x(1)) / 3, (2 * y(0) + y(1)) / 3)); // P2 = 2P1 P0 - m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_x[0], 2 * m_controlPoints[0].y() - m_y[0])); + m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - x(0), 2 * m_controlPoints[0].y() - y(0))); return; } @@ -69,35 +69,35 @@ void QSplineSeries::calculateControlPoints() // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn | // QList rhs; - rhs.append(m_x[0] + 2 * m_x[1]); + rhs.append(x(0) + 2 * x(1)); // Set right hand side X values for (int i = 1; i < n - 1; ++i) - rhs.append(4 * m_x[i] + 2 * m_x[i + 1]); + rhs.append(4 * x(i) + 2 * x(i + 1)); - rhs.append((8 * m_x[n - 1] + m_x[n]) / 2.0); + rhs.append((8 * x(n - 1) + x(n)) / 2.0); // Get first control points X-values - QList x = getFirstControlPoints(rhs); - rhs[0] = m_y[0] + 2 * m_y[1]; + QList xControl = getFirstControlPoints(rhs); + rhs[0] = y(0) + 2 * y(1); // Set right hand side Y values for (int i = 1; i < n - 1; ++i) - rhs[i] = 4 * m_y[i] + 2 * m_y[i + 1]; + rhs[i] = 4 * y(i) + 2 * y(i + 1); - rhs[n - 1] = (8 * m_y[n - 1] + m_y[n]) / 2.0; + rhs[n - 1] = (8 * y(n - 1) + y(n)) / 2.0; // Get first control points Y-values - QList y = getFirstControlPoints(rhs); + QList yControl = getFirstControlPoints(rhs); // Fill output arrays. for (int i = 0; i < n; ++i) { // First control point - m_controlPoints.append(QPointF(x[i], y[i])); + m_controlPoints.append(QPointF(xControl[i], yControl[i])); // Second control point if (i < n - 1) - m_controlPoints.append(QPointF(2 * m_x[i + 1] - x[i + 1], 2 * m_y[i + 1] - y[i + 1])); + m_controlPoints.append(QPointF(2 * x(i + 1) - xControl[i + 1], 2 * y(i + 1) - yControl[i + 1])); else - m_controlPoints.append(QPointF((m_x[n] + x[n - 1]) / 2, (m_y[n] + y[n - 1]) / 2)); + m_controlPoints.append(QPointF((x(n) + xControl[n - 1]) / 2, (y(n) + yControl[n - 1]) / 2)); } } @@ -130,13 +130,19 @@ QList QSplineSeries::getFirstControlPoints(QList rhs) */ void QSplineSeries::updateControlPoints() { - if(m_x.size() > 1) + if(count() > 1) { m_controlPoints.clear(); calculateControlPoints(); } } +bool QSplineSeries::setModel(QAbstractItemModel* model) +{ + QXYSeries::setModel(model); + calculateControlPoints(); +} + #include "moc_qsplineseries.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/splinechart/qsplineseries.h b/src/splinechart/qsplineseries.h index 20567e3..9df24f5 100644 --- a/src/splinechart/qsplineseries.h +++ b/src/splinechart/qsplineseries.h @@ -19,6 +19,7 @@ public: // int count() const { return m_x.size(); } QPointF controlPoint(int index) const {return m_controlPoints[index];} + bool setModel(QAbstractItemModel* model); // TODO: allow the user to set custom control points // void setCustomControlPoints(QList controlPoints); diff --git a/src/xychart/qxyseries.cpp b/src/xychart/qxyseries.cpp index 8b1ad2c..e4c1e0e 100644 --- a/src/xychart/qxyseries.cpp +++ b/src/xychart/qxyseries.cpp @@ -45,6 +45,9 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE */ QXYSeries::QXYSeries(QObject* parent):QSeries(parent) { + m_model = 0; + m_mapX = 0; + m_mapY = 1; } /*! Destroys the object. Series added to QChartView or QChart instances are owned by those, @@ -102,7 +105,7 @@ void QXYSeries::replace(qreal x,qreal y) */ void QXYSeries::replace(const QPointF& point) { - replace(point.x(),point.y()); + replace(point.x(),point.y()); } /*! @@ -138,7 +141,10 @@ void QXYSeries::removeAll() */ qreal QXYSeries::x(int pos) const { - return m_x.at(pos); + if (m_model) + return m_model->data(m_model->index(pos, m_mapX), Qt::DisplayRole).toDouble(); + else + return m_x.at(pos); } /*! @@ -146,7 +152,10 @@ qreal QXYSeries::x(int pos) const */ qreal QXYSeries::y(int pos) const { - return m_y.at(pos); + if (m_model) + return m_model->data(m_model->index(pos, m_mapY), Qt::DisplayRole).toDouble(); + else + return m_y.at(pos); } /*! @@ -154,10 +163,13 @@ qreal QXYSeries::y(int pos) const */ int QXYSeries::count() const { - Q_ASSERT(m_x.size() == m_y.size()); - - return m_x.size(); + Q_ASSERT(m_x.size() == m_y.size()); +// int k = m_model->rowCount(); + if (m_model) + return m_model->rowCount(); + else + return m_x.size(); } /*! @@ -224,6 +236,19 @@ QXYSeries& QXYSeries::operator<< (const QList points) } +void QXYSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight) +{ + emit pointReplaced(topLeft.row()); +} + +bool QXYSeries::setModel(QAbstractItemModel* model) { + m_model = model; + for (int i = 0; i < m_model->rowCount(); i++) + emit pointAdded(i); + connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex))); +// connect(m_model,SIGNAL(), this, SLOT(modelUpdated(QModelIndex, QModelIndex))); +} + #include "moc_qxyseries.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/xychart/qxyseries.h b/src/xychart/qxyseries.h index e852aa0..258488f 100644 --- a/src/xychart/qxyseries.h +++ b/src/xychart/qxyseries.h @@ -39,6 +39,15 @@ public: void setBrush(const QBrush& pen); QBrush brush() const {return m_brush;} + bool setModel(QAbstractItemModel* model); + QAbstractItemModel* model() {return m_model;} + + void setModelMappingX(int modelColumn) {m_mapX = modelColumn;} + void setModelMappingY(int modelColumn) {m_mapY = modelColumn;} + + private slots: + void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight); + signals: void updated(); void pointReplaced(int index); @@ -48,8 +57,13 @@ signals: protected: QVector m_x; QVector m_y; + QPen m_pen; QBrush m_brush; + + QAbstractItemModel* m_model; + int m_mapX; + int m_mapY; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/xychart/xychartitem.cpp b/src/xychart/xychartitem.cpp index 70f312e..5e77410 100644 --- a/src/xychart/xychartitem.cpp +++ b/src/xychart/xychartitem.cpp @@ -101,7 +101,7 @@ void XYChartItem::handlePointReplaced(int index) QPointF point = calculateGeometryPoint(index); QVector points = m_points; m_points.replace(index,point); - updatePoint(points); + updatePoint(m_points); update(); } @@ -125,7 +125,7 @@ void XYChartItem::handleGeometryChanged(const QRectF& rect) m_clipRect=rect.translated(-rect.topLeft()); setPos(rect.topLeft()); - if(isEmpty()) return; + if(isEmpty()) return; QVector points = calculateGeometryPoints(); updatePoints(points); update();