From 44b410f080c4820cea682c4d1278152d2767595c Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 29 Apr 2014 14:50:04 +0300 Subject: Bar data item and row changing optimizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No longer reset the entire render item array if single item or row changes, significantly speeding up these operations. Task-number: QTRD-2190 Change-Id: I44b8abd384003e252e4bfc34af5d73ac1dee34bf Reviewed-by: Tomi Korpipää Reviewed-by: Mika Salmela --- src/datavisualization/engine/bars3dcontroller.cpp | 81 +++++-- src/datavisualization/engine/bars3dcontroller_p.h | 18 +- src/datavisualization/engine/bars3drenderer.cpp | 168 +++++++++---- src/datavisualization/engine/bars3drenderer_p.h | 6 + src/datavisualization/engine/scatter3drenderer.cpp | 6 +- .../engine/surface3dcontroller.cpp | 35 ++- src/datavisualization/engine/surface3drenderer.cpp | 19 +- src/datavisualization/engine/surface3drenderer_p.h | 2 +- tests/barstest/chart.cpp | 269 ++++++++++++++++++--- tests/barstest/chart.h | 6 +- tests/barstest/main.cpp | 13 +- tests/surfacetest/graphmodifier.cpp | 4 +- 12 files changed, 494 insertions(+), 133 deletions(-) diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 38870115..99fa8223 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -83,6 +83,18 @@ void Bars3DController::synchDataToRenderer() Abstract3DController::synchDataToRenderer(); // Notify changes to renderer + if (m_changeTracker.rowsChanged) { + m_renderer->updateRows(m_changedRows); + m_changeTracker.rowsChanged = false; + m_changedRows.clear(); + } + + if (m_changeTracker.itemChanged) { + m_renderer->updateItems(m_changedItems); + m_changeTracker.itemChanged = false; + m_changedItems.clear(); + } + if (m_changeTracker.multiSeriesScalingChanged) { m_renderer->updateMultiSeriesScaling(m_isMultiSeriesUniform); m_changeTracker.multiSeriesScalingChanged = false; @@ -131,17 +143,39 @@ void Bars3DController::handleRowsAdded(int startIndex, int count) void Bars3DController::handleRowsChanged(int startIndex, int count) { - Q_UNUSED(startIndex) - Q_UNUSED(count) QBar3DSeries *series = static_cast(sender())->series(); - if (series->isVisible()) { - adjustAxisRanges(); - m_isDataDirty = true; - series->d_ptr->markItemLabelDirty(); + int oldChangeCount = m_changedRows.size(); + if (!oldChangeCount) + m_changedRows.reserve(count); + + int selectedRow = m_selectedBar.x(); + for (int i = 0; i < count; i++) { + bool newItem = true; + int candidate = startIndex + i; + for (int j = 0; j < oldChangeCount; j++) { + const ChangeRow &oldChangeItem = m_changedRows.at(j); + if (oldChangeItem.row == candidate && series == oldChangeItem.series) { + newItem = false; + break; + } + } + if (newItem) { + ChangeRow newChangeItem = {series, candidate}; + m_changedRows.append(newChangeItem); + if (series == m_selectedBarSeries && selectedRow == candidate) + series->d_ptr->markItemLabelDirty(); + } + } + if (count) { + m_changeTracker.rowsChanged = true; + + if (series->isVisible()) + adjustAxisRanges(); + + // Clear selection unless still valid (row length might have changed) + setSelectedBar(m_selectedBar, m_selectedBarSeries, false); + emitNeedRender(); } - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); - emitNeedRender(); } void Bars3DController::handleRowsRemoved(int startIndex, int count) @@ -199,17 +233,28 @@ void Bars3DController::handleRowsInserted(int startIndex, int count) void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) { - Q_UNUSED(rowIndex) - Q_UNUSED(columnIndex) QBar3DSeries *series = static_cast(sender())->series(); - if (series->isVisible()) { - adjustAxisRanges(); - m_isDataDirty = true; - series->d_ptr->markItemLabelDirty(); + + bool newItem = true; + QPoint candidate(rowIndex, columnIndex); + foreach (ChangeItem item, m_changedItems) { + if (item.point == candidate && item.series == series) { + newItem = false; + break; + } + } + + if (newItem) { + ChangeItem newItem = {series, candidate}; + m_changedItems.append(newItem); + m_changeTracker.itemChanged = true; + + if (series == m_selectedBarSeries && m_selectedBar == candidate) + series->d_ptr->markItemLabelDirty(); + if (series->isVisible()) + adjustAxisRanges(); + emitNeedRender(); } - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); - emitNeedRender(); } void Bars3DController::handleDataRowLabelsChanged() diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 33928306..00eda402 100644 --- a/src/datavisualization/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -42,12 +42,16 @@ struct Bars3DChangeBitField { bool multiSeriesScalingChanged : 1; bool barSpecsChanged : 1; bool selectedBarChanged : 1; + bool rowsChanged : 1; + bool itemChanged : 1; Bars3DChangeBitField() : slicingActiveChanged(true), multiSeriesScalingChanged(true), barSpecsChanged(true), - selectedBarChanged(true) + selectedBarChanged(true), + rowsChanged(false), + itemChanged(false) { } }; @@ -56,8 +60,20 @@ class QT_DATAVISUALIZATION_EXPORT Bars3DController : public Abstract3DController { Q_OBJECT +public: + struct ChangeItem { + QBar3DSeries *series; + QPoint point; + }; + struct ChangeRow { + QBar3DSeries *series; + int row; + }; + private: Bars3DChangeBitField m_changeTracker; + QVector m_changedItems; + QVector m_changedRows; // Interaction QPoint m_selectedBar; // Points to row & column in data window. diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 01fcebb2..ec1f0c7e 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -95,7 +95,8 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_clickedPosition(Bars3DController::invalidSelectionPosition()), m_keepSeriesUniform(false), m_haveUniformColorSeries(false), - m_haveGradientSeries(false) + m_haveGradientSeries(false), + m_zeroPosition(0.0f) { m_axisCacheY.setScale(2.0f); m_axisCacheY.setTranslate(-1.0f); @@ -159,7 +160,6 @@ void Bars3DRenderer::updateData() int maxCol = m_axisCacheX.max(); int newRows = maxRow - minRow + 1; int newColumns = maxCol - minCol + 1; - int updateSize = 0; int dataRowCount = 0; int maxDataRowCount = 0; @@ -187,8 +187,7 @@ void Bars3DRenderer::updateData() calculateSceneScalingFactors(); } - const QValue3DAxisFormatter *axisFormatter = m_axisCacheY.formatter(); - float zeroPosition = axisFormatter->positionAt(0.0f); + m_zeroPosition = m_axisCacheY.formatter()->positionAt(0.0f); foreach (SeriesRenderCache *baseCache, m_renderCacheList) { BarSeriesRenderCache *cache = static_cast(baseCache); @@ -212,50 +211,12 @@ void Bars3DRenderer::updateData() if (maxDataRowCount < dataRowCount) maxDataRowCount = qMin(dataRowCount, newRows); int dataRowIndex = minRow; - GLfloat heightValue = 0.0f; for (int i = 0; i < newRows; i++) { - int j = 0; BarRenderItemRow &renderRow = renderArray[i]; - if (dataRowIndex < dataRowCount) { - const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex); - updateSize = qMin((dataRow->size() - minCol), renderRow.size()); - if (dataRow) { - int dataColIndex = minCol; - for (; j < updateSize ; j++) { - float value = dataRow->at(dataColIndex).value(); - heightValue = axisFormatter->positionAt(value); - if (m_noZeroInRange) { - if (m_hasNegativeValues) { - heightValue = -1.0f + heightValue; - if (heightValue > 0.0f) - heightValue = 0.0f; - } else { - if (heightValue < 0.0f) - heightValue = 0.0f; - } - } else { - heightValue -= zeroPosition; - } - renderRow[j].setValue(value); - renderRow[j].setHeight(heightValue); - - float angle = dataRow->at(dataColIndex).rotation(); - if (angle) { - renderRow[j].setRotation( - QQuaternion::fromAxisAndAngle( - upVector, angle)); - } else { - renderRow[j].setRotation(identityQuaternion); - } - dataColIndex++; - } - } - } - for (; j < newColumns; j++) { - renderRow[j].setValue(0.0f); - renderRow[j].setHeight(0.0f); - renderRow[j].setRotation(identityQuaternion); - } + const QBarDataRow *dataRow = 0; + if (dataRowIndex < dataRowCount) + dataRow = dataProxy->rowAt(dataRowIndex); + updateRenderRow(dataRow, renderRow); dataRowIndex++; } cache->setDataDirty(false); @@ -268,6 +229,56 @@ void Bars3DRenderer::updateData() m_selectedSeriesCache ? m_selectedSeriesCache->series() : 0); } +void Bars3DRenderer::updateRenderRow(const QBarDataRow *dataRow, BarRenderItemRow &renderRow) +{ + int j = 0; + int renderRowSize = renderRow.size(); + int startIndex = m_axisCacheX.min(); + + if (dataRow) { + int updateSize = qMin((dataRow->size() - startIndex), renderRowSize); + int dataColIndex = startIndex; + for (; j < updateSize ; j++) { + updateRenderItem(dataRow->at(dataColIndex), renderRow[j]); + dataColIndex++; + } + } + for (; j < renderRowSize; j++) { + renderRow[j].setValue(0.0f); + renderRow[j].setHeight(0.0f); + renderRow[j].setRotation(identityQuaternion); + } +} + +void Bars3DRenderer::updateRenderItem(const QBarDataItem &dataItem, BarRenderItem &renderItem) +{ + float value = dataItem.value(); + float heightValue = m_axisCacheY.formatter()->positionAt(value); + if (m_noZeroInRange) { + if (m_hasNegativeValues) { + heightValue = -1.0f + heightValue; + if (heightValue > 0.0f) + heightValue = 0.0f; + } else { + if (heightValue < 0.0f) + heightValue = 0.0f; + } + } else { + heightValue -= m_zeroPosition; + } + renderItem.setValue(value); + renderItem.setHeight(heightValue); + + float angle = dataItem.rotation(); + if (angle) { + renderItem.setRotation( + QQuaternion::fromAxisAndAngle( + upVector, angle)); + } else { + renderItem.setRotation(identityQuaternion); + } +} + void Bars3DRenderer::updateSeries(const QList &seriesList) { Abstract3DRenderer::updateSeries(seriesList); @@ -283,9 +294,9 @@ void Bars3DRenderer::updateSeries(const QList &seriesList) BarSeriesRenderCache *cache = static_cast(m_renderCacheList.value(barSeries)); if (noSelection - && barSeries->selectedBar() != QBar3DSeries::invalidSelectionPosition() - && selectionLabel() != cache->itemLabel()) { - m_selectionLabelDirty = true; + && barSeries->selectedBar() != QBar3DSeries::invalidSelectionPosition()) { + if (selectionLabel() != cache->itemLabel()) + m_selectionLabelDirty = true; noSelection = false; } cache->setVisualIndex(visualIndex++); @@ -304,6 +315,65 @@ SeriesRenderCache *Bars3DRenderer::createNewCache(QAbstract3DSeries *series) return new BarSeriesRenderCache(series, this); } +void Bars3DRenderer::updateRows(const QVector &rows) +{ + int minRow = m_axisCacheZ.min(); + int maxRow = m_axisCacheZ.max(); + BarSeriesRenderCache *cache = 0; + const QBar3DSeries *prevSeries = 0; + const QBarDataArray *dataArray = 0; + + foreach (Bars3DController::ChangeRow item, rows) { + const int row = item.row; + if (row < minRow || row > maxRow) + continue; + QBar3DSeries *currentSeries = item.series; + if (currentSeries != prevSeries) { + cache = static_cast(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()) + updateRenderRow(dataArray->at(row), cache->renderArray()[row - minRow]); + } +} + +void Bars3DRenderer::updateItems(const QVector &points) +{ + int minRow = m_axisCacheZ.min(); + int maxRow = m_axisCacheZ.max(); + int minCol = m_axisCacheX.min(); + int maxCol = m_axisCacheX.max(); + BarSeriesRenderCache *cache = 0; + const QBar3DSeries *prevSeries = 0; + const QBarDataArray *dataArray = 0; + + foreach (Bars3DController::ChangeItem item, points) { + const int row = item.point.x(); + const int col = item.point.y(); + if (row < minRow || row > maxRow || col < minCol || col > maxCol) + continue; + QBar3DSeries *currentSeries = item.series; + if (currentSeries != prevSeries) { + cache = static_cast(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()) { + updateRenderItem(dataArray->at(row)->at(col), + cache->renderArray()[row - minRow][col - minCol]); + } + } +} + void Bars3DRenderer::updateScene(Q3DScene *scene) { if (m_hasNegativeValues) diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index ca0e690e..ddea546e 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -108,6 +108,7 @@ private: bool m_keepSeriesUniform; bool m_haveUniformColorSeries; bool m_haveGradientSeries; + float m_zeroPosition; public: explicit Bars3DRenderer(Bars3DController *controller); @@ -116,6 +117,8 @@ public: void updateData(); void updateSeries(const QList &seriesList); SeriesRenderCache *createNewCache(QAbstract3DSeries *series); + void updateRows(const QVector &rows); + void updateItems(const QVector &points); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); @@ -169,6 +172,9 @@ private: QPoint selectionColorToArrayPosition(const QVector4D &selectionColor); QBar3DSeries *selectionColorToSeries(const QVector4D &selectionColor); + inline void updateRenderRow(const QBarDataRow *dataRow, BarRenderItemRow &renderRow); + inline void updateRenderItem(const QBarDataItem &dataItem, BarRenderItem &renderItem); + Q_DISABLE_COPY(Bars3DRenderer) friend class BarRenderItem; diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 5d37e6e1..3f91e9c3 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -240,9 +240,9 @@ void Scatter3DRenderer::updateSeries(const QList &seriesLis if (cache->itemSize() != itemSize) cache->setItemSize(itemSize); if (noSelection - && scatterSeries->selectedItem() != QScatter3DSeries::invalidSelectionIndex() - && m_selectionLabel != cache->itemLabel()) { - m_selectionLabelDirty = true; + && scatterSeries->selectedItem() != QScatter3DSeries::invalidSelectionIndex()) { + if (m_selectionLabel != cache->itemLabel()) + m_selectionLabelDirty = true; noSelection = false; } diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 591cbdda..6f27c7df 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -76,7 +76,7 @@ void Surface3DController::synchDataToRenderer() } if (m_changeTracker.itemChanged) { - m_renderer->updateItem(m_changedItems); + m_renderer->updateItems(m_changedItems); m_changeTracker.itemChanged = false; m_changedItems.clear(); } @@ -309,36 +309,34 @@ void Surface3DController::handleFlatShadingSupportedChange(bool supported) void Surface3DController::handleRowsChanged(int startIndex, int count) { - QSurfaceDataProxy *sender = static_cast(QObject::sender()); - if (m_changedRows.size() == 0) - m_changedRows.reserve(sender->rowCount()); - - QSurface3DSeries *series = sender->series(); + QSurface3DSeries *series = static_cast(QObject::sender())->series(); int oldChangeCount = m_changedRows.size(); + if (!oldChangeCount) + m_changedRows.reserve(count); + int selectedRow = m_selectedPoint.x(); for (int i = 0; i < count; i++) { bool newItem = true; int candidate = startIndex + i; - for (int i = 0; i < oldChangeCount; i++) { - if (m_changedRows.at(i).row == candidate && - series == m_changedRows.at(i).series) { + for (int j = 0; j < oldChangeCount; j++) { + const ChangeRow &oldChangeItem = m_changedRows.at(j); + if (oldChangeItem.row == candidate && series == oldChangeItem.series) { newItem = false; break; } } if (newItem) { - ChangeRow newItem = {series, candidate}; - m_changedRows.append(newItem); + ChangeRow newChangeItem = {series, candidate}; + m_changedRows.append(newChangeItem); if (series == m_selectedSeries && selectedRow == candidate) series->d_ptr->markItemLabelDirty(); } } - if (m_changedRows.size()) { + if (count) { m_changeTracker.rowsChanged = true; - adjustAxisRanges(); - // Clear selection unless still valid - setSelectedPoint(m_selectedPoint, m_selectedSeries, false); + if (series->isVisible()) + adjustAxisRanges(); emitNeedRender(); } } @@ -349,7 +347,7 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex) QSurface3DSeries *series = sender->series(); bool newItem = true; - QPoint candidate(columnIndex, rowIndex); + QPoint candidate(rowIndex, columnIndex); foreach (ChangeItem item, m_changedItems) { if (item.point == candidate && item.series == series) { newItem = false; @@ -364,9 +362,8 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex) if (series == m_selectedSeries && m_selectedPoint == candidate) series->d_ptr->markItemLabelDirty(); - adjustAxisRanges(); - // Clear selection unless still valid - setSelectedPoint(m_selectedPoint, m_selectedSeries, false); + if (series->isVisible()) + adjustAxisRanges(); emitNeedRender(); } } diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index f04277f7..198a034d 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -256,9 +256,9 @@ void Surface3DRenderer::updateSeries(const QList &seriesLis SurfaceSeriesRenderCache *cache = static_cast( m_renderCacheList.value(series)); if (noSelection - && surfaceSeries->selectedPoint() != QSurface3DSeries::invalidSelectionPosition() - && selectionLabel() != cache->itemLabel()) { - m_selectionLabelDirty = true; + && surfaceSeries->selectedPoint() != QSurface3DSeries::invalidSelectionPosition()) { + if (selectionLabel() != cache->itemLabel()) + m_selectionLabelDirty = true; noSelection = false; } @@ -346,7 +346,7 @@ void Surface3DRenderer::updateRows(const QVector updateSelectedPoint(m_selectedPoint, m_selectedSeries); } -void Surface3DRenderer::updateItem(const QVector &points) +void Surface3DRenderer::updateItems(const QVector &points) { foreach (Surface3DController::ChangeItem item, points) { SurfaceSeriesRenderCache *cache = @@ -364,14 +364,15 @@ void Surface3DRenderer::updateItem(const QVector= sampleSpace.y() && - point.x() <= sampleSpaceRight && point.x() >= sampleSpace.x()) { + if (point.x() <= sampleSpaceTop && point.x() >= sampleSpace.y() && + point.y() <= sampleSpaceRight && point.y() >= sampleSpace.x()) { updateBuffers = true; - int x = point.x() - sampleSpace.x(); - int y = point.y() - sampleSpace.y(); - (*(dstArray.at(y)))[x] = srcArray->at(point.y())->at(point.x()); + int x = point.y() - sampleSpace.x(); + int y = point.x() - sampleSpace.y(); + (*(dstArray.at(y)))[x] = srcArray->at(point.x())->at(point.y()); if (cache->isFlatShadingEnabled()) cache->surfaceObject()->updateCoarseItem(dstArray, y, x); diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 0cd4502a..db46a17b 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -110,7 +110,7 @@ public: void cleanCache(SeriesRenderCache *cache); void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode); void updateRows(const QVector &rows); - void updateItem(const QVector &points); + void updateItems(const QVector &points); void updateScene(Q3DScene *scene); void updateSlicingActive(bool isSlicing); void updateSelectedPoint(const QPoint &position, QSurface3DSeries *series); diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index 2c095cf8..9bf21cbd 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -316,32 +316,14 @@ void GraphModifier::releaseAxes() // Releases all axes - results in default axes for all dimensions. // Axes reset when the graph is switched as set*Axis calls are made, which // implicitly add axes. - m_graph->releaseAxis(m_autoAdjustingAxis); - m_graph->releaseAxis(m_fixedRangeAxis); - m_graph->releaseAxis(m_temperatureAxis); - m_graph->releaseAxis(m_yearAxis); - m_graph->releaseAxis(m_monthAxis); - m_graph->releaseAxis(m_genericRowAxis); - m_graph->releaseAxis(m_genericColumnAxis); + foreach (QAbstract3DAxis *axis, m_graph->axes()) + m_graph->releaseAxis(axis); } -void GraphModifier::releaseProxies() +void GraphModifier::releaseSeries() { - // Releases all series/add all series toggle - if (m_graph->seriesList().size() > 0) { - m_graph->removeSeries(m_temperatureData); - m_graph->removeSeries(m_temperatureData2); - m_graph->removeSeries(m_genericData); - m_graph->removeSeries(m_dummyData); - m_graph->removeSeries(m_dummyData2); - m_graph->removeSeries(m_dummyData3); - m_graph->removeSeries(m_dummyData4); - m_graph->removeSeries(m_dummyData5); - } else { - m_graph->addSeries(m_temperatureData); - m_graph->addSeries(m_temperatureData2); - m_graph->addSeries(m_genericData); - } + foreach (QBar3DSeries *series, m_graph->seriesList()) + m_graph->removeSeries(series); } void GraphModifier::flipViews() @@ -771,7 +753,7 @@ void GraphModifier::changeShadowQuality(int quality) void GraphModifier::showFiveSeries() { - releaseProxies(); + releaseSeries(); releaseAxes(); m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemRowAndColumn | QAbstract3DGraph::SelectionMultiSeries); @@ -838,7 +820,7 @@ void GraphModifier::primarySeriesTest() case 0: { qDebug() << "Step 0 - Init:"; m_graph->addSeries(m_dummyData); // Add one series to enforce release in releaseProxies() - releaseProxies(); + releaseSeries(); releaseAxes(); m_dummyData->dataProxy()->resetArray(makeDummyData(), testLabels, @@ -1028,11 +1010,11 @@ void GraphModifier::insertRemoveTestToggle() m_selectionTimer.stop(); m_graph->removeSeries(m_dummyData); m_graph->removeSeries(m_dummyData2); - releaseProxies(); + releaseSeries(); releaseAxes(); m_graph->setActiveInputHandler(m_defaultInputHandler); } else { - releaseProxies(); + releaseSeries(); releaseAxes(); m_graph->rowAxis()->setRange(0, 32); m_graph->columnAxis()->setRange(0, 10); @@ -1211,6 +1193,213 @@ void GraphModifier::addRemoveSeries() counter++; } +void GraphModifier::testItemAndRowChanges() +{ + static int counter = 0; + const int rowCount = 12; + const int colCount = 10; + const float flatValue = 10.0f; + static QBar3DSeries *series0 = 0; + static QBar3DSeries *series1 = 0; + static QBar3DSeries *series2 = 0; + QBarDataItem item25; + QBarDataItem item50; + QBarDataItem item75; + item25.setValue(25); + item50.setValue(50); + item75.setValue(75); + + switch (counter) { + case 0: { + qDebug() << __FUNCTION__ << counter << "Setup test"; + releaseSeries(); + releaseAxes(); + delete series0; + delete series1; + delete series2; + series0 = new QBar3DSeries; + series1 = new QBar3DSeries; + series2 = new QBar3DSeries; + populateFlatSeries(series0, rowCount, colCount, flatValue); + populateFlatSeries(series1, rowCount, colCount, flatValue); + populateFlatSeries(series2, rowCount, colCount, flatValue); + m_graph->rowAxis()->setRange(4.0f, 8.0f); + m_graph->columnAxis()->setRange(3.0f, 6.0f); + m_graph->valueAxis()->setRange(0.0f, 100.0f); + m_graph->addSeries(series0); + m_graph->addSeries(series1); + m_graph->addSeries(series2); + //counter = 11; // skip single item tests + } + break; + case 1: { + qDebug() << __FUNCTION__ << counter << "Change single item, unselected"; + series0->dataProxy()->setItem(4, 3, item50); + } + break; + case 2: { + qDebug() << __FUNCTION__ << counter << "Change single item, selected"; + series1->setSelectedBar(QPoint(4, 5)); + series1->dataProxy()->setItem(4, 5, item25); + } + break; + case 3: { + qDebug() << __FUNCTION__ << counter << "Change item outside visible area"; + series1->dataProxy()->setItem(0, 3, item25); + } + break; + case 4: { + qDebug() << __FUNCTION__ << counter << "Change single item from two series, unselected"; + series0->dataProxy()->setItem(5, 3, item25); + series1->dataProxy()->setItem(5, 3, item75); + } + break; + case 5: { + qDebug() << __FUNCTION__ << counter << "Change single item from two series, one selected"; + series0->dataProxy()->setItem(5, 4, item25); + series1->dataProxy()->setItem(4, 5, item75); + } + break; + case 6: { + qDebug() << __FUNCTION__ << counter << "Change single item from two series, one outside range"; + series0->dataProxy()->setItem(1, 2, item25); + series1->dataProxy()->setItem(6, 6, item75); + } + break; + case 7: { + qDebug() << __FUNCTION__ << counter << "Change single item from two series, both outside range"; + series0->dataProxy()->setItem(1, 2, item25); + series1->dataProxy()->setItem(8, 8, item75); + } + break; + case 8: { + qDebug() << __FUNCTION__ << counter << "Change item to same value"; + series1->dataProxy()->setItem(6, 6, item75); + } + break; + case 9: { + qDebug() << __FUNCTION__ << counter << "Change 3 items on each series"; + series0->dataProxy()->setItem(7, 3, item25); + series0->dataProxy()->setItem(7, 4, item50); + series0->dataProxy()->setItem(7, 5, item75); + series1->dataProxy()->setItem(6, 3, item25); + series1->dataProxy()->setItem(6, 4, item50); + series1->dataProxy()->setItem(6, 5, item75); + } + break; + case 10: { + qDebug() << __FUNCTION__ << counter << "Level the field single item at a time"; + QBarDataItem item; + item.setValue(15.0f); + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < colCount; j++) { + series0->dataProxy()->setItem(i, j, item); + series1->dataProxy()->setItem(i, j, item); + series2->dataProxy()->setItem(i, j, item); + } + } + } + break; + case 11: { + qDebug() << __FUNCTION__ << counter << "Change same items multiple times"; + series0->dataProxy()->setItem(7, 3, item25); + series1->dataProxy()->setItem(7, 3, item25); + series0->dataProxy()->setItem(7, 3, item50); + series1->dataProxy()->setItem(7, 3, item50); + series0->dataProxy()->setItem(7, 3, item75); + series1->dataProxy()->setItem(7, 3, item75); + } + break; + case 12: { + qDebug() << __FUNCTION__ << counter << "Change row"; + series0->dataProxy()->setRow(5, createFlatRow(colCount, 50.0f)); + } + break; + case 13: { + qDebug() << __FUNCTION__ << counter << "Change row with selected item"; + series1->setSelectedBar(QPoint(6, 6)); + series1->dataProxy()->setRow(6, createFlatRow(colCount, 40.0f)); + } + break; + case 14: { + qDebug() << __FUNCTION__ << counter << "Change hidden row"; + series1->dataProxy()->setRow(9, createFlatRow(colCount, 50.0f)); + } + break; + case 15: { + qDebug() << __FUNCTION__ << counter << "Change multiple rows singly"; + series0->dataProxy()->setRow(6, createFlatRow(colCount, 70.0f)); + series1->dataProxy()->setRow(6, createFlatRow(colCount, 80.0f)); + series2->dataProxy()->setRow(6, createFlatRow(colCount, 90.0f)); + } + break; + case 16: { + qDebug() << __FUNCTION__ << counter << "Change multiple rows many at a time"; + QBarDataArray newRows; + newRows.reserve(4); + newRows.append(createFlatRow(colCount, 26.0f)); + newRows.append(createFlatRow(colCount, 30.0f)); + newRows.append(createFlatRow(colCount, 34.0f)); + newRows.append(createFlatRow(colCount, 38.0f)); + series0->dataProxy()->setRows(2, newRows); + newRows[0] = createFlatRow(colCount, 26.0f); + newRows[1] = createFlatRow(colCount, 30.0f); + newRows[2] = createFlatRow(colCount, 34.0f); + newRows[3] = createFlatRow(colCount, 38.0f); + series1->dataProxy()->setRows(3, newRows); + newRows[0] = createFlatRow(colCount, 26.0f); + newRows[1] = createFlatRow(colCount, 30.0f); + newRows[2] = createFlatRow(colCount, 34.0f); + newRows[3] = createFlatRow(colCount, 38.0f); + series2->dataProxy()->setRows(4, newRows); + } + break; + case 17: { + qDebug() << __FUNCTION__ << counter << "Change same rows multiple times"; + QBarDataArray newRows; + newRows.reserve(4); + newRows.append(createFlatRow(colCount, 65.0f)); + newRows.append(createFlatRow(colCount, 65.0f)); + newRows.append(createFlatRow(colCount, 65.0f)); + newRows.append(createFlatRow(colCount, 65.0f)); + series0->dataProxy()->setRows(4, newRows); + newRows[0] = createFlatRow(colCount, 65.0f); + newRows[1] = createFlatRow(colCount, 65.0f); + newRows[2] = createFlatRow(colCount, 65.0f); + newRows[3] = createFlatRow(colCount, 65.0f); + series1->dataProxy()->setRows(4, newRows); + newRows[0] = createFlatRow(colCount, 65.0f); + newRows[1] = createFlatRow(colCount, 65.0f); + newRows[2] = createFlatRow(colCount, 65.0f); + newRows[3] = createFlatRow(colCount, 65.0f); + series2->dataProxy()->setRows(4, newRows); + series0->dataProxy()->setRow(6, createFlatRow(colCount, 20.0f)); + series1->dataProxy()->setRow(6, createFlatRow(colCount, 20.0f)); + series2->dataProxy()->setRow(6, createFlatRow(colCount, 20.0f)); + series0->dataProxy()->setRow(6, createFlatRow(colCount, 90.0f)); + series1->dataProxy()->setRow(6, createFlatRow(colCount, 90.0f)); + series2->dataProxy()->setRow(6, createFlatRow(colCount, 90.0f)); + } + break; + case 18: { + qDebug() << __FUNCTION__ << counter << "Change row to different length"; + series0->dataProxy()->setRow(4, createFlatRow(5, 20.0f)); + series1->dataProxy()->setRow(4, createFlatRow(0, 20.0f)); + series2->dataProxy()->setRow(4, 0); + } + break; + case 19: { + qDebug() << __FUNCTION__ << counter << "Change selected row shorter so that selected item is no longer valid"; + series1->dataProxy()->setRow(6, createFlatRow(6, 20.0f)); + } + break; + default: + qDebug() << __FUNCTION__ << "Resetting test"; + counter = -1; + } + counter++; +} + void GraphModifier::changeValueAxisSegments(int value) { qDebug() << __FUNCTION__ << value; @@ -1285,6 +1474,32 @@ void GraphModifier::handleFpsChange(qreal fps) m_fpsLabel->setText(fpsPrefix + QString::number(qRound(fps))); } +void GraphModifier::populateFlatSeries(QBar3DSeries *series, int rows, int columns, float value) +{ + QBarDataArray *dataArray = new QBarDataArray; + dataArray->reserve(rows); + for (int i = 0; i < rows; i++) { + QBarDataRow *dataRow = new QBarDataRow(columns); + for (int j = 0; j < columns; j++) + (*dataRow)[j].setValue(value); + dataArray->append(dataRow); + } + QStringList axisLabels; + int count = qMax(rows, columns); + for (int i = 0; i < count; i++) + axisLabels << QString::number(i); + + series->dataProxy()->resetArray(dataArray, axisLabels, axisLabels); +} + +QBarDataRow *GraphModifier::createFlatRow(int columns, float value) +{ + QBarDataRow *dataRow = new QBarDataRow(columns); + for (int j = 0; j < columns; j++) + (*dataRow)[j].setValue(value); + return dataRow; +} + void GraphModifier::setBackgroundEnabled(int enabled) { m_graph->activeTheme()->setBackgroundEnabled(bool(enabled)); diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index e64b282a..385e139c 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -77,7 +77,7 @@ public: void selectBar(); void swapAxis(); void releaseAxes(); - void releaseProxies(); + void releaseSeries(); void createMassiveArray(); void useOwnTheme(); void changeBaseColor(const QColor &color); @@ -92,6 +92,7 @@ public: void changeLogBase(const QString & text); void setFpsLabel(QLabel *fpsLabel) { m_fpsLabel = fpsLabel; } void addRemoveSeries(); + void testItemAndRowChanges(); public slots: void flipViews(); @@ -118,6 +119,9 @@ signals: void shadowQualityChanged(int quality); private: + void populateFlatSeries(QBar3DSeries *series, int rows, int columns, float value); + QBarDataRow *createFlatRow(int columns, float value); + Q3DBars *m_graph; QColorDialog *m_colorDialog; int m_columnCount; diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index e02bddce..1182ffdf 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -175,6 +175,10 @@ int main(int argc, char **argv) logAxisButton->setText(QStringLiteral("Use Log Axis")); logAxisButton->setEnabled(true); + QPushButton *testItemAndRowChangesButton = new QPushButton(widget); + testItemAndRowChangesButton->setText(QStringLiteral("Test Item/Row changing")); + testItemAndRowChangesButton->setEnabled(true); + QColorDialog *colorDialog = new QColorDialog(widget); QLinearGradient grBtoY(0, 0, 100, 0); @@ -337,7 +341,9 @@ int main(int argc, char **argv) vLayout->addWidget(ownThemeButton, 0, Qt::AlignTop); vLayout->addWidget(primarySeriesTestsButton, 0, Qt::AlignTop); vLayout->addWidget(toggleRotationButton, 0, Qt::AlignTop); - vLayout->addWidget(gradientBtoYPB, 1, Qt::AlignTop); + vLayout->addWidget(gradientBtoYPB, 0, Qt::AlignTop); + vLayout->addWidget(logAxisButton, 0, Qt::AlignTop); + vLayout->addWidget(testItemAndRowChangesButton, 1, Qt::AlignTop); vLayout2->addWidget(staticCheckBox, 0, Qt::AlignTop); vLayout2->addWidget(rotationCheckBox, 0, Qt::AlignTop); @@ -372,7 +378,6 @@ int main(int argc, char **argv) vLayout2->addWidget(logBaseEdit, 0, Qt::AlignTop); vLayout2->addWidget(new QLabel(QStringLiteral("Value axis segments")), 0, Qt::AlignTop); vLayout2->addWidget(valueAxisSegmentsSpin, 0, Qt::AlignTop); - vLayout->addWidget(logAxisButton, 1, Qt::AlignTop); // TODO: Add example for setMeshFileName widget->show(); @@ -446,7 +451,7 @@ int main(int argc, char **argv) QObject::connect(releaseAxesButton, &QPushButton::clicked, modifier, &GraphModifier::releaseAxes); QObject::connect(releaseProxiesButton, &QPushButton::clicked, modifier, - &GraphModifier::releaseProxies); + &GraphModifier::releaseSeries); QObject::connect(flipViewsButton, &QPushButton::clicked, modifier, &GraphModifier::flipViews); @@ -460,6 +465,8 @@ int main(int argc, char **argv) &GraphModifier::toggleRotation); QObject::connect(logAxisButton, &QPushButton::clicked, modifier, &GraphModifier::useLogAxis); + QObject::connect(testItemAndRowChangesButton, &QPushButton::clicked, modifier, + &GraphModifier::testItemAndRowChanges); QObject::connect(colorDialog, &QColorDialog::currentColorChanged, modifier, &GraphModifier::changeBaseColor); QObject::connect(gradientBtoYPB, &QPushButton::clicked, modifier, diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp index a4eb3a27..0f3aa985 100644 --- a/tests/surfacetest/graphmodifier.cpp +++ b/tests/surfacetest/graphmodifier.cpp @@ -143,7 +143,7 @@ void GraphModifier::fillSeries() for (int i = 0; i < m_zCount; i++) { QSurfaceDataRow *newRow[4]; float zAdjust = 0.0f; - if (i == 3) + if (i == 2) zAdjust = 0.7f; for (int s = 0; s < 4; s++) { @@ -151,7 +151,7 @@ void GraphModifier::fillSeries() float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[s] + zAdjust; for (int j = 0; j < m_xCount; j++) { float xAdjust = 0.0f; - if (j == 3) + if (j == 4) xAdjust = 0.7f; float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[s] + xAdjust; float angle = (z * x) / full * 1.57f; -- cgit v1.2.3