From fe2e12ffd7bb495634a66dc9c3e0d0fcbcfeb0df Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 22 Nov 2013 09:26:46 +0200 Subject: Multi series selection part 3: surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTRD-2556 Change-Id: I3a465c1bfff95f6c89d2f473f9e235c6079b8116 Reviewed-by: Tomi Korpipää --- src/datavisualization/engine/bars3dcontroller.cpp | 4 +- src/datavisualization/engine/q3dsurface.cpp | 25 +---- src/datavisualization/engine/q3dsurface.h | 5 - .../engine/scatter3dcontroller.cpp | 4 +- .../engine/surface3dcontroller.cpp | 103 +++++++++++++-------- .../engine/surface3dcontroller_p.h | 12 +-- src/datavisualization/engine/surface3drenderer.cpp | 20 ++-- src/datavisualization/engine/surface3drenderer_p.h | 5 +- 8 files changed, 92 insertions(+), 86 deletions(-) (limited to 'src/datavisualization/engine') diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index b1cf8338..e1a038cb 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -244,11 +244,11 @@ void Bars3DController::removeSeries(QAbstract3DSeries *series) { bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series); + Abstract3DController::removeSeries(series); + if (m_selectedBarSeries == series) setSelectedBar(invalidSelectionPosition(), 0); - Abstract3DController::removeSeries(series); - if (firstRemoved) { adjustAxisRanges(); diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp index b19b5a0c..1655c338 100644 --- a/src/datavisualization/engine/q3dsurface.cpp +++ b/src/datavisualization/engine/q3dsurface.cpp @@ -39,8 +39,9 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * surface can be changed by controlling the smooth status. * * The Q3DSurface supports selection by showing a highlighted ball on the data point where the user has clicked - * with left mouse button (when default input handler is in use). The selection pointer is accompanied with - * a label which in default case shows the value of the data point and the coordinates of the point. + * with left mouse button (when default input handler is in use) or selected via QSurface3DSeries. + * The selection pointer is accompanied with a label which in default case shows the value of the + * data point and the coordinates of the point. * * The value range and the label format shown on the axis can be controlled through Q3DValueAxis. * @@ -118,8 +119,6 @@ Q3DSurface::Q3DSurface() &Q3DSurface::surfaceGridEnabledChanged); QObject::connect(d_ptr->m_shared, &Abstract3DController::fontChanged, this, &Q3DSurface::fontChanged); - QObject::connect(d_ptr->m_shared, &Surface3DController::selectedPointChanged, this, - &Q3DSurface::selectedPointChanged); QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this, &Q3DWindow::renderLater); } @@ -373,24 +372,6 @@ Q3DScene *Q3DSurface::scene() const return d_ptr->m_shared->scene(); } -/*! - * \property Q3DSurface::selectedPoint - * - * Selects a surface grid point in a \a position. The position is the (row, column) position in - * the data array of the active data proxy. - * Only one point can be selected at a time. - * To clear selection, specify an illegal \a position, e.g. (-1, -1). - */ -void Q3DSurface::setSelectedPoint(const QPoint &position) -{ - d_ptr->m_shared->setSelectedPoint(position); -} - -QPoint Q3DSurface::selectedPoint() const -{ - return d_ptr->m_shared->selectedPoint(); -} - /*! * \property Q3DSurface::labelStyle * diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h index 3287bee4..9bc04f78 100644 --- a/src/datavisualization/engine/q3dsurface.h +++ b/src/datavisualization/engine/q3dsurface.h @@ -46,7 +46,6 @@ class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) Q_PROPERTY(Q3DScene* scene READ scene) - Q_PROPERTY(QPoint selectedPoint READ selectedPoint WRITE setSelectedPoint NOTIFY selectedPointChanged) public: explicit Q3DSurface(); @@ -97,9 +96,6 @@ public: Q3DScene *scene() const; - void setSelectedPoint(const QPoint &position); - QPoint selectedPoint() const; - void setLabelStyle(QDataVis::LabelStyle style); QDataVis::LabelStyle labelStyle() const; @@ -114,7 +110,6 @@ signals: void smoothSurfaceEnabledChanged(bool enabled); void surfaceGridEnabledChanged(bool visible); void fontChanged(QFont font); - void selectedPointChanged(QPoint position); protected: void mouseDoubleClickEvent(QMouseEvent *event); diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index 27d1b609..34b1c563 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -99,11 +99,11 @@ void Scatter3DController::removeSeries(QAbstract3DSeries *series) { bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series); + Abstract3DController::removeSeries(series); + if (m_selectedItemSeries == series) setSelectedItem(invalidSelectionIndex(), 0); - Abstract3DController::removeSeries(series); - if (firstRemoved) adjustValueAxisRange(); } diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 9bd4b508..31c8b178 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -37,7 +37,8 @@ Surface3DController::Surface3DController(QRect rect) m_isSmoothSurfaceEnabled(false), m_isSurfaceEnabled(true), m_isSurfaceGridEnabled(true), - m_selectedPoint(noSelectionPoint()) + m_selectedPoint(invalidSelectionPosition()), + m_selectedSeries(0) { // Setting a null axis creates a new default axis according to orientation and graph type. // Note: these cannot be set in the Abstract3DController constructor, as they will call virtual @@ -97,7 +98,7 @@ void Surface3DController::synchDataToRenderer() } if (m_changeTracker.selectedPointChanged) { - m_renderer->updateSelectedPoint(m_selectedPoint); + m_renderer->updateSelectedPoint(m_selectedPoint, m_selectedSeries); m_changeTracker.selectedPointChanged = false; } } @@ -115,10 +116,19 @@ void Surface3DController::handleAxisRangeChangedBySender(QObject *sender) Abstract3DController::handleAxisRangeChangedBySender(sender); // Update selected point - may be moved offscreen - setSelectedPoint(m_selectedPoint); + setSelectedPoint(m_selectedPoint, m_selectedSeries); } -QPoint Surface3DController::noSelectionPoint() +void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender) +{ + Abstract3DController::handleSeriesVisibilityChangedBySender(sender); + + // Visibility changes may require disabling/enabling slicing, + // so just reset selection to ensure everything is still valid. + setSelectedPoint(m_selectedPoint, m_selectedSeries); +} + +QPoint Surface3DController::invalidSelectionPosition() { static QPoint noSelectionPoint(-1, -1); return noSelectionPoint; @@ -132,12 +142,13 @@ void Surface3DController::addSeries(QAbstract3DSeries *series) Abstract3DController::addSeries(series); adjustValueAxisRange(); - - // TODO: Temp until selection by series is properly implemented - setSelectedPoint(noSelectionPoint()); } else { qWarning("Surface graph only supports a single series."); } + + QSurface3DSeries *surfaceSeries = static_cast(series); + if (surfaceSeries->selectedPoint() != invalidSelectionPosition()) + setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries); } void Surface3DController::removeSeries(QAbstract3DSeries *series) @@ -145,10 +156,10 @@ void Surface3DController::removeSeries(QAbstract3DSeries *series) if (series && series->d_ptr->m_controller == this) { Abstract3DController::removeSeries(series); - adjustValueAxisRange(); + if (m_selectedSeries == series) + setSelectedPoint(invalidSelectionPosition(), 0); - // TODO: Temp until selection by series is properly implemented - setSelectedPoint(noSelectionPoint()); + adjustValueAxisRange(); } } @@ -228,43 +239,51 @@ void Surface3DController::setSelectionMode(QDataVis::SelectionFlags mode) && (mode.testFlag(QDataVis::SelectionRow) == mode.testFlag(QDataVis::SelectionColumn))) { qWarning("Must specify one of either row or column selection mode in conjunction with slicing mode."); } else { - // When setting selection mode to a new slicing mode, activate slicing - if (mode != selectionMode()) { - bool isSlicing = mode.testFlag(QDataVis::SelectionSlice); - if (isSlicing && m_selectedPoint != noSelectionPoint()) - scene()->setSlicingActive(true); - else - scene()->setSlicingActive(false); - } + QDataVis::SelectionFlags oldMode = selectionMode(); Abstract3DController::setSelectionMode(mode); + + if (mode != oldMode) { + // Refresh selection upon mode change to ensure slicing is correctly updated + // according to series the visibility. + setSelectedPoint(m_selectedPoint, m_selectedSeries); + + // Special case: Always deactivate slicing when changing away from slice + // automanagement, as this can't be handled in setSelectedBar. + if (!mode.testFlag(QDataVis::SelectionSlice) + && oldMode.testFlag(QDataVis::SelectionSlice)) { + scene()->setSlicingActive(false); + } + } } } -void Surface3DController::setSelectedPoint(const QPoint &position) +void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series) { // If the selection targets non-existent point, clear selection instead. QPoint pos = position; - // TODO: Selection needs to be refactored to be handled by series + // Series may already have been removed, so check it before setting the selection. + if (!m_seriesList.contains(series)) + series = 0; + const QSurfaceDataProxy *proxy = 0; - if (m_seriesList.size()) { - QSurface3DSeries *series = static_cast(m_seriesList.at(0)); - proxy = static_cast(series->dataProxy()); - } else { - return; - } + if (series) + proxy = series->dataProxy(); - if (pos != noSelectionPoint()) { + if (!proxy) + pos = invalidSelectionPosition(); + + if (pos != invalidSelectionPosition()) { int maxRow = proxy->rowCount() - 1; int maxCol = proxy->columnCount() - 1; if (pos.x() < 0 || pos.x() > maxRow || pos.y() < 0 || pos.y() > maxCol) - pos = noSelectionPoint(); + pos = invalidSelectionPosition(); } if (selectionMode().testFlag(QDataVis::SelectionSlice)) { - if (pos == noSelectionPoint()) { + if (pos == invalidSelectionPosition() || !series->isVisible()) { scene()->setSlicingActive(false); } else { // If the selected point is outside data window, or there is no selected point, disable slicing @@ -276,7 +295,8 @@ void Surface3DController::setSelectedPoint(const QPoint &position) float axisMaxZ = float(m_axisZ->max()); // Comparisons between float and double are not accurate, so fudge our comparison values - //a little to get all rows and columns into view that need to be visible. + // a little to get all rows and columns into view that need to be visible. + // TODO: Probably unnecessary after QTRD-2622 done const float fudgeFactor = 0.00001f; float fudgedAxisXRange = (axisMaxX - axisMinX) * fudgeFactor; float fudgedAxisZRange = (axisMaxZ - axisMinZ) * fudgeFactor; @@ -297,29 +317,34 @@ void Surface3DController::setSelectedPoint(const QPoint &position) if (pos != m_selectedPoint) { m_selectedPoint = pos; + m_selectedSeries = series; m_changeTracker.selectedPointChanged = true; - emit selectedPointChanged(pos); + + // Clear selection from other series and finally set new selection to the specified series + foreach (QAbstract3DSeries *otherSeries, m_seriesList) { + QSurface3DSeries *surfaceSeries = static_cast(otherSeries); + if (surfaceSeries != m_selectedSeries) + surfaceSeries->dptr()->setSelectedPoint(invalidSelectionPosition()); + } + if (m_selectedSeries) + m_selectedSeries->dptr()->setSelectedPoint(m_selectedPoint); + emitNeedRender(); } } -QPoint Surface3DController::selectedPoint() const -{ - return m_selectedPoint; -} - void Surface3DController::handleArrayReset() { adjustValueAxisRange(); m_isDataDirty = true; // Clear selection unless still valid - setSelectedPoint(m_selectedPoint); + setSelectedPoint(m_selectedPoint, m_selectedSeries); emitNeedRender(); } -void Surface3DController::handlePointClicked(const QPoint &position) +void Surface3DController::handlePointClicked(const QPoint &position, QSurface3DSeries *series) { - setSelectedPoint(position); + setSelectedPoint(position, series); // TODO: pass clicked to parent. (QTRD-2517) // TODO: Also hover needed? (QTRD-2131) } diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index 09c0ca5b..56419d75 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -66,6 +66,8 @@ private: bool m_isSurfaceGridEnabled; QLinearGradient m_userDefinedGradient; QPoint m_selectedPoint; + QSurface3DSeries *m_selectedSeries; // Points to the series for which the point is selected in + // single series selection cases. public: explicit Surface3DController(QRect rect); @@ -86,14 +88,13 @@ public: void setGradientColorAt(qreal pos, const QColor &color); void setSelectionMode(QDataVis::SelectionFlags mode); - - void setSelectedPoint(const QPoint &position); - QPoint selectedPoint() const; + void setSelectedPoint(const QPoint &position, QSurface3DSeries *series); virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); virtual void handleAxisRangeChangedBySender(QObject *sender); + virtual void handleSeriesVisibilityChangedBySender(QObject *sender); - static QPoint noSelectionPoint(); + static QPoint invalidSelectionPosition(); virtual void addSeries(QAbstract3DSeries *series); virtual void removeSeries(QAbstract3DSeries *series); @@ -103,12 +104,11 @@ public slots: void handleArrayReset(); // Renderer callback handlers - void handlePointClicked(const QPoint &position); + void handlePointClicked(const QPoint &position, QSurface3DSeries *series); void handleRequestSmoothSurface(bool enable); signals: void smoothSurfaceEnabledChanged(bool enable); - void selectedPointChanged(QPoint position); void surfaceVisibleChanged(bool visible); void surfaceGridEnabledChanged(bool enable); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index e19b70d8..b90b3527 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -112,7 +112,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_shadowQualityMultiplier(3), m_clickedPointId(invalidSelectionId), m_hasHeightAdjustmentChanged(true), - m_selectedPoint(Surface3DController::noSelectionPoint()) + m_selectedPoint(Surface3DController::invalidSelectionPosition()), + m_selectedSeries(0) { // Check if flat feature is supported ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), @@ -266,7 +267,7 @@ void Surface3DRenderer::updateData() delete m_sliceDataArray.at(i); m_sliceDataArray.clear(); - m_selectionDirty = true; + updateSelectedPoint(m_selectedPoint, m_selectedSeries); } void Surface3DRenderer::updateSliceDataModel(const QPoint &point) @@ -337,7 +338,8 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array) float axisMaxZ = float(m_axisCacheZ.max()); // Comparisons between float and double are not accurate, so fudge our comparison values - //a little to get all rows and columns into view that need to be visible. + // a little to get all rows and columns into view that need to be visible. + // TODO: Probably unnecessary after QTRD-2622 done const float fudgeFactor = 0.00001f; float fudgedAxisXRange = (axisMaxX - axisMinX) * fudgeFactor; float fudgedAxisZRange = (axisMaxZ - axisMinZ) * fudgeFactor; @@ -937,7 +939,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536; #endif - emit pointClicked(QPoint(selectionIdToSurfacePoint(selectionId))); + emit pointClicked(QPoint(selectionIdToSurfacePoint(selectionId)), + static_cast(m_visibleSeriesList.at(0).series())); } // Draw the surface @@ -1588,8 +1591,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Selection handling if (m_selectionDirty) { - QPoint visiblePoint = Surface3DController::noSelectionPoint(); - if (m_selectedPoint != Surface3DController::noSelectionPoint()) { + QPoint visiblePoint = Surface3DController::invalidSelectionPosition(); + if (m_selectedPoint != Surface3DController::invalidSelectionPosition()) { int x = m_selectedPoint.x() - m_sampleSpace.y(); int y = m_selectedPoint.y() - m_sampleSpace.x(); if (x >= 0 && y >= 0 && x < m_sampleSpace.height() && y < m_sampleSpace.width() @@ -1599,7 +1602,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } if (m_cachedSelectionMode == QDataVis::SelectionNone - || visiblePoint == Surface3DController::noSelectionPoint()) { + || visiblePoint == Surface3DController::invalidSelectionPosition()) { m_selectionActive = false; } else { // TODO: Need separate selection ball for slice and main surface view QTRD-2515 @@ -1769,9 +1772,10 @@ bool Surface3DRenderer::updateSmoothStatus(bool enable) return m_cachedSmoothSurface; } -void Surface3DRenderer::updateSelectedPoint(const QPoint &position) +void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series) { m_selectedPoint = position; + m_selectedSeries = series; m_selectionDirty = true; } diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 5ac20e0e..2d5c8da9 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -127,6 +127,7 @@ private: uint m_clickedPointId; bool m_hasHeightAdjustmentChanged; QPoint m_selectedPoint; + const QSurface3DSeries *m_selectedSeries; public: explicit Surface3DRenderer(Surface3DController *controller); @@ -138,7 +139,7 @@ public: void updateSurfaceGridStatus(bool enable); void updateSurfaceGradient(const QLinearGradient &gradient); void updateSlicingActive(bool isSlicing); - void updateSelectedPoint(const QPoint &position); + void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series); void drawSlicedScene(); void render(GLuint defaultFboHandle = 0); @@ -148,7 +149,7 @@ protected: virtual void loadMeshFile(); signals: - void pointClicked(QPoint position); + void pointClicked(QPoint position, QSurface3DSeries *series); void requestSmoothSurface(bool enable); private: -- cgit v1.2.3