From 36bc54f5720bddb9899e64d665117ac1e1b5bc94 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 19 Sep 2014 13:32:31 +0300 Subject: Allow setting the floor level on bar graphs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTRD-3313 Change-Id: Ie0f8e36af8698081a6937c360043773da895b6e6 Reviewed-by: Tomi Korpipää --- .../doc/src/qtdatavisualization-qml-bars3d.qdoc | 8 ++++ src/datavisualization/engine/bars3dcontroller.cpp | 20 +++++++++ src/datavisualization/engine/bars3dcontroller_p.h | 7 +++- src/datavisualization/engine/bars3drenderer.cpp | 47 ++++++++++++++-------- src/datavisualization/engine/bars3drenderer_p.h | 3 ++ src/datavisualization/engine/q3dbars.cpp | 20 +++++++++ src/datavisualization/engine/q3dbars.h | 4 ++ .../datavisualizationqml2_plugin.cpp | 1 + src/datavisualizationqml2/declarativebars.cpp | 13 ++++++ src/datavisualizationqml2/declarativebars_p.h | 5 +++ tests/barstest/chart.cpp | 6 +++ tests/barstest/chart.h | 1 + tests/barstest/main.cpp | 11 ++++- tests/qmlcamera/qml/qmlcamera/main.qml | 2 + 14 files changed, 129 insertions(+), 19 deletions(-) diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc index 6ee51742..0348652a 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc @@ -114,6 +114,14 @@ * Defaults to the first added series or zero if no series are added to the graph. */ +/*! + * \qmlproperty real Bars3D::floorLevel + * + * The desired floor level for the bar graph in Y-axis data coordinates. + * The actual floor level cannot go below Y-axis minimum or above Y-axis maximum. + * Defaults to zero. + */ + /*! * \qmlmethod void Bars3D::addSeries(Bar3DSeries series) * Adds the \a series to the graph. A graph can contain multiple series, but only one set of axes, diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index bbec6967..2092dd60 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -36,6 +36,7 @@ Bars3DController::Bars3DController(QRect boundRect, Q3DScene *scene) m_isBarSpecRelative(true), m_barThicknessRatio(1.0f), m_barSpacing(QSizeF(1.0, 1.0)), + m_floorLevel(0.0f), m_renderer(0) { // Setting a null axis creates a new default axis according to orientation and graph type. @@ -83,6 +84,12 @@ void Bars3DController::synchDataToRenderer() needSceneUpdate = true; } + // Floor level update requires data update, so do before abstract sync + if (m_changeTracker.floorLevelChanged) { + m_renderer->updateFloorLevel(m_floorLevel); + m_changeTracker.floorLevelChanged = false; + } + Abstract3DController::synchDataToRenderer(); // Notify changes to renderer @@ -485,6 +492,19 @@ bool Bars3DController::isBarSpecRelative() return m_isBarSpecRelative; } +void Bars3DController::setFloorLevel(float level) +{ + m_floorLevel = level; + m_isDataDirty = true; + m_changeTracker.floorLevelChanged = true; + emitNeedRender(); +} + +float Bars3DController::floorLevel() const +{ + return m_floorLevel; +} + void Bars3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode) { if (mode.testFlag(QAbstract3DGraph::SelectionSlice) diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 4f0e1f20..ac62f37d 100644 --- a/src/datavisualization/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -43,13 +43,15 @@ struct Bars3DChangeBitField { bool selectedBarChanged : 1; bool rowsChanged : 1; bool itemChanged : 1; + bool floorLevelChanged : 1; Bars3DChangeBitField() : multiSeriesScalingChanged(true), barSpecsChanged(true), selectedBarChanged(true), rowsChanged(false), - itemChanged(false) + itemChanged(false), + floorLevelChanged(false) { } }; @@ -84,6 +86,7 @@ private: bool m_isBarSpecRelative; GLfloat m_barThicknessRatio; QSizeF m_barSpacing; + float m_floorLevel; // Rendering Bars3DRenderer *m_renderer; @@ -107,6 +110,8 @@ public: GLfloat barThickness(); QSizeF barSpacing(); bool isBarSpecRelative(); + void setFloorLevel(float level); + float floorLevel() const; inline QBar3DSeries *selectedSeries() const { return m_selectedBarSeries; } diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index e9cd9d43..9f3c2e2a 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -77,7 +77,9 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_haveGradientSeries(false), m_zeroPosition(0.0f), m_xScaleFactor(1.0f), - m_zScaleFactor(1.0f) + m_zScaleFactor(1.0f), + m_floorLevel(0.0f), + m_actualFloorLevel(0.0f) { m_axisCacheY.setScale(2.0f); m_axisCacheY.setTranslate(-1.0f); @@ -209,7 +211,7 @@ void Bars3DRenderer::updateData() calculateSceneScalingFactors(); - m_zeroPosition = m_axisCacheY.formatter()->positionAt(0.0f); + m_zeroPosition = m_axisCacheY.formatter()->positionAt(m_actualFloorLevel); foreach (SeriesRenderCache *baseCache, m_renderCacheList) { BarSeriesRenderCache *cache = static_cast(baseCache); @@ -2457,14 +2459,8 @@ void Bars3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientatio { Abstract3DRenderer::updateAxisRange(orientation, min, max); - if (orientation == QAbstract3DAxis::AxisOrientationY) { - // Check if we have negative values - if (min < 0) - m_hasNegativeValues = true; - else if (min >= 0) - m_hasNegativeValues = false; + if (orientation == QAbstract3DAxis::AxisOrientationY) calculateHeightAdjustment(); - } } void Bars3DRenderer::updateAxisReversed(QAbstract3DAxis::AxisOrientation orientation, bool enable) @@ -2602,24 +2598,33 @@ void Bars3DRenderer::calculateSceneScalingFactors() void Bars3DRenderer::calculateHeightAdjustment() { + float min = m_axisCacheY.min(); + float max = m_axisCacheY.max(); GLfloat newAdjustment = 1.0f; - GLfloat maxAbs = qFabs(m_axisCacheY.max()); - - if (m_axisCacheY.max() < 0.0f) { - m_heightNormalizer = GLfloat(qFabs(m_axisCacheY.min()) - qFabs(m_axisCacheY.max())); - maxAbs = qFabs(m_axisCacheY.max()) - qFabs(m_axisCacheY.min()); + m_actualFloorLevel = qBound(min, m_floorLevel, max); + GLfloat maxAbs = qFabs(max - m_actualFloorLevel); + + // Check if we have negative values + if (min < m_actualFloorLevel) + m_hasNegativeValues = true; + else if (min >= m_actualFloorLevel) + m_hasNegativeValues = false; + + if (max < m_actualFloorLevel) { + m_heightNormalizer = GLfloat(qFabs(min) - qFabs(max)); + maxAbs = qFabs(max) - qFabs(min); } else { - m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min()); + m_heightNormalizer = GLfloat(max - min); } // Height fractions are used in gradient calculations and are therefore doubled // Note that if max or min is exactly zero, we still consider it outside the range - if (m_axisCacheY.max() <= 0.0f || m_axisCacheY.min() >= 0.0f) { + if (max <= m_actualFloorLevel || min >= m_actualFloorLevel) { m_noZeroInRange = true; m_gradientFraction = 2.0f; } else { m_noZeroInRange = false; - GLfloat minAbs = qFabs(m_axisCacheY.min()); + GLfloat minAbs = qFabs(min - m_actualFloorLevel); m_gradientFraction = qMax(minAbs, maxAbs) / m_heightNormalizer * 2.0f; } @@ -2835,4 +2840,12 @@ void Bars3DRenderer::updateAspectRatio(float ratio) Q_UNUSED(ratio) } +void Bars3DRenderer::updateFloorLevel(float level) +{ + foreach (SeriesRenderCache *cache, m_renderCacheList) + cache->setDataDirty(true); + m_floorLevel = level; + calculateHeightAdjustment(); +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 47c9ab1d..92dae311 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -99,6 +99,8 @@ private: float m_zeroPosition; float m_xScaleFactor; float m_zScaleFactor; + float m_floorLevel; + float m_actualFloorLevel; public: explicit Bars3DRenderer(Bars3DController *controller); @@ -115,6 +117,7 @@ public: QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute); void updateAspectRatio(float ratio); + void updateFloorLevel(float level); protected: virtual void initializeOpenGL(); diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp index bb7aca89..d42c11b7 100644 --- a/src/datavisualization/engine/q3dbars.cpp +++ b/src/datavisualization/engine/q3dbars.cpp @@ -330,6 +330,26 @@ QBar3DSeries *Q3DBars::selectedSeries() const return dptrc()->m_shared->selectedSeries(); } +/*! + * \property Q3DBars::floorLevel + * + * The desired floor level for the bar graph in Y-axis data coordinates. + * The actual floor level cannot go below Y-axis minimum or above Y-axis maximum. + * Defaults to zero. + */ +void Q3DBars::setFloorLevel(float level) +{ + if (level != floorLevel()) { + dptr()->m_shared->setFloorLevel(level); + emit floorLevelChanged(level); + } +} + +float Q3DBars::floorLevel() const +{ + return dptrc()->m_shared->floorLevel(); +} + /*! * Adds \a axis to the graph. The axes added via addAxis are not yet taken to use, * addAxis is simply used to give the ownership of the \a axis to the graph. diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h index 7f9c981f..df1c846e 100644 --- a/src/datavisualization/engine/q3dbars.h +++ b/src/datavisualization/engine/q3dbars.h @@ -40,6 +40,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DBars : public QAbstract3DGraph Q_PROPERTY(QValue3DAxis *valueAxis READ valueAxis WRITE setValueAxis NOTIFY valueAxisChanged) Q_PROPERTY(QBar3DSeries *primarySeries READ primarySeries WRITE setPrimarySeries NOTIFY primarySeriesChanged) Q_PROPERTY(QBar3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) + Q_PROPERTY(float floorLevel READ floorLevel WRITE setFloorLevel NOTIFY floorLevelChanged) public: explicit Q3DBars(const QSurfaceFormat *format = 0, QWindow *parent = 0); @@ -75,6 +76,8 @@ public: QList axes() const; QBar3DSeries *selectedSeries() const; + void setFloorLevel(float level); + float floorLevel() const; signals: void multiSeriesUniformChanged(bool uniform); @@ -86,6 +89,7 @@ signals: void valueAxisChanged(QValue3DAxis *axis); void primarySeriesChanged(QBar3DSeries *series); void selectedSeriesChanged(QBar3DSeries *series); + void floorLevelChanged(float level); private: Q3DBarsPrivate *dptr(); diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp index ecdd7454..a22fc55c 100644 --- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp @@ -116,6 +116,7 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri) qmlRegisterType(uri, 1, 2, "Surface3D"); qmlRegisterType(uri, 1, 2, "Camera3D"); qmlRegisterType(uri, 1, 2, "Custom3DItem"); + qmlRegisterType(uri, 1, 2, "Bars3D"); // New types qmlRegisterType(uri, 1, 2, "InputHandler3D"); diff --git a/src/datavisualizationqml2/declarativebars.cpp b/src/datavisualizationqml2/declarativebars.cpp index 9670a7db..61e6aafb 100644 --- a/src/datavisualizationqml2/declarativebars.cpp +++ b/src/datavisualizationqml2/declarativebars.cpp @@ -129,6 +129,19 @@ QBar3DSeries *DeclarativeBars::selectedSeries() const return m_barsController->selectedSeries(); } +void DeclarativeBars::setFloorLevel(float level) +{ + if (level != floorLevel()) { + m_barsController->setFloorLevel(level); + emit floorLevelChanged(level); + } +} + +float DeclarativeBars::floorLevel() const +{ + return m_barsController->floorLevel(); +} + QQmlListProperty DeclarativeBars::seriesList() { return QQmlListProperty(this, this, diff --git a/src/datavisualizationqml2/declarativebars_p.h b/src/datavisualizationqml2/declarativebars_p.h index 52690813..05d66cdc 100644 --- a/src/datavisualizationqml2/declarativebars_p.h +++ b/src/datavisualizationqml2/declarativebars_p.h @@ -48,6 +48,7 @@ class DeclarativeBars : public AbstractDeclarative Q_PROPERTY(QQmlListProperty seriesList READ seriesList) Q_PROPERTY(QBar3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) Q_PROPERTY(QBar3DSeries *primarySeries READ primarySeries WRITE setPrimarySeries NOTIFY primarySeriesChanged) + Q_PROPERTY(float floorLevel READ floorLevel WRITE setFloorLevel NOTIFY floorLevelChanged REVISION 1) Q_CLASSINFO("DefaultProperty", "seriesList") public: @@ -85,6 +86,9 @@ public: QBar3DSeries *primarySeries() const; QBar3DSeries *selectedSeries() const; + void setFloorLevel(float level); + float floorLevel() const; + public slots: void handleAxisXChanged(QAbstract3DAxis *axis); void handleAxisYChanged(QAbstract3DAxis *axis); @@ -101,6 +105,7 @@ signals: void meshFileNameChanged(QString filename); void primarySeriesChanged(QBar3DSeries *series); void selectedSeriesChanged(QBar3DSeries *series); + Q_REVISION(1) void floorLevelChanged(float level); private: Bars3DController *m_barsController; diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index 137ce88e..9a81fc86 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -1519,6 +1519,12 @@ void GraphModifier::setCameraTargetZ(int value) qDebug() << "m_cameraTarget:" << m_cameraTarget; } +void GraphModifier::setFloorLevel(int value) +{ + m_graph->setFloorLevel(float(value)); + qDebug() << "Floor level:" << value; +} + void GraphModifier::populateFlatSeries(QBar3DSeries *series, int rows, int columns, float value) { QBarDataArray *dataArray = new QBarDataArray; diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index a5061df4..eac6d3f1 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -124,6 +124,7 @@ public slots: void setCameraTargetX(int value); void setCameraTargetY(int value); void setCameraTargetZ(int value); + void setFloorLevel(int value); signals: void shadowQualityChanged(int quality); diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index 409ecbab..1cc47859 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -262,6 +262,11 @@ int main(int argc, char **argv) reflectivitySlider->setValue(50); reflectivitySlider->setMaximum(100); + QSlider *floorLevelSlider = new QSlider(Qt::Horizontal, widget); + floorLevelSlider->setMinimum(-50); + floorLevelSlider->setValue(0); + floorLevelSlider->setMaximum(50); + QPushButton *toggleCustomItemButton = new QPushButton(widget); toggleCustomItemButton->setText(QStringLiteral("Toggle Custom Item")); @@ -435,7 +440,9 @@ int main(int argc, char **argv) vLayout3->addWidget(cameraTargetSliderZ, 0, Qt::AlignTop); vLayout3->addWidget(reflectionCheckBox, 0, Qt::AlignTop); vLayout3->addWidget(reflectivitySlider, 0, Qt::AlignTop); - vLayout3->addWidget(toggleCustomItemButton, 1, Qt::AlignTop); + vLayout3->addWidget(toggleCustomItemButton, 0, Qt::AlignTop); + vLayout3->addWidget(new QLabel(QStringLiteral("Adjust floor level")), 0, Qt::AlignTop); + vLayout3->addWidget(floorLevelSlider, 1, Qt::AlignTop); widget->show(); @@ -568,6 +575,8 @@ int main(int argc, char **argv) &GraphModifier::setReflection); QObject::connect(reflectivitySlider, &QSlider::valueChanged, modifier, &GraphModifier::setReflectivity); + QObject::connect(floorLevelSlider, &QSlider::valueChanged, modifier, + &GraphModifier::setFloorLevel); QObject::connect(toggleCustomItemButton, &QPushButton::clicked, modifier, &GraphModifier::toggleCustomItem); diff --git a/tests/qmlcamera/qml/qmlcamera/main.qml b/tests/qmlcamera/qml/qmlcamera/main.qml index cb22af59..be4feca3 100644 --- a/tests/qmlcamera/qml/qmlcamera/main.qml +++ b/tests/qmlcamera/qml/qmlcamera/main.qml @@ -74,6 +74,8 @@ Rectangle { customItemList: [shuttleItem, labelItem] orthoProjection: true + + floorLevel: 10 } Custom3DItem { -- cgit v1.2.3