diff --git a/examples/examples.pro b/examples/examples.pro index e49f7b2..2ff04ea 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -17,7 +17,7 @@ SUBDIRS += \ splinechart \ stackedbarchart \ stackedbarchartdrilldown \ - #tablemodelchart \ + tablemodelchart \ zoomlinechart diff --git a/examples/tablemodelchart/customtablemodel.cpp b/examples/tablemodelchart/customtablemodel.cpp index 660a3a3..f4516ff 100644 --- a/examples/tablemodelchart/customtablemodel.cpp +++ b/examples/tablemodelchart/customtablemodel.cpp @@ -98,7 +98,7 @@ QVariant CustomTableModel::headerData (int section, Qt::Orientation orientation, } } else - return QString("%1").arg(section + 1); + return QString("%1").arg(section /*+ 1*/); } QVariant CustomTableModel::data(const QModelIndex & index, int role) const @@ -203,7 +203,10 @@ bool CustomTableModel::insertRows ( int row, int count, const QModelIndex & pare { if (i - 1 >= 0) { - difference = (int)((qAbs(m_data[i]->at(k) - m_data[row - 1]->at(k)))/count); + if (row > 0) + difference = (int)((qAbs(m_data[i]->at(k) - m_data[row - 1]->at(k)))/count); + else + difference = (int)((qAbs(m_data[i]->at(k)/count))); dataVec->replace(k, m_data[i - 1]->at(k) + qrand()%qMax(1, difference)); } else diff --git a/examples/tablemodelchart/tablewidget.cpp b/examples/tablemodelchart/tablewidget.cpp index e664f23..374e8d8 100644 --- a/examples/tablemodelchart/tablewidget.cpp +++ b/examples/tablemodelchart/tablewidget.cpp @@ -42,14 +42,15 @@ TableWidget::TableWidget(QWidget *parent) // create simple model for storing data // user's table data model m_model = new CustomTableModel; - tableView = new QTableView; - tableView->setModel(m_model); - tableView->setMinimumHeight(240); + m_tableView = new QTableView; + m_tableView->setModel(m_model); + m_tableView->setMinimumHeight(240); // tableView->setMinimumSize(340, 480); // tableView->setItemDelegate(new QStyledItemDelegate); - chartView = new QChartView(this); - chartView->setRenderHint(QPainter::Antialiasing); - chartView->setMinimumSize(640, 480); + m_chart = new QChart; + m_chartView = new QChartView(m_chart); + m_chartView->setRenderHint(QPainter::Antialiasing); + m_chartView->setMinimumSize(640, 480); // create // QLineSeries* series = new QLineSeries; @@ -74,59 +75,59 @@ TableWidget::TableWidget(QWidget *parent) QPushButton* removeRowButton = new QPushButton("Remove row"); connect(removeRowButton, SIGNAL(clicked()), this, SLOT(removeRow())); - linesCountSpinBox = new QSpinBox; - linesCountSpinBox->setRange(1, 10); - linesCountSpinBox->setValue(1); + m_linesCountSpinBox = new QSpinBox; + m_linesCountSpinBox->setRange(1, 10); + m_linesCountSpinBox->setValue(1); // buttons layout QVBoxLayout* buttonsLayout = new QVBoxLayout; - buttonsLayout->addWidget(linesCountSpinBox); + buttonsLayout->addWidget(m_linesCountSpinBox); buttonsLayout->addWidget(addRowAboveButton); buttonsLayout->addWidget(addRowBelowButton); buttonsLayout->addWidget(removeRowButton); buttonsLayout->addStretch(); // chart type radio buttons - lineRadioButton = new QRadioButton("Line"); - splineRadioButton = new QRadioButton("Spline"); - scatterRadioButton = new QRadioButton("Scatter"); - pieRadioButton = new QRadioButton("Pie"); - areaRadioButton = new QRadioButton("Area"); - barRadioButton = new QRadioButton("Bar"); - - connect(lineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); - connect(splineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); - connect(scatterRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); - connect(pieRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); - connect(areaRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); - connect(barRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); - lineRadioButton->setChecked(true); + m_lineRadioButton = new QRadioButton("Line"); + m_splineRadioButton = new QRadioButton("Spline"); + m_scatterRadioButton = new QRadioButton("Scatter"); + m_pieRadioButton = new QRadioButton("Pie"); + m_areaRadioButton = new QRadioButton("Area"); + m_barRadioButton = new QRadioButton("Bar"); + + connect(m_lineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); + connect(m_splineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); + connect(m_scatterRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); + connect(m_pieRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); + connect(m_areaRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); + connect(m_barRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType())); + m_lineRadioButton->setChecked(true); // radio buttons layout QVBoxLayout* radioLayout = new QVBoxLayout; - radioLayout->addWidget(lineRadioButton); - radioLayout->addWidget(splineRadioButton); - radioLayout->addWidget(scatterRadioButton); - radioLayout->addWidget(pieRadioButton); - radioLayout->addWidget(areaRadioButton); - radioLayout->addWidget(barRadioButton); + radioLayout->addWidget(m_lineRadioButton); + radioLayout->addWidget(m_splineRadioButton); + radioLayout->addWidget(m_scatterRadioButton); + radioLayout->addWidget(m_pieRadioButton); + radioLayout->addWidget(m_areaRadioButton); + radioLayout->addWidget(m_barRadioButton); radioLayout->addStretch(); // create main layout QGridLayout* mainLayout = new QGridLayout; - mainLayout->addLayout(buttonsLayout, 1, 0); - mainLayout->addLayout(radioLayout, 2, 0); - mainLayout->addWidget(tableView, 1, 1); - mainLayout->addWidget(chartView, 2, 1); + mainLayout->addLayout(buttonsLayout, 1, 1); + mainLayout->addLayout(radioLayout, 2, 1); + mainLayout->addWidget(m_tableView, 1, 0); + mainLayout->addWidget(m_chartView, 2, 0); setLayout(mainLayout); - lineRadioButton->setFocus(); + m_lineRadioButton->setFocus(); } void TableWidget::addRowAbove() { // m_model->insertRow(m_model->rowCount()); // m_model->insertRow(tableView->currentIndex().row()); - m_model->insertRows(tableView->currentIndex().row(), linesCountSpinBox->value()); + m_model->insertRows(m_tableView->currentIndex().row(), m_linesCountSpinBox->value()); } @@ -134,7 +135,7 @@ void TableWidget::addRowBelow() { // m_model->insertRow(m_model->rowCount()); // m_model->insertRow(tableView->currentIndex().row() + 1); - m_model->insertRows(tableView->currentIndex().row() + 1, linesCountSpinBox->value()); + m_model->insertRows(m_tableView->currentIndex().row() + 1, m_linesCountSpinBox->value()); } @@ -142,14 +143,14 @@ void TableWidget::removeRow() { // m_model->removeRow(m_model->rowCount() - 1); // m_model->removeRow(tableView->currentIndex().row()); - m_model->removeRows(tableView->currentIndex().row(), qMin(m_model->rowCount() - tableView->currentIndex().row(), linesCountSpinBox->value())); + m_model->removeRows(m_tableView->currentIndex().row(), qMin(m_model->rowCount() - m_tableView->currentIndex().row(), m_linesCountSpinBox->value())); } void TableWidget::updateChartType() { - chartView->removeAllSeries(); + m_chart->removeAllSeries(); - if (lineRadioButton->isChecked()) + if (m_lineRadioButton->isChecked()) { QPen pen; pen.setWidth(2); @@ -157,15 +158,15 @@ void TableWidget::updateChartType() QColor seriesColor("#8FBC8F"); // series 1 - series = new QLineSeries; - series->setModel(m_model); - series->setModelMapping(0,1, Qt::Vertical); - series->setModelMappingShift(1, 4); + m_series = new QLineSeries; + m_series->setModel(m_model); + m_series->setModelMapping(0,1, Qt::Vertical); + m_series->setModelMappingShift(3, 3); // series->setModelMapping(0,1, Qt::Horizontal); pen.setColor(seriesColor); - series->setPen(pen); - chartView->addSeries(series); + m_series->setPen(pen); + m_chart->addSeries(m_series); for (int i = 1; i <=4; i++) { m_model->setData(m_model->index(i, 0), seriesColor , Qt::BackgroundRole); @@ -176,15 +177,16 @@ void TableWidget::updateChartType() seriesColor = QColor("#1E90FF"); // series 2 - series = new QLineSeries; - series->setModel(m_model); - series->setModelMapping(2,3, Qt::Vertical); + m_series = new QLineSeries; + m_series->setModel(m_model); + m_series->setModelMapping(2,3, Qt::Vertical); // series->setModelMapping(2,3, Qt::Horizontal); pen.setColor(seriesColor); - series->setPen(pen); - chartView->addSeries(series); + m_series->setPen(pen); +// m_chart->addSeries(m_series); - chartView->axisX()->setRange(0, 500); + m_chart->axisX()->setRange(0, 500); + m_chart->axisY()->setRange(0, 120); for (int i = 0; i < m_model->rowCount(); i++) { @@ -198,56 +200,56 @@ void TableWidget::updateChartType() //// series->setModelMapping(4,5, Qt::Horizontal); // chartView->addSeries(series); } - else if (splineRadioButton->isChecked()) + else if (m_splineRadioButton->isChecked()) { // series 1 - series = new QSplineSeries; - series->setModel(m_model); - series->setModelMapping(0,1, Qt::Vertical); - series->setModelMappingShift(1, 4); + m_series = new QSplineSeries; + m_series->setModel(m_model); + m_series->setModelMapping(0,1, Qt::Vertical); + m_series->setModelMappingShift(1, 4); // series->setModelMapping(0,1, Qt::Horizontal); - chartView->addSeries(series); + m_chart->addSeries(m_series); // series 2 - series = new QSplineSeries; - series->setModel(m_model); - series->setModelMapping(2,3, Qt::Vertical); - series->setModelMappingShift(0, 0); + m_series = new QSplineSeries; + m_series->setModel(m_model); + m_series->setModelMapping(2,3, Qt::Vertical); + m_series->setModelMappingShift(0, 0); // series->setModelMapping(2,3, Qt::Horizontal); - chartView->addSeries(series); + m_chart->addSeries(m_series); // series 3 - series = new QSplineSeries; - series->setModel(m_model); - series->setModelMapping(4,5, Qt::Vertical); - series->setModelMappingShift(0, 0); + m_series = new QSplineSeries; + m_series->setModel(m_model); + m_series->setModelMapping(4,5, Qt::Vertical); + m_series->setModelMappingShift(0, 0); // series->setModelMapping(4,5, Qt::Horizontal); - chartView->addSeries(series); + m_chart->addSeries(m_series); } - else if (scatterRadioButton->isChecked()) + else if (m_scatterRadioButton->isChecked()) { // series 1 - series = new QScatterSeries; - series->setModel(m_model); - series->setModelMapping(0,1, Qt::Vertical); + m_series = new QScatterSeries; + m_series->setModel(m_model); + m_series->setModelMapping(0,1, Qt::Vertical); // series->setModelMapping(0,1, Qt::Horizontal); - chartView->addSeries(series); + m_chart->addSeries(m_series); // series 2 - series = new QScatterSeries; - series->setModel(m_model); - series->setModelMapping(2,3, Qt::Vertical); + m_series = new QScatterSeries; + m_series->setModel(m_model); + m_series->setModelMapping(2,3, Qt::Vertical); // series->setModelMapping(2,3, Qt::Horizontal); - chartView->addSeries(series); + m_chart->addSeries(m_series); // series 3 - series = new QScatterSeries; - series->setModel(m_model); - series->setModelMapping(4,5, Qt::Vertical); + m_series = new QScatterSeries; + m_series->setModel(m_model); + m_series->setModelMapping(4,5, Qt::Vertical); // series->setModelMapping(4,5, Qt::Horizontal); - chartView->addSeries(series); + m_chart->addSeries(m_series); } - else if (pieRadioButton->isChecked()) + else if (m_pieRadioButton->isChecked()) { // pie 1 QPieSeries* pieSeries = new QPieSeries; @@ -256,7 +258,7 @@ void TableWidget::updateChartType() pieSeries->setLabelsVisible(true); pieSeries->setPieSize(0.4); pieSeries->setPiePosition(0.2, 0.35); - chartView->addSeries(pieSeries); + m_chart->addSeries(pieSeries); // pie 2 pieSeries = new QPieSeries; @@ -265,7 +267,7 @@ void TableWidget::updateChartType() pieSeries->setLabelsVisible(true); pieSeries->setPieSize(0.4); pieSeries->setPiePosition(0.8, 0.35); - chartView->addSeries(pieSeries); + m_chart->addSeries(pieSeries); // pie 3 pieSeries = new QPieSeries; @@ -274,9 +276,9 @@ void TableWidget::updateChartType() pieSeries->setLabelsVisible(true); pieSeries->setPieSize(0.4); pieSeries->setPiePosition(0.5, 0.65); - chartView->addSeries(pieSeries); + m_chart->addSeries(pieSeries); } - else if (areaRadioButton->isChecked()) + else if (m_areaRadioButton->isChecked()) { QLineSeries* upperLineSeries = new QLineSeries; upperLineSeries->setModel(m_model); @@ -285,15 +287,15 @@ void TableWidget::updateChartType() lowerLineSeries->setModel(m_model); lowerLineSeries->setModelMapping(2, 3, Qt::Vertical); QAreaSeries* areaSeries = new QAreaSeries(upperLineSeries, lowerLineSeries); - chartView->addSeries(areaSeries); + m_chart->addSeries(areaSeries); } - else if (barRadioButton->isChecked()) + else if (m_barRadioButton->isChecked()) { QBarSeries* barSeries = new QBarSeries(QStringList()); barSeries->setModel(m_model); barSeries->setModelMapping(5, 2, 4, Qt::Vertical); barSeries->setToolTipEnabled(true); - chartView->addSeries(barSeries); + m_chart->addSeries(barSeries); } // series->setModel(m_model); diff --git a/examples/tablemodelchart/tablewidget.h b/examples/tablemodelchart/tablewidget.h index 82d9f89..7af0cb0 100644 --- a/examples/tablemodelchart/tablewidget.h +++ b/examples/tablemodelchart/tablewidget.h @@ -49,17 +49,18 @@ public: void updateChartType(); private: - QChartView* chartView; - QXYSeries* series; + QChartView* m_chartView; + QChart* m_chart; + QXYSeries* m_series; CustomTableModel* m_model; - QTableView* tableView; - QRadioButton* lineRadioButton; - QRadioButton* splineRadioButton; - QRadioButton* scatterRadioButton; - QRadioButton* pieRadioButton; - QRadioButton* areaRadioButton; - QRadioButton* barRadioButton; - QSpinBox* linesCountSpinBox; + QTableView* m_tableView; + QRadioButton* m_lineRadioButton; + QRadioButton* m_splineRadioButton; + QRadioButton* m_scatterRadioButton; + QRadioButton* m_pieRadioButton; + QRadioButton* m_areaRadioButton; + QRadioButton* m_barRadioButton; + QSpinBox* m_linesCountSpinBox; }; #endif // TABLEWIDGET_H diff --git a/src/xychart/qxyseries.cpp b/src/xychart/qxyseries.cpp index 9c86826..548484b 100644 --- a/src/xychart/qxyseries.cpp +++ b/src/xychart/qxyseries.cpp @@ -345,10 +345,10 @@ void QXYSeries::modelDataAboutToBeAdded(QModelIndex parent, int start, int end) // if the number of items currently is equal the m_mapCount then some needs to be removed from xychartitem // internal storage before new ones can be added - int itemsToRemove = qMin(count() - (start - m_mapFirst), end - start + 1); + int itemsToRemove = qMin(count() - qMax(start - m_mapFirst, 0), end - start + 1); if (m_mapCount == count()) { for (int i = 0; i < itemsToRemove; i++) - emit pointRemoved(count() - 1 - i); + emit pointRemoved(qMin(end, count()) - i); } } } else { @@ -372,14 +372,16 @@ void QXYSeries::modelDataAdded(QModelIndex parent, int start, int end) // the added data is in the mapped area or before it // update needed if (count() > 0) { - for (int i = 0; i < qMin(m_mapCount - (start - m_mapFirst), end - start + 1); i++) - emit pointAdded(qMax(start + i - m_mapFirst, 0)); + int toBeAdded = qMin(m_mapCount - (start - m_mapFirst), end - start + 1); + for (int i = 0; i < toBeAdded; i++) + if (start + i >= m_mapFirst) + emit pointAdded(start + i); } } } else { // map is not limited (it included all the items starting from m_mapFirst till the end of model) for (int i = 0; i < end - start + 1; i++) - emit pointAdded(qMax(start + i - m_mapFirst, 0)); + emit pointAdded(start + i); } } @@ -403,12 +405,12 @@ void QXYSeries::modelDataAboutToBeRemoved(QModelIndex parent, int start, int end // the max is the current number of items in storage (count()) int itemsToRemove = qMin(count(), qMin(end, m_mapFirst + m_mapCount - 1) - start + 1); for (int i = 0; i < itemsToRemove; i++) - emit pointRemoved(qMax(start - m_mapFirst, 0)); + emit pointRemoved(start); } } else { // map is not limited (it included all the items starting from m_mapFirst till the end of model) for (int i = 0; i < end - start + 1; i++) - emit pointRemoved(qMax(start - m_mapFirst, 0)); + emit pointRemoved(start); } } @@ -428,18 +430,22 @@ void QXYSeries::modelDataRemoved(QModelIndex parent, int start, int end) } else { // if the current items count in the whole model is bigger than the index of the last item // that was removed than it means there are some extra items available + + int removedItemsCount = qMin(count(), qMin(end, m_mapFirst + m_mapCount - 1) - start + 1); int extraItemsAvailable = 0; if (m_mapOrientation == Qt::Vertical) { - extraItemsAvailable = qMax(m_model->rowCount() - end, 0); +// int temp1 = m_model->rowCount(); +// int temp2 = (end - start + 1); +// int temp3 = qMax(end + 1, m_mapFirst + m_mapCount); + extraItemsAvailable = qMax(m_model->rowCount() + (end - start + 1) - qMax(end + 1, m_mapFirst + m_mapCount), 0); } else { - extraItemsAvailable = qMax(m_model->columnCount() - end, 0); + extraItemsAvailable = qMax(m_model->columnCount() + (end - start + 1) - qMax(end + 1, m_mapFirst + m_mapCount), 0); } // if there are excess items available (below the mapped area) use them to repopulate mapped area - int removedItemsCount = qMin(count(), qMin(end, m_mapFirst + m_mapCount - 1) - qMax(start, m_mapFirst) + 1); int toBeAdded = qMin(extraItemsAvailable, removedItemsCount); for (int k = 0; k < toBeAdded; k++) - emit pointAdded(qMax(start - m_mapFirst, m_mapFirst) + k); + emit pointAdded(m_mapFirst + m_mapCount - removedItemsCount + k); } } else { // data was removed from XYSeries interal storage. Nothing more to do diff --git a/src/xychart/qxyseries.h b/src/xychart/qxyseries.h index 4ce2c38..ef1c3e5 100644 --- a/src/xychart/qxyseries.h +++ b/src/xychart/qxyseries.h @@ -64,6 +64,7 @@ public: virtual void setModelMapping(int modelX, int modelY, Qt::Orientation orientation = Qt::Vertical); virtual void setModelMappingShift(int first, int count = 0); + int mapFirst() const { return m_mapFirst; } private Q_SLOTS: void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight); diff --git a/src/xychart/xychartitem.cpp b/src/xychart/xychartitem.cpp index a987367..2ae2d4c 100644 --- a/src/xychart/xychartitem.cpp +++ b/src/xychart/xychartitem.cpp @@ -105,21 +105,40 @@ void XYChartItem::setLayout(QVector &points) void XYChartItem::handlePointAdded(int index) { - Q_ASSERT(indexcount()); - Q_ASSERT(index>=0); - QPointF point = calculateGeometryPoint(index); QVector points = m_points; - points.insert(index,point); - updateLayout(m_points,points,index); + QPointF point; + if (m_series->model()) { + point = calculateGeometryPoint(index - m_series->mapFirst()); + points.insert(index - m_series->mapFirst(), point); + updateLayout(m_points, points, index - m_series->mapFirst()); + } + else { + // this checks do not work correctly if model is set + Q_ASSERT(indexcount()); + Q_ASSERT(index>=0); + point = calculateGeometryPoint(index); + points.insert(index, point); + updateLayout(m_points, points, index); + } update(); } void XYChartItem::handlePointRemoved(int index) -{ - Q_ASSERT(indexcount() + 1); - Q_ASSERT(index>=0); +{ QVector points = m_points; - points.remove(index); - updateLayout(m_points,points,index); + if (m_series->model()) { + if (index < m_series->mapFirst()) + points.remove(0); + else + points.remove(index - m_series->mapFirst()); + updateLayout(m_points, points, index - m_series->mapFirst()); + } + else { + // this checks do not work correctly if model is set + Q_ASSERT(indexcount() + 1); + Q_ASSERT(index>=0); + points.remove(index); + updateLayout(m_points, points, index); + } update(); } @@ -149,21 +168,21 @@ void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal void XYChartItem::handleGeometryChanged(const QRectF &rect) { - Q_ASSERT(rect.isValid()); - m_size=rect.size(); - m_clipRect=rect.translated(-rect.topLeft()); - setPos(rect.topLeft()); + Q_ASSERT(rect.isValid()); + m_size=rect.size(); + m_clipRect=rect.translated(-rect.topLeft()); + setPos(rect.topLeft()); if (isEmpty()) return; - QVector points = calculateGeometryPoints(); - updateLayout(m_points,points); - update(); + QVector points = calculateGeometryPoints(); + updateLayout(m_points,points); + update(); } bool XYChartItem::isEmpty() { - return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY); + return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY); } void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)