diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-22 12:08:47 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-22 13:17:36 +0300 |
commit | 44f83ac64537ca6ac13a97a2c267492bdd288fe7 (patch) | |
tree | 19399700a719b18dda5c060a2b57ea76a85e1211 /src/datavis3d/engine | |
parent | 3ab324d0a6d6ff5fa7d15588ee2dc613f0c5e4b9 (diff) |
Selection improvements for bars:
- Signal to notify of selection change
- Setting selection via API
Change-Id: I87c71005d76b15dd259f745392ff7b5112d146b5
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavis3d/engine')
-rw-r--r-- | src/datavis3d/engine/abstract3dcontroller_p.h | 1 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3drenderer_p.h | 1 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3dcontroller.cpp | 56 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3dcontroller_p.h | 14 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3drenderer.cpp | 104 | ||||
-rw-r--r-- | src/datavis3d/engine/bars3drenderer_p.h | 16 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dbars.cpp | 24 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dbars.h | 7 |
8 files changed, 153 insertions, 70 deletions
diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavis3d/engine/abstract3dcontroller_p.h index 9157f1a6..df34e673 100644 --- a/src/datavis3d/engine/abstract3dcontroller_p.h +++ b/src/datavis3d/engine/abstract3dcontroller_p.h @@ -172,7 +172,6 @@ public: */ virtual void synchDataToRenderer(); - virtual void render(const GLuint defaultFboHandle = 0); /** diff --git a/src/datavis3d/engine/abstract3drenderer_p.h b/src/datavis3d/engine/abstract3drenderer_p.h index b4286f20..37271025 100644 --- a/src/datavis3d/engine/abstract3drenderer_p.h +++ b/src/datavis3d/engine/abstract3drenderer_p.h @@ -95,7 +95,6 @@ public: virtual void updateMeshFileName(const QString &objFileName); virtual QString itemLabelFormat() const; - virtual void requestSelectionAtPoint(const QPoint &point) = 0; virtual void updateTextures() = 0; virtual void initSelectionBuffer() = 0; #if !defined(QT_OPENGL_ES_2) diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp index 42284c56..d54aeace 100644 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -37,6 +37,7 @@ Bars3dController::Bars3dController(QRect boundRect) m_mouseState(MouseNone), m_mousePos(QPoint(0, 0)), m_isSlicingActivated(false), + m_selectedBarPos(noSelectionPoint()), m_isBarSpecRelative(true), m_barThicknessRatio(1.0f), m_barSpacing(QSizeF(1.0, 1.0)), @@ -68,6 +69,9 @@ void Bars3dController::initializeOpenGL() m_renderer = new Bars3dRenderer(this); setRenderer(m_renderer); synchDataToRenderer(); + + QObject::connect(m_renderer, &Bars3dRenderer::selectedBarPosChanged, this, + &Bars3dController::handleSelectedBarPosChanged, Qt::QueuedConnection); } void Bars3dController::synchDataToRenderer() @@ -93,6 +97,11 @@ void Bars3dController::synchDataToRenderer() m_changeTracker.barSpecsChanged = false; } + if (m_changeTracker.selectedBarPosChanged) { + m_renderer->updateSelectedBarPos(m_selectedBarPos); + m_changeTracker.selectedBarPosChanged = false; + } + if (m_isDataDirty) { m_renderer->updateDataModel(m_data); m_isDataDirty = false; @@ -267,6 +276,7 @@ void Bars3dController::setDataProxy(QBarDataProxy *proxy) adjustValueAxisRange(); m_isDataDirty = true; + setSelectedBarPos(noSelectionPoint()); } QBarDataProxy *Bars3dController::dataProxy() @@ -279,6 +289,7 @@ void Bars3dController::handleArrayReset() setSlicingActive(false); adjustValueAxisRange(); m_isDataDirty = true; + setSelectedBarPos(noSelectionPoint()); } void Bars3dController::handleRowsAdded(int startIndex, int count) @@ -312,6 +323,9 @@ void Bars3dController::handleRowsRemoved(int startIndex, int count) setSlicingActive(false); adjustValueAxisRange(); m_isDataDirty = true; + // TODO this will break once data window offset is implemented + if (startIndex >= m_data->rowCount()) + setSelectedBarPos(noSelectionPoint()); } void Bars3dController::handleRowsInserted(int startIndex, int count) @@ -336,6 +350,17 @@ void Bars3dController::handleItemChanged(int rowIndex, int columnIndex) m_isDataDirty = true; } +void Bars3dController::handleSelectedBarPosChanged(const QPoint &position) +{ + QPoint pos = position; + if (pos == QPoint(255, 255)) + pos = noSelectionPoint(); + if (pos != m_selectedBarPos) { + m_selectedBarPos = pos; + emit selectedBarPosChanged(pos); + } +} + void Bars3dController::handleAxisAutoAdjustRangeChangedInOrientation( QAbstractAxis::AxisOrientation orientation, bool autoAdjust) { @@ -344,6 +369,12 @@ void Bars3dController::handleAxisAutoAdjustRangeChangedInOrientation( adjustValueAxisRange(); } +QPoint Bars3dController::noSelectionPoint() +{ + static QPoint noSelectionPos(-1, -1); + return noSelectionPos; +} + void Bars3dController::setBarSpecs(GLfloat thicknessRatio, QSizeF spacing, bool relative) { m_barThicknessRatio = thicknessRatio; @@ -400,6 +431,9 @@ void Bars3dController::setDataWindow(int rowCount, int columnCount) adjustValueAxisRange(); + if (m_selectedBarPos.x() >= rowCount || m_selectedBarPos.y() >= columnCount) + setSelectedBarPos(noSelectionPoint()); + m_changeTracker.sampleSpaceChanged = true; emit sampleSpaceChanged(rowCount, columnCount); } @@ -411,6 +445,28 @@ void Bars3dController::setSelectionMode(QDataVis::SelectionMode mode) Abstract3DController::setSelectionMode(mode); } +void Bars3dController::setSelectedBarPos(const QPoint &position) +{ + // TODO this will break once data window offset is implemented + QPoint pos = position; + if (pos.x() < 0 || pos.y() < 0 + || pos.x() >= m_data->rowCount() + || pos.y() >= m_data->rowAt(pos.x())->size()) { + pos = noSelectionPoint(); + } + + if (pos != m_selectedBarPos) { + m_selectedBarPos = pos; + m_changeTracker.selectedBarPosChanged = true; + emit selectedBarPosChanged(pos); + } +} + +QPoint Bars3dController::selectedBarPos() const +{ + return m_selectedBarPos; +} + QPoint Bars3dController::mousePosition() { return m_mousePos; diff --git a/src/datavis3d/engine/bars3dcontroller_p.h b/src/datavis3d/engine/bars3dcontroller_p.h index 521b4f32..60fd2c35 100644 --- a/src/datavis3d/engine/bars3dcontroller_p.h +++ b/src/datavis3d/engine/bars3dcontroller_p.h @@ -43,11 +43,13 @@ struct Bars3DChangeBitField { bool slicingActiveChanged : 1; bool sampleSpaceChanged : 1; bool barSpecsChanged : 1; + bool selectedBarPosChanged : 1; Bars3DChangeBitField() : slicingActiveChanged(true), sampleSpaceChanged(true), - barSpecsChanged(true) + barSpecsChanged(true), + selectedBarPosChanged(true) { } }; @@ -57,8 +59,6 @@ class QT_DATAVIS3D_EXPORT Bars3dController : public Abstract3DController Q_OBJECT private: - - Bars3DChangeBitField m_changeTracker; // Data @@ -69,6 +69,7 @@ private: MouseState m_mouseState; QPoint m_mousePos; bool m_isSlicingActivated; + QPoint m_selectedBarPos; // Points to row & column in data window. // Look'n'feel bool m_isBarSpecRelative; @@ -116,6 +117,9 @@ public: // Change selection mode; single bar, bar and row, bar and column, or all void setSelectionMode(QDataVis::SelectionMode mode); + void setSelectedBarPos(const QPoint &position); + QPoint selectedBarPos() const; + #if defined(Q_OS_ANDROID) void mouseDoubleClickEvent(QMouseEvent *event); void touchEvent(QTouchEvent *event); @@ -130,6 +134,8 @@ public: QBarDataProxy *dataProxy(); virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); + static QPoint noSelectionPoint(); + public slots: void handleArrayReset(); void handleRowsAdded(int startIndex, int count); @@ -138,11 +144,13 @@ public slots: void handleRowsInserted(int startIndex, int count); void handleItemChanged(int rowIndex, int columnIndex); + void handleSelectedBarPosChanged(const QPoint &position); signals: void slicingActiveChanged(bool isSlicing); void sampleSpaceChanged(int samplesRow, int samplesColumn); void barSpecsChanged(GLfloat thicknessRatio, QSizeF spacing, bool relative); + void selectedBarPosChanged(QPoint position); private: void adjustValueAxisRange(); diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp index f4ed21ef..89d9df9b 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -88,6 +88,7 @@ Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) m_scaleFactor(0), m_maxSceneSize(40.0), m_selection(selectionSkipColor), + m_previousSelection(selectionSkipColor), m_hasHeightAdjustmentChanged(true) { m_dummyBarRenderItem.setRenderer(this); @@ -662,14 +663,6 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, if (Bars3dController::MouseOnScene == m_controller->mouseState()) m_selection = Utils::getSelection(m_controller->mousePosition(), m_cachedBoundingRect.height()); - QMutexLocker locker(&m_mutex); - if (m_isSelectionPointRequestActive) { - m_isSelectionPointRequestActive = false; - m_selection = Utils::getSelection(m_selectionPointRequest, m_cachedBoundingRect.height()); - emit selectionUpdated(m_selection); - } - locker.unlock(); - glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); // Release selection shader @@ -700,12 +693,25 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Bind bar shader m_barShader->bind(); - // Draw bars - if (!m_cachedIsSlicingActivated && m_sliceSelection) { - m_sliceSelection->clear(); // Slice doesn't own its items - m_sliceCache = 0; - m_sliceTitleItem = 0; + bool selectionDirty = (m_selection != m_previousSelection + || (m_selection != selectionSkipColor + && Bars3dController::MouseOnScene == m_controller->mouseState() + && !m_cachedIsSlicingActivated)); + if (selectionDirty) { + m_previousSelection = m_selection; + if (m_sliceSelection) { + if (!m_cachedIsSlicingActivated) { + m_sliceCache = 0; + m_sliceTitleItem = 0; + } + if (m_sliceSelection->size()) { + // Slice doesn't own its items, no need to delete them - just clear + m_sliceSelection->clear(); + } + } } + + // Draw bars bool barSelectionFound = false; for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { @@ -752,15 +758,31 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, case Bars3dController::SelectionItem: { barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); lightStrength = m_cachedTheme.m_highlightLightStrength; - // Insert data to QDataItem. We have no ownership, don't delete the previous one + // Insert position data into render item. We have no ownership, don't delete the previous one if (!m_cachedIsSlicingActivated) { m_selectedBar = &item; m_selectedBar->setPosition(QPoint(row, bar)); item.setTranslation(modelMatrix.column(3).toVector3D()); barSelectionFound = true; - if (m_cachedSelectionMode >= QDataVis::ModeSliceRow) { - item.setTranslation(modelMatrix.column(3).toVector3D()); - m_sliceSelection->append(&item); + } + if (selectionDirty && m_cachedSelectionMode >= QDataVis::ModeSliceRow) { + item.setTranslation(modelMatrix.column(3).toVector3D()); + m_sliceSelection->append(&item); + barSelectionFound = true; + if (m_cachedSelectionMode == QDataVis::ModeSliceRow) { + if (m_axisCacheX.labelItems().size() > row) + m_sliceTitleItem = m_axisCacheX.labelItems().at(row); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheZ; + } + } else if (m_cachedSelectionMode == QDataVis::ModeSliceColumn) { + if (m_axisCacheZ.labelItems().size() > bar) + m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheX; + } } } break; @@ -769,15 +791,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Current bar is on the same row as the selected bar barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor); lightStrength = m_cachedTheme.m_highlightLightStrength; - if (!m_cachedIsSlicingActivated && QDataVis::ModeSliceRow == m_cachedSelectionMode) { + if (QDataVis::ModeSliceRow == m_cachedSelectionMode) { item.setTranslation(modelMatrix.column(3).toVector3D()); - m_sliceSelection->append(&item); - if (!m_sliceCache) { - // m_sliceCache is the axis for labels, while title comes from different axis. - m_sliceCache = &m_axisCacheZ; - if (m_axisCacheX.labelItems().size() > row) - m_sliceTitleItem = m_axisCacheX.labelItems().at(row); - } + if (selectionDirty) + m_sliceSelection->append(&item); } break; } @@ -785,16 +802,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Current bar is on the same column as the selected bar barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor); lightStrength = m_cachedTheme.m_highlightLightStrength; - if (!m_cachedIsSlicingActivated - && QDataVis::ModeSliceColumn == m_cachedSelectionMode) { + if (QDataVis::ModeSliceColumn == m_cachedSelectionMode) { item.setTranslation(modelMatrix.column(3).toVector3D()); - m_sliceSelection->append(&item); - if (!m_sliceCache) { - // m_sliceCache is the axis for labels, while title comes from different axis. - m_sliceCache = &m_axisCacheX; - if (m_axisCacheZ.labelItems().size() > bar) - m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar); - } + if (selectionDirty) + m_sliceSelection->append(&item); } break; } @@ -840,6 +851,9 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, } } + if (selectionDirty) + emit selectedBarPosChanged(QPoint(int(m_selection.x()), int(m_selection.y()))); + // Release bar shader m_barShader->release(); @@ -1307,10 +1321,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // We have no ownership, don't delete. Just NULL the pointer. m_selectedBar = NULL; if (m_cachedIsSlicingActivated - && Bars3dController::MouseOnOverview == m_controller->mouseState()) + && (m_selection == selectionSkipColor + || Bars3dController::MouseOnOverview == m_controller->mouseState())) m_controller->setSlicingActive(false); - } else if (m_cachedSelectionMode >= QDataVis::ModeSliceRow - && Bars3dController::MouseOnScene == m_controller->mouseState()) { + } else if (m_cachedSelectionMode >= QDataVis::ModeSliceRow && selectionDirty) { // Activate slice mode m_controller->setSlicingActive(true); @@ -1380,14 +1394,6 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, m_labelShader->release(); } -void Bars3dRenderer::requestSelectionAtPoint(const QPoint &point) -{ - QMutexLocker locker(&m_mutex); - m_selectionPointRequest.setX(point.x()); - m_selectionPointRequest.setY(point.y()); - m_isSelectionPointRequestActive = true; -} - void Bars3dRenderer::handleResize() { if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) @@ -1495,6 +1501,14 @@ void Bars3dRenderer::updateBackgroundEnabled(bool enable) } } +void Bars3dRenderer::updateSelectedBarPos(QPoint selectedBarPos) +{ + if (selectedBarPos == Bars3dController::noSelectionPoint()) + m_selection = selectionSkipColor; + else + m_selection = QVector3D(selectedBarPos.x(), selectedBarPos.y(), 0); +} + void Bars3dRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) { qDebug() << __FUNCTION__ << quality; diff --git a/src/datavis3d/engine/bars3drenderer_p.h b/src/datavis3d/engine/bars3drenderer_p.h index aecded6a..110bfea4 100644 --- a/src/datavis3d/engine/bars3drenderer_p.h +++ b/src/datavis3d/engine/bars3drenderer_p.h @@ -64,10 +64,6 @@ private: // TODO: Filter to the set of attributes to be moved to the model object. Bars3dController *m_controller; - // Mutex for sharing resources between render and main threads. - // TODO this mutex needs to go, too... - QMutex m_mutex; - // Cached state based on emitted signals from the controller QSizeF m_cachedBarThickness; QSizeF m_cachedBarSpacing; @@ -113,9 +109,7 @@ private: GLfloat m_scaleFactor; GLfloat m_maxSceneSize; QVector3D m_selection; - - QPoint m_selectionPointRequest; - bool m_isSelectionPointRequestActive; + QVector3D m_previousSelection; bool m_hasHeightAdjustmentChanged; BarRenderItem m_dummyBarRenderItem; @@ -149,17 +143,13 @@ public slots: void updateSlicingActive(bool isSlicing); void updateSampleSpace(int rowCount, int columnCount); void updateBackgroundEnabled(bool enable); + void updateSelectedBarPos(QPoint selectedBarPos); // Overloaded from abstract renderer virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); - // Requests that upon next render pass the column and row under the given point is inspected for selection. - // Only one request can be queued per render pass at this point. New request will override any pending requests. - // After inspection the selectionUpdated signal is emitted. - virtual void requestSelectionAtPoint(const QPoint &point); - signals: - void selectionUpdated(QVector3D selection); + void selectedBarPosChanged(QPoint position); private: virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp index e7812a17..73df356b 100644 --- a/src/datavis3d/engine/q3dbars.cpp +++ b/src/datavis3d/engine/q3dbars.cpp @@ -87,6 +87,8 @@ Q3DBars::Q3DBars() d_ptr->m_shared->initializeOpenGL(); QObject::connect(d_ptr->m_shared, &Abstract3DController::shadowQualityChanged, this, &Q3DBars::handleShadowQualityUpdate); + QObject::connect(d_ptr->m_shared, &Bars3dController::selectedBarPosChanged, this, + &Q3DBars::selectedBarPosChanged); } /*! @@ -404,6 +406,22 @@ bool Q3DBars::isBackgroundVisible() const } /*! + * \property Q3DBars::selectedBarPos + * + * Selects a bar in a \a position. Only one bar can be selected at a time. + * To clear selection, specify an illegal \a position, e.g. (-1, -1). + */ +void Q3DBars::setSelectedBarPos(const QPoint &position) +{ + d_ptr->m_shared->setSelectedBarPos(position); +} + +QPoint Q3DBars::selectedBarPos() const +{ + return d_ptr->m_shared->selectedBarPos(); +} + +/*! * \property Q3DBars::shadowQuality * * Sets shadow \a quality to one of \c QDataVis::ShadowQuality. It is preset to @@ -473,12 +491,6 @@ QBarDataProxy *Q3DBars::dataProxy() return d_ptr->m_shared->dataProxy(); } -/*! - * \fn void Q3DBars::shadowQualityChanged(QDataVis::ShadowQuality quality) - * - * This signal is emitted when shadow \a quality changes. - */ - Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) : q_ptr(q), m_shared(new Bars3dController(rect)) diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h index 537cc5b4..2b217085 100644 --- a/src/datavis3d/engine/q3dbars.h +++ b/src/datavis3d/engine/q3dbars.h @@ -35,12 +35,13 @@ class QT_DATAVIS3D_EXPORT Q3DBars : public Q3DWindow Q_OBJECT Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_PROPERTY(QPoint selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged) Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) @@ -94,6 +95,9 @@ public: void setBackgroundVisible(bool visible); bool isBackgroundVisible() const; + void setSelectedBarPos(const QPoint &position); + QPoint selectedBarPos() const; + void setShadowQuality(QDataVis::ShadowQuality quality); QDataVis::ShadowQuality shadowQuality() const; @@ -111,6 +115,7 @@ public slots: signals: void shadowQualityChanged(QDataVis::ShadowQuality quality); + void selectedBarPosChanged(QPoint position); protected: void render(); |