summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-04-30 15:36:19 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-05-02 10:53:05 +0300
commit13d1117087e66c77d2eea2f0a046fc556c19cb3c (patch)
treef003ec51145278cea0fd2d123da6c0478c961297
parent44b410f080c4820cea682c4d1278152d2767595c (diff)
Scatter data changing optimization.
No longer reset the entire render item array if single item changes, significantly speeding up this operation. Task-number: QTRD-2190 Change-Id: Ia3de833b761dc6f24acff581ad79668f51c3e9c5 Reviewed-by: Titta Heikkala <titta.heikkala@digia.com> Reviewed-by: Mika Salmela <mika.salmela@digia.com>
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp4
-rw-r--r--src/datavisualization/engine/bars3drenderer_p.h2
-rw-r--r--src/datavisualization/engine/scatter3dcontroller.cpp42
-rw-r--r--src/datavisualization/engine/scatter3dcontroller_p.h10
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp67
-rw-r--r--src/datavisualization/engine/scatter3drenderer_p.h2
-rw-r--r--tests/scattertest/main.cpp20
-rw-r--r--tests/scattertest/scatterchart.cpp197
-rw-r--r--tests/scattertest/scatterchart.h6
9 files changed, 311 insertions, 39 deletions
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index ec1f0c7e..ab7bb4ca 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -342,7 +342,7 @@ void Bars3DRenderer::updateRows(const QVector<Bars3DController::ChangeRow> &rows
}
}
-void Bars3DRenderer::updateItems(const QVector<Bars3DController::ChangeItem> &points)
+void Bars3DRenderer::updateItems(const QVector<Bars3DController::ChangeItem> &items)
{
int minRow = m_axisCacheZ.min();
int maxRow = m_axisCacheZ.max();
@@ -352,7 +352,7 @@ void Bars3DRenderer::updateItems(const QVector<Bars3DController::ChangeItem> &po
const QBar3DSeries *prevSeries = 0;
const QBarDataArray *dataArray = 0;
- foreach (Bars3DController::ChangeItem item, points) {
+ foreach (Bars3DController::ChangeItem item, items) {
const int row = item.point.x();
const int col = item.point.y();
if (row < minRow || row > maxRow || col < minCol || col > maxCol)
diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h
index ddea546e..8e39ee11 100644
--- a/src/datavisualization/engine/bars3drenderer_p.h
+++ b/src/datavisualization/engine/bars3drenderer_p.h
@@ -118,7 +118,7 @@ public:
void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
void updateRows(const QVector<Bars3DController::ChangeRow> &rows);
- void updateItems(const QVector<Bars3DController::ChangeItem> &points);
+ void updateItems(const QVector<Bars3DController::ChangeItem> &items);
void updateScene(Q3DScene *scene);
void render(GLuint defaultFboHandle = 0);
diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp
index 05c0efe7..2d38a4a7 100644
--- a/src/datavisualization/engine/scatter3dcontroller.cpp
+++ b/src/datavisualization/engine/scatter3dcontroller.cpp
@@ -71,6 +71,12 @@ void Scatter3DController::synchDataToRenderer()
Abstract3DController::synchDataToRenderer();
// Notify changes to renderer
+ if (m_changeTracker.itemChanged) {
+ m_renderer->updateItems(m_changedItems);
+ m_changeTracker.itemChanged = false;
+ m_changedItems.clear();
+ }
+
if (m_changeTracker.selectedItemChanged) {
m_renderer->updateSelectedItem(m_selectedItem, m_selectedItemSeries);
m_changeTracker.selectedItemChanged = false;
@@ -144,17 +150,35 @@ void Scatter3DController::handleItemsAdded(int startIndex, int count)
void Scatter3DController::handleItemsChanged(int startIndex, int count)
{
- Q_UNUSED(startIndex)
- Q_UNUSED(count)
QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series();
- if (series->isVisible()) {
- adjustAxisRanges();
- m_isDataDirty = true;
- series->d_ptr->markItemLabelDirty();
+ int oldChangeCount = m_changedItems.size();
+ if (!oldChangeCount)
+ m_changedItems.reserve(count);
+
+ for (int i = 0; i < count; i++) {
+ bool newItem = true;
+ int candidate = startIndex + i;
+ for (int j = 0; j < oldChangeCount; j++) {
+ const ChangeItem &oldChangeItem = m_changedItems.at(j);
+ if (oldChangeItem.index == candidate && series == oldChangeItem.series) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem) {
+ ChangeItem newChangeItem = {series, candidate};
+ m_changedItems.append(newChangeItem);
+ if (series == m_selectedItemSeries && m_selectedItem == candidate)
+ series->d_ptr->markItemLabelDirty();
+ }
+ }
+
+ if (count) {
+ m_changeTracker.itemChanged = true;
+ if (series->isVisible())
+ adjustAxisRanges();
+ emitNeedRender();
}
- if (!m_changedSeriesList.contains(series))
- m_changedSeriesList.append(series);
- emitNeedRender();
}
void Scatter3DController::handleItemsRemoved(int startIndex, int count)
diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h
index 1194bc3a..db5a95f5 100644
--- a/src/datavisualization/engine/scatter3dcontroller_p.h
+++ b/src/datavisualization/engine/scatter3dcontroller_p.h
@@ -40,9 +40,11 @@ class QScatter3DSeries;
struct Scatter3DChangeBitField {
bool selectedItemChanged : 1;
+ bool itemChanged : 1;
Scatter3DChangeBitField() :
- selectedItemChanged(true)
+ selectedItemChanged(true),
+ itemChanged(false)
{
}
};
@@ -51,8 +53,14 @@ class QT_DATAVISUALIZATION_EXPORT Scatter3DController : public Abstract3DControl
{
Q_OBJECT
+public:
+ struct ChangeItem {
+ QScatter3DSeries *series;
+ int index;
+ };
private:
Scatter3DChangeBitField m_changeTracker;
+ QVector<ChangeItem> m_changedItems;
// Rendering
Scatter3DRenderer *m_renderer;
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index 3f91e9c3..c1705179 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -165,12 +165,6 @@ void Scatter3DRenderer::initializeOpenGL()
void Scatter3DRenderer::updateData()
{
calculateSceneScalingFactors();
- float minX = float(m_axisCacheX.min());
- float maxX = float(m_axisCacheX.max());
- float minY = float(m_axisCacheY.min());
- float maxY = float(m_axisCacheY.max());
- float minZ = float(m_axisCacheZ.min());
- float maxZ = float(m_axisCacheZ.max());
int totalDataSize = 0;
foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
@@ -185,23 +179,8 @@ void Scatter3DRenderer::updateData()
if (dataSize != renderArray.size())
renderArray.resize(dataSize);
- for (int i = 0; i < dataSize; i++) {
- QVector3D dotPos = dataArray.at(i).position();
- ScatterRenderItem &renderItem = renderArray[i];
- if ((dotPos.x() >= minX && dotPos.x() <= maxX )
- && (dotPos.y() >= minY && dotPos.y() <= maxY)
- && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
- renderItem.setPosition(dotPos);
- renderItem.setVisible(true);
- if (!dataArray.at(i).rotation().isIdentity())
- renderItem.setRotation(dataArray.at(i).rotation().normalized());
- else
- renderItem.setRotation(identityQuaternion);
- calculateTranslation(renderItem);
- } else {
- renderItem.setVisible(false);
- }
- }
+ for (int i = 0; i < dataSize; i++)
+ updateRenderItem(dataArray.at(i), renderArray[i]);
cache->setDataDirty(false);
}
}
@@ -272,6 +251,30 @@ SeriesRenderCache *Scatter3DRenderer::createNewCache(QAbstract3DSeries *series)
return new ScatterSeriesRenderCache(series, this);
}
+void Scatter3DRenderer::updateItems(const QVector<Scatter3DController::ChangeItem> &items)
+{
+ ScatterSeriesRenderCache *cache = 0;
+ const QScatter3DSeries *prevSeries = 0;
+ const QScatterDataArray *dataArray = 0;
+
+ foreach (Scatter3DController::ChangeItem item, items) {
+ QScatter3DSeries *currentSeries = item.series;
+ if (currentSeries != prevSeries) {
+ cache = static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(currentSeries));
+ prevSeries = currentSeries;
+ dataArray = item.series->dataProxy()->array();
+ // Invisible series render caches are not updated, but instead just marked dirty, so that
+ // they can be completely recalculated when they are turned visible.
+ if (!cache->isVisible() && !cache->dataDirty())
+ cache->setDataDirty(true);
+ }
+ if (cache->isVisible()) {
+ const int index = item.index;
+ updateRenderItem(dataArray->at(index), cache->renderArray()[index]);
+ }
+ }
+}
+
void Scatter3DRenderer::updateScene(Q3DScene *scene)
{
scene->activeCamera()->d_ptr->setMinYRotation(-90.0f);
@@ -1802,6 +1805,24 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color,
series = 0;
}
+void Scatter3DRenderer::updateRenderItem(const QScatterDataItem &dataItem, ScatterRenderItem &renderItem)
+{
+ QVector3D dotPos = dataItem.position();
+ if ((dotPos.x() >= m_axisCacheX.min() && dotPos.x() <= m_axisCacheX.max() )
+ && (dotPos.y() >= m_axisCacheY.min() && dotPos.y() <= m_axisCacheY.max())
+ && (dotPos.z() >= m_axisCacheZ.min() && dotPos.z() <= m_axisCacheZ.max())) {
+ renderItem.setPosition(dotPos);
+ renderItem.setVisible(true);
+ if (!dataItem.rotation().isIdentity())
+ renderItem.setRotation(dataItem.rotation().normalized());
+ else
+ renderItem.setRotation(identityQuaternion);
+ calculateTranslation(renderItem);
+ } else {
+ renderItem.setVisible(false);
+ }
+}
+
QVector3D Scatter3DRenderer::convertPositionToTranslation(const QVector3D &position) {
float xTrans = m_axisCacheX.positionAt(position.x());
float yTrans = m_axisCacheY.positionAt(position.y());
diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h
index 172d0c46..09b8dace 100644
--- a/src/datavisualization/engine/scatter3drenderer_p.h
+++ b/src/datavisualization/engine/scatter3drenderer_p.h
@@ -105,6 +105,7 @@ public:
void updateData();
void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
+ void updateItems(const QVector<Scatter3DController::ChangeItem> &items);
void updateScene(Q3DScene *scene);
QVector3D convertPositionToTranslation(const QVector3D &position);
@@ -154,6 +155,7 @@ public slots:
private:
void selectionColorToSeriesAndIndex(const QVector4D &color, int &index,
QAbstract3DSeries *&series);
+ inline void updateRenderItem(const QScatterDataItem &dataItem, ScatterRenderItem &renderItem);
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/tests/scattertest/main.cpp b/tests/scattertest/main.cpp
index 78bab934..82d025aa 100644
--- a/tests/scattertest/main.cpp
+++ b/tests/scattertest/main.cpp
@@ -123,6 +123,9 @@ int main(int argc, char **argv)
QPushButton *massiveDataTestButton = new QPushButton(widget);
massiveDataTestButton->setText(QStringLiteral("Massive data test"));
+ QPushButton *testItemChangesButton = new QPushButton(widget);
+ testItemChangesButton->setText(QStringLiteral("Test Item changing"));
+
QLinearGradient grBtoY(0, 0, 100, 0);
grBtoY.setColorAt(1.0, Qt::black);
grBtoY.setColorAt(0.67, Qt::blue);
@@ -137,6 +140,12 @@ int main(int argc, char **argv)
gradientBtoYPB->setIcon(QIcon(pm));
gradientBtoYPB->setIconSize(QSize(100, 24));
+ QLabel *fpsLabel = new QLabel(QStringLiteral(""));
+
+ QCheckBox *fpsCheckBox = new QCheckBox(widget);
+ fpsCheckBox->setText(QStringLiteral("Measure Fps"));
+ fpsCheckBox->setChecked(false);
+
QCheckBox *backgroundCheckBox = new QCheckBox(widget);
backgroundCheckBox->setText(QStringLiteral("Show background"));
backgroundCheckBox->setChecked(true);
@@ -232,9 +241,12 @@ int main(int argc, char **argv)
vLayout->addWidget(toggleSeriesVisibilityButton, 0, Qt::AlignTop);
vLayout->addWidget(changeSeriesNameButton, 0, Qt::AlignTop);
vLayout->addWidget(startTimerButton, 0, Qt::AlignTop);
- vLayout->addWidget(massiveDataTestButton, 1, Qt::AlignTop);
+ vLayout->addWidget(massiveDataTestButton, 0, Qt::AlignTop);
+ vLayout->addWidget(testItemChangesButton, 1, Qt::AlignTop);
vLayout2->addWidget(gradientBtoYPB, 0, Qt::AlignTop);
+ vLayout2->addWidget(fpsLabel, 0, Qt::AlignTop);
+ vLayout2->addWidget(fpsCheckBox, 0, Qt::AlignTop);
vLayout2->addWidget(backgroundCheckBox);
vLayout2->addWidget(gridCheckBox);
vLayout2->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")));
@@ -302,6 +314,8 @@ int main(int argc, char **argv)
&ScatterDataModifier::startStopTimer);
QObject::connect(massiveDataTestButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::massiveDataTest);
+ QObject::connect(testItemChangesButton, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::testItemChanges);
QObject::connect(gradientBtoYPB, &QPushButton::clicked, modifier,
&ScatterDataModifier::setGradient);
QObject::connect(themeButton, &QPushButton::clicked, modifier,
@@ -316,6 +330,8 @@ int main(int argc, char **argv)
QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier,
&ScatterDataModifier::changeFont);
+ QObject::connect(fpsCheckBox, &QCheckBox::stateChanged, modifier,
+ &ScatterDataModifier::setFpsMeasurement);
QObject::connect(backgroundCheckBox, &QCheckBox::stateChanged, modifier,
&ScatterDataModifier::setBackgroundEnabled);
QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier,
@@ -335,6 +351,8 @@ int main(int argc, char **argv)
&ScatterDataModifier::setMaxZ);
+ modifier->setFpsLabel(fpsLabel);
+
modifier->start();
return app.exec();
diff --git a/tests/scattertest/scatterchart.cpp b/tests/scattertest/scatterchart.cpp
index c9404736..13a0f040 100644
--- a/tests/scattertest/scatterchart.cpp
+++ b/tests/scattertest/scatterchart.cpp
@@ -134,7 +134,6 @@ void ScatterDataModifier::massiveDataTest()
xAxis->setSegmentCount(1);
yAxis->setSegmentCount(1);
zAxis->setSegmentCount(1);
- m_chart->setMeasureFps(true);
m_chart->setAxisX(xAxis);
m_chart->setAxisY(yAxis);
m_chart->setAxisZ(zAxis);
@@ -231,6 +230,187 @@ void ScatterDataModifier::massiveTestAppendAndScroll()
m_chart->axisZ()->setRange(min, max);
}
+void ScatterDataModifier::setFpsMeasurement(bool enable)
+{
+ m_chart->setMeasureFps(enable);
+}
+
+void ScatterDataModifier::testItemChanges()
+{
+ static int counter = 0;
+ const int rowCount = 12;
+ const int colCount = 10;
+ static QScatter3DSeries *series0 = 0;
+ static QScatter3DSeries *series1 = 0;
+ static QScatter3DSeries *series2 = 0;
+
+ switch (counter) {
+ case 0: {
+ qDebug() << __FUNCTION__ << counter << "Setup test";
+ foreach (QScatter3DSeries *series, m_chart->seriesList())
+ m_chart->removeSeries(series);
+ foreach (QValue3DAxis *axis, m_chart->axes())
+ m_chart->releaseAxis(axis);
+ delete series0;
+ delete series1;
+ delete series2;
+ series0 = new QScatter3DSeries;
+ series1 = new QScatter3DSeries;
+ series2 = new QScatter3DSeries;
+ populateFlatSeries(series0, rowCount, colCount, 10.0f);
+ populateFlatSeries(series1, rowCount, colCount, 30.0f);
+ populateFlatSeries(series2, rowCount, colCount, 50.0f);
+ m_chart->axisX()->setRange(3.0f, 6.0f);
+ m_chart->axisY()->setRange(0.0f, 100.0f);
+ m_chart->axisZ()->setRange(4.0f, 8.0f);
+ m_chart->addSeries(series0);
+ m_chart->addSeries(series1);
+ m_chart->addSeries(series2);
+ }
+ break;
+ case 1: {
+ qDebug() << __FUNCTION__ << counter << "Change single item, unselected";
+ int itemIndex = 3 * colCount + 5;
+ QScatterDataItem item = *series0->dataProxy()->itemAt(itemIndex);
+ item.setY(75.0f);
+ series0->dataProxy()->setItem(itemIndex, item);
+ }
+ break;
+ case 2: {
+ qDebug() << __FUNCTION__ << counter << "Change single item, selected";
+ int itemIndex = 4 * colCount + 4;
+ series1->setSelectedItem(itemIndex);
+ QScatterDataItem item = *series1->dataProxy()->itemAt(itemIndex);
+ item.setY(75.0f);
+ series1->dataProxy()->setItem(itemIndex, item);
+ }
+ break;
+ case 3: {
+ qDebug() << __FUNCTION__ << counter << "Change item outside visible area";
+ int itemIndex = 2;
+ QScatterDataItem item = *series1->dataProxy()->itemAt(itemIndex);
+ item.setY(75.0f);
+ series1->dataProxy()->setItem(itemIndex, item);
+ }
+ break;
+ case 4: {
+ qDebug() << __FUNCTION__ << counter << "Change single item from two series, unselected";
+ int itemIndex = 4 * colCount + 6;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex);
+ QScatterDataItem item1 = *series1->dataProxy()->itemAt(itemIndex);
+ item0.setY(65.0f);
+ item1.setY(85.0f);
+ series0->dataProxy()->setItem(itemIndex, item0);
+ series1->dataProxy()->setItem(itemIndex, item1);
+ }
+ break;
+ case 5: {
+ qDebug() << __FUNCTION__ << counter << "Change single item from two series, one selected";
+ int itemIndex0 = 5 * colCount + 5;
+ int itemIndex1 = 4 * colCount + 4;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex0);
+ QScatterDataItem item1 = *series1->dataProxy()->itemAt(itemIndex1);
+ item0.setY(65.0f);
+ item1.setY(85.0f);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series1->dataProxy()->setItem(itemIndex1, item1);
+ }
+ break;
+ case 6: {
+ qDebug() << __FUNCTION__ << counter << "Change single item from two series, one outside range";
+ int itemIndex0 = 6 * colCount + 6;
+ int itemIndex1 = 9 * colCount + 2;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex0);
+ QScatterDataItem item1 = *series1->dataProxy()->itemAt(itemIndex1);
+ item0.setY(65.0f);
+ item1.setY(85.0f);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series1->dataProxy()->setItem(itemIndex1, item1);
+ }
+ break;
+ case 7: {
+ qDebug() << __FUNCTION__ << counter << "Change single item from two series, both outside range";
+ int itemIndex0 = 1 * colCount + 3;
+ int itemIndex1 = 9 * colCount + 2;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex0);
+ QScatterDataItem item1 = *series1->dataProxy()->itemAt(itemIndex1);
+ item0.setY(65.0f);
+ item1.setY(85.0f);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series1->dataProxy()->setItem(itemIndex1, item1);
+ }
+ break;
+ case 8: {
+ qDebug() << __FUNCTION__ << counter << "Change item to same value as previously";
+ int itemIndex0 = 5 * colCount + 7;
+ int itemIndex1 = 4 * colCount + 7;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex0);
+ QScatterDataItem item1 = *series1->dataProxy()->itemAt(itemIndex1);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series1->dataProxy()->setItem(itemIndex1, item1);
+ }
+ break;
+ case 9: {
+ qDebug() << __FUNCTION__ << counter << "Change 3 items on each series";
+ int itemIndex0 = 5 * colCount + 6;
+ int itemIndex1 = 4 * colCount + 6;
+ QScatterDataItem item00 = *series0->dataProxy()->itemAt(itemIndex0);
+ QScatterDataItem item01 = *series0->dataProxy()->itemAt(itemIndex0 + 1);
+ QScatterDataItem item02 = *series0->dataProxy()->itemAt(itemIndex0 + 2);
+ QScatterDataItem item10 = *series1->dataProxy()->itemAt(itemIndex1);
+ QScatterDataItem item11 = *series1->dataProxy()->itemAt(itemIndex1 + 1);
+ QScatterDataItem item12 = *series1->dataProxy()->itemAt(itemIndex1 + 2);
+ item00.setY(65.0f);
+ item01.setY(70.0f);
+ item02.setY(75.0f);
+ item10.setY(80.0f);
+ item11.setY(85.0f);
+ item12.setY(90.0f);
+ series0->dataProxy()->setItem(itemIndex0, item00);
+ series0->dataProxy()->setItem(itemIndex0 + 1, item01);
+ series0->dataProxy()->setItem(itemIndex0 + 2, item02);
+ series1->dataProxy()->setItem(itemIndex1, item10);
+ series1->dataProxy()->setItem(itemIndex1 + 1, item11);
+ series1->dataProxy()->setItem(itemIndex1 + 2, item12);
+ }
+ break;
+ case 10: {
+ qDebug() << __FUNCTION__ << counter << "Level the field single item at a time";
+ QScatterDataItem item;
+ for (int i = 0; i < rowCount; i++) {
+ for (int j = 0; j < colCount; j++) {
+ int itemIndex = i * colCount + j;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex);
+ QScatterDataItem item1 = *series1->dataProxy()->itemAt(itemIndex);
+ QScatterDataItem item2 = *series2->dataProxy()->itemAt(itemIndex);
+ item0.setY(10.0f);
+ item1.setY(15.0f);
+ item2.setY(20.0f);
+ series0->dataProxy()->setItem(itemIndex, item0);
+ series1->dataProxy()->setItem(itemIndex, item1);
+ series2->dataProxy()->setItem(itemIndex, item2);
+ }
+ }
+ }
+ break;
+ case 11: {
+ qDebug() << __FUNCTION__ << counter << "Change same items multiple times";
+ int itemIndex0 = 6 * colCount + 6;
+ QScatterDataItem item0 = *series0->dataProxy()->itemAt(itemIndex0);
+ item0.setY(90.0f);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ series0->dataProxy()->setItem(itemIndex0, item0);
+ }
+ break;
+ default:
+ qDebug() << __FUNCTION__ << "Resetting test";
+ counter = -1;
+ }
+ counter++;
+}
+
void ScatterDataModifier::addData()
{
// Add labels
@@ -673,7 +853,8 @@ void ScatterDataModifier::handleAxisZChanged(QValue3DAxis *axis)
void ScatterDataModifier::handleFpsChange(qreal fps)
{
- qDebug() << "FPS:" << fps;
+ static const QString fpsPrefix(QStringLiteral("FPS: "));
+ m_fpsLabel->setText(fpsPrefix + QString::number(qRound(fps)));
}
void ScatterDataModifier::changeShadowQuality(int quality)
@@ -757,3 +938,15 @@ QScatter3DSeries *ScatterDataModifier::createAndAddSeries()
return series;
}
+
+void ScatterDataModifier::populateFlatSeries(QScatter3DSeries *series, int rows, int columns,
+ float value)
+{
+ QScatterDataArray *dataArray = new QScatterDataArray;
+ dataArray->resize(rows * columns);
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < columns; j++)
+ (*dataArray)[i * columns + j].setPosition(QVector3D(float(i), value, float(j)));
+ }
+ series->dataProxy()->resetArray(dataArray);
+}
diff --git a/tests/scattertest/scatterchart.h b/tests/scattertest/scatterchart.h
index 66f69625..f239cb73 100644
--- a/tests/scattertest/scatterchart.h
+++ b/tests/scattertest/scatterchart.h
@@ -25,6 +25,7 @@
#include <QFont>
#include <QDebug>
#include <QTimer>
+#include <QLabel>
using namespace QtDataVisualization;
@@ -55,6 +56,9 @@ public:
void massiveDataTest();
void massiveTestScroll();
void massiveTestAppendAndScroll();
+ void setFpsMeasurement(bool enable);
+ void setFpsLabel(QLabel *fpsLabel) { m_fpsLabel = fpsLabel; }
+ void testItemChanges();
public slots:
void changeShadowQuality(int quality);
@@ -91,6 +95,7 @@ signals:
private:
QVector3D randVector();
QScatter3DSeries *createAndAddSeries();
+ void populateFlatSeries(QScatter3DSeries *series, int rows, int columns, float value);
Q3DScatter *m_chart;
int m_fontSize;
@@ -99,6 +104,7 @@ private:
int m_selectedItem;
QScatter3DSeries *m_targetSeries;
QScatterDataArray m_massiveTestCacheArray;
+ QLabel *m_fpsLabel;
};
#endif