From aaf51bfad10e0eac7a8ee64e36aab5f0c1119468 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 2 Apr 2014 12:16:05 +0300 Subject: Enable querying selection label via API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also enable suppressing drawing the label on graph. Selection label formatting was consequently moved from renderers to series. Task-number: QTRD-2896 Change-Id: Ia6a1a40298d8db0f54349de3eb27fb0b683dd302 Reviewed-by: Tomi Korpipää --- .../qmlaxisformatter/customformatter.cpp | 1 + .../qmloscilloscope/datasource.cpp | 23 ---- .../datavisualization/qmloscilloscope/datasource.h | 3 - .../qmloscilloscope/doc/src/qmloscilloscope.qdoc | 15 +-- .../qmloscilloscope/qml/qmloscilloscope/main.qml | 31 ++--- src/datavisualization/axis/qvalue3daxisformatter.h | 3 + src/datavisualization/data/qabstract3dseries.cpp | 101 +++++++++++++-- src/datavisualization/data/qabstract3dseries.h | 8 ++ src/datavisualization/data/qabstract3dseries_p.h | 18 ++- src/datavisualization/data/qbar3dseries.cpp | 51 ++++++++ src/datavisualization/data/qbar3dseries_p.h | 1 + src/datavisualization/data/qscatter3dseries.cpp | 45 +++++++ src/datavisualization/data/qscatter3dseries_p.h | 1 + src/datavisualization/data/qsurface3dseries.cpp | 45 +++++++ src/datavisualization/data/qsurface3dseries_p.h | 1 + .../engine/abstract3dcontroller.cpp | 12 ++ .../engine/abstract3dcontroller_p.h | 2 + .../engine/abstract3drenderer.cpp | 8 +- src/datavisualization/engine/bars3dcontroller.cpp | 3 + src/datavisualization/engine/bars3drenderer.cpp | 136 +++++++++------------ src/datavisualization/engine/bars3drenderer_p.h | 4 +- .../engine/scatter3dcontroller.cpp | 2 + src/datavisualization/engine/scatter3drenderer.cpp | 47 +++---- src/datavisualization/engine/seriesrendercache.cpp | 17 ++- src/datavisualization/engine/seriesrendercache_p.h | 4 +- .../engine/surface3dcontroller.cpp | 7 ++ src/datavisualization/engine/surface3drenderer.cpp | 65 +++------- src/datavisualization/engine/surface3drenderer_p.h | 1 - .../datavisualizationqml2_plugin.cpp | 4 + tests/barstest/main.cpp | 2 +- 30 files changed, 414 insertions(+), 247 deletions(-) diff --git a/examples/datavisualization/qmlaxisformatter/customformatter.cpp b/examples/datavisualization/qmlaxisformatter/customformatter.cpp index eeea0451..4a52d273 100644 --- a/examples/datavisualization/qmlaxisformatter/customformatter.cpp +++ b/examples/datavisualization/qmlaxisformatter/customformatter.cpp @@ -142,6 +142,7 @@ void CustomFormatter::setSelectionFormat(const QString &format) { if (m_selectionFormat != format) { m_selectionFormat = format; + markDirty(true); // Necessary to regenerate already visible selection label emit selectionFormatChanged(format); } } diff --git a/examples/datavisualization/qmloscilloscope/datasource.cpp b/examples/datavisualization/qmloscilloscope/datasource.cpp index 01d7e73d..40ebd962 100644 --- a/examples/datavisualization/qmloscilloscope/datasource.cpp +++ b/examples/datavisualization/qmloscilloscope/datasource.cpp @@ -138,29 +138,6 @@ void DataSource::update(QSurface3DSeries *series) } //! [1] -//! [2] -QString DataSource::selectionLabel(QSurface3DSeries *series, QValue3DAxis *axisX, - QValue3DAxis *axisY, QValue3DAxis *axisZ) -{ - QString label; - - if (series && series->selectedPoint() != QSurface3DSeries::invalidSelectionPosition()) { - const QSurfaceDataItem *item = series->dataProxy()->itemAt(series->selectedPoint()); - QString x; - QString y; - QString z; - x.sprintf(axisX->labelFormat().toUtf8().constData(), int(item->x())); - y.sprintf(axisY->labelFormat().toUtf8().constData(), int(item->y())); - z.sprintf(axisZ->labelFormat().toUtf8().constData(), int(item->z())); - label = QStringLiteral("%1, %3: %2").arg(x).arg(y).arg(z); - } else { - label = QStringLiteral("No selection"); - } - - return label; -} -//! [2] - void DataSource::clearData() { for (int i(0); i < m_data.size(); i++) { diff --git a/examples/datavisualization/qmloscilloscope/datasource.h b/examples/datavisualization/qmloscilloscope/datasource.h index 4f210269..76ba7c9c 100644 --- a/examples/datavisualization/qmloscilloscope/datasource.h +++ b/examples/datavisualization/qmloscilloscope/datasource.h @@ -37,9 +37,6 @@ public slots: float xMin, float xMax, float yMin, float yMax, float zMin, float zMax); void update(QSurface3DSeries *series); - - QString selectionLabel(QSurface3DSeries *series, QValue3DAxis *axisX, - QValue3DAxis *axisY, QValue3DAxis *axisZ); //! [0] private: void clearData(); diff --git a/examples/datavisualization/qmloscilloscope/doc/src/qmloscilloscope.qdoc b/examples/datavisualization/qmloscilloscope/doc/src/qmloscilloscope.qdoc index c574950b..93bd5c30 100644 --- a/examples/datavisualization/qmloscilloscope/doc/src/qmloscilloscope.qdoc +++ b/examples/datavisualization/qmloscilloscope/doc/src/qmloscilloscope.qdoc @@ -59,11 +59,6 @@ we still need to call QSurfaceDataProxy::resetArray() after changing the data in it to prompt the graph to render the data. - The final method, \c selectionLabel(), is used to generate a label string we can show on the - QML ui. This method utilizes the axis formats to format the label: - - \snippet qmloscilloscope/datasource.cpp 2 - To be able to access the \c DataSource methods from QML, we need to expose it. We do this by defining a context property in application main: @@ -86,15 +81,11 @@ One interesting detail is that we don't specify a proxy for the Surface3DSeries we attach to the graph. This makes the series to utilize the default QSurfaceDataProxy. - We also specify an empty string for \l{Abstract3DSeries::itemLabelFormat}{itemLabelFormat}, since we want to display - the selected item information in a \c Text element instead of a label above the selection pointer. + We also hide the item label with \l{Abstract3DSeries::itemLabelVisible}{itemLabelFormat}, since + we want to display the selected item information in a \c Text element instead of a floating + label above the selection pointer. This is done because the selection pointer moves around a lot as the data changes, which makes the regular selection label difficult to read. - When selection point changes, we update the label text using a helper function - \c updateSelectionLabel(), which calls one of the methods we defined for our \c DataSource class - to obtain the label: - - \snippet qmloscilloscope/qml/qmloscilloscope/main.qml 1 We initialize the \c DataSource cache when the graph is complete by calling a helper function \c generateData(), which calls the method with the same name on the \c DataSource: diff --git a/examples/datavisualization/qmloscilloscope/qml/qmloscilloscope/main.qml b/examples/datavisualization/qmloscilloscope/qml/qmloscilloscope/main.qml index 81884154..5f5bfe1a 100644 --- a/examples/datavisualization/qmloscilloscope/qml/qmloscilloscope/main.qml +++ b/examples/datavisualization/qmloscilloscope/qml/qmloscilloscope/main.qml @@ -19,7 +19,7 @@ import QtQuick 2.1 import QtQuick.Layouts 1.0 import QtQuick.Controls 1.0 -import QtDataVisualization 1.0 +import QtDataVisualization 1.1 import "." Item { @@ -72,9 +72,8 @@ Item { drawMode: Surface3DSeries.DrawSurface; flatShadingEnabled: false; meshSmooth: true - itemLabelFormat: "" - - onSelectedPointChanged: mainView.updateSelectionLabel() + itemLabelFormat: "@xLabel, @zLabel: @yLabel" + itemLabelVisible: false } //! [0] @@ -90,10 +89,7 @@ Item { interval: 1000 / frequencySlider.value running: true repeat: true - onTriggered: { - dataSource.update(surfaceSeries) - mainView.updateSelectionLabel() - } + onTriggered: dataSource.update(surfaceSeries) } //! [3] @@ -218,10 +214,18 @@ Item { Text { id: selectionText - text: "No selection" anchors.fill: parent verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter + + Binding on text { + when: surfaceSeries.itemLabel.length + value: surfaceSeries.itemLabel + } + Binding on text { + when: !surfaceSeries.itemLabel.length + value: "No selection" + } } } } @@ -285,15 +289,6 @@ Item { } - //! [1] - function updateSelectionLabel() { - selectionText.text = dataSource.selectionLabel(surfaceSeries, - surfaceGraph.axisX, - surfaceGraph.axisY, - surfaceGraph.axisZ) - } - //! [1] - //! [4] function generateData() { dataSource.generateData(mainView.sampleCache, mainView.sampleRows, diff --git a/src/datavisualization/axis/qvalue3daxisformatter.h b/src/datavisualization/axis/qvalue3daxisformatter.h index 5ecc798d..c7b0bac5 100644 --- a/src/datavisualization/axis/qvalue3daxisformatter.h +++ b/src/datavisualization/axis/qvalue3daxisformatter.h @@ -76,6 +76,9 @@ private: friend class QValue3DAxis; friend class QValue3DAxisPrivate; friend class AxisRenderCache; + friend class QBar3DSeriesPrivate; + friend class QScatter3DSeriesPrivate; + friend class QSurface3DSeriesPrivate; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/data/qabstract3dseries.cpp b/src/datavisualization/data/qabstract3dseries.cpp index 802a4e8e..934fad16 100644 --- a/src/datavisualization/data/qabstract3dseries.cpp +++ b/src/datavisualization/data/qabstract3dseries.cpp @@ -240,6 +240,25 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION * \sa itemLabelFormat */ +/*! + * \qmlproperty string Abstract3DSeries::itemLabel + * + * Contains the formatted item label. If there is no selected item or the selected item is not + * visible, returns an empty string. + * + * \sa itemLabelFormat + */ + +/*! + * \qmlproperty bool Abstract3DSeries::itemLabelVisible + * + * If \c true, item labels are drawn as floating labels in the graph. Otherwise item labels are not + * drawn. If you prefer to show the item label in an external control, set this property to + * \c false. Defaults to \c true. + * + * \sa itemLabelFormat, itemLabel + */ + /*! * \qmlmethod void Abstract3DSeries::setMeshAxisAndAngle(vector3d axis, real angle) * @@ -587,6 +606,41 @@ QString QAbstract3DSeries::name() const return d_ptr->m_name; } +/*! + * \property QAbstract3DSeries::itemLabel + * + * Contains the formatted item label. If there is no selected item or the selected item is not + * visible, returns an empty string. + * + * \sa itemLabelFormat + */ +QString QAbstract3DSeries::itemLabel() const +{ + return d_ptr->itemLabel(); +} + +/*! + * \property QAbstract3DSeries::itemLabelVisible + * + * If \c true, item labels are drawn as floating labels in the graph. Otherwise item labels are not + * drawn. If you prefer to show the item label in an external control, set this property to + * \c false. Defaults to \c true. + * + * \sa itemLabelFormat, itemLabel + */ +void QAbstract3DSeries::setItemLabelVisible(bool visible) +{ + if (d_ptr->m_itemLabelVisible != visible) { + d_ptr->setItemLabelVisible(visible); + emit itemLabelVisibilityChanged(visible); + } +} + +bool QAbstract3DSeries::isItemLabelVisible() const +{ + return d_ptr->m_itemLabelVisible; +} + // QAbstract3DSeriesPrivate QAbstract3DSeriesPrivate::QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type) @@ -598,7 +652,9 @@ QAbstract3DSeriesPrivate::QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstra m_controller(0), m_mesh(QAbstract3DSeries::MeshCube), m_meshSmooth(false), - m_colorStyle(Q3DTheme::ColorStyleUniform) + m_colorStyle(Q3DTheme::ColorStyleUniform), + m_itemLabelDirty(true), + m_itemLabelVisible(true) { } @@ -631,21 +687,19 @@ void QAbstract3DSeriesPrivate::setController(Abstract3DController *controller) connectControllerAndProxy(controller); m_controller = controller; q_ptr->setParent(controller); + markItemLabelDirty(); } void QAbstract3DSeriesPrivate::setItemLabelFormat(const QString &format) { m_itemLabelFormat = format; - m_changeTracker.itemLabelFormatChanged = true; - if (m_controller) - m_controller->markSeriesVisualsDirty(); + markItemLabelDirty(); } void QAbstract3DSeriesPrivate::setVisible(bool visible) { m_visible = visible; - if (m_controller) - m_controller->markSeriesVisualsDirty(); + markItemLabelDirty(); } void QAbstract3DSeriesPrivate::setMesh(QAbstract3DSeries::Mesh mesh) @@ -739,9 +793,8 @@ void QAbstract3DSeriesPrivate::setMultiHighlightGradient(const QLinearGradient & void QAbstract3DSeriesPrivate::setName(const QString &name) { m_name = name; + markItemLabelDirty(); m_changeTracker.nameChanged = true; - if (m_controller) - m_controller->markSeriesVisualsDirty(); } void QAbstract3DSeriesPrivate::resetToTheme(const Q3DTheme &theme, int seriesIndex, bool force) @@ -781,4 +834,36 @@ void QAbstract3DSeriesPrivate::resetToTheme(const Q3DTheme &theme, int seriesInd } } +QString QAbstract3DSeriesPrivate::itemLabel() +{ + if (m_itemLabelDirty) { + QString oldLabel = m_itemLabel; + if (m_controller && m_visible) + createItemLabel(); + else + m_itemLabel = QString(); + m_itemLabelDirty = false; + + if (oldLabel != m_itemLabel) + emit q_ptr->itemLabelChanged(m_itemLabel); + } + + return m_itemLabel; +} + +void QAbstract3DSeriesPrivate::markItemLabelDirty() +{ + m_itemLabelDirty = true; + m_changeTracker.itemLabelChanged = true; + if (m_controller) + m_controller->markSeriesVisualsDirty(); +} + +void QAbstract3DSeriesPrivate::setItemLabelVisible(bool visible) +{ + m_itemLabelVisible = visible; + markItemLabelDirty(); + m_changeTracker.itemLabelVisibilityChanged = true; +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h index bf56422f..55254904 100644 --- a/src/datavisualization/data/qabstract3dseries.h +++ b/src/datavisualization/data/qabstract3dseries.h @@ -50,6 +50,8 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DSeries : public QObject Q_PROPERTY(QColor multiHighlightColor READ multiHighlightColor WRITE setMultiHighlightColor NOTIFY multiHighlightColorChanged) Q_PROPERTY(QLinearGradient multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString itemLabel READ itemLabel NOTIFY itemLabelChanged REVISION 1) + Q_PROPERTY(bool itemLabelVisible READ isItemLabelVisible WRITE setItemLabelVisible NOTIFY itemLabelVisibilityChanged REVISION 1) public: enum SeriesType { @@ -119,6 +121,10 @@ public: void setName(const QString &name); QString name() const; + QString itemLabel() const; + void setItemLabelVisible(bool visible); + bool isItemLabelVisible() const; + signals: void itemLabelFormatChanged(const QString &format); void visibilityChanged(bool visible); @@ -134,6 +140,8 @@ signals: void multiHighlightColorChanged(const QColor &color); void multiHighlightGradientChanged(const QLinearGradient &gradient); void nameChanged(const QString &name); + void itemLabelChanged(const QString &label); + void itemLabelVisibilityChanged(bool visible); protected: QScopedPointer d_ptr; diff --git a/src/datavisualization/data/qabstract3dseries_p.h b/src/datavisualization/data/qabstract3dseries_p.h index a803e99b..530afe5e 100644 --- a/src/datavisualization/data/qabstract3dseries_p.h +++ b/src/datavisualization/data/qabstract3dseries_p.h @@ -38,7 +38,6 @@ class QAbstractDataProxy; class Abstract3DController; struct QAbstract3DSeriesChangeBitField { - bool itemLabelFormatChanged : 1; bool meshChanged : 1; bool meshSmoothChanged : 1; bool meshRotationChanged : 1; @@ -51,10 +50,11 @@ struct QAbstract3DSeriesChangeBitField { bool multiHighlightColorChanged : 1; bool multiHighlightGradientChanged : 1; bool nameChanged : 1; + bool itemLabelChanged : 1; + bool itemLabelVisibilityChanged : 1; QAbstract3DSeriesChangeBitField() - : itemLabelFormatChanged(true), - meshChanged(true), + : meshChanged(true), meshSmoothChanged(true), meshRotationChanged(true), userDefinedMeshChanged(true), @@ -65,7 +65,9 @@ struct QAbstract3DSeriesChangeBitField { singleHighlightGradientChanged(true), multiHighlightColorChanged(true), multiHighlightGradientChanged(true), - nameChanged(true) + nameChanged(true), + itemLabelChanged(true), + itemLabelVisibilityChanged(true) { } }; @@ -102,6 +104,7 @@ public: virtual void setDataProxy(QAbstractDataProxy *proxy); virtual void setController(Abstract3DController *controller); virtual void connectControllerAndProxy(Abstract3DController *newController) = 0; + virtual void createItemLabel() = 0; void setItemLabelFormat(const QString &format); void setVisible(bool visible); @@ -120,6 +123,10 @@ public: void setName(const QString &name); void resetToTheme(const Q3DTheme &theme, int seriesIndex, bool force); + QString itemLabel(); + void markItemLabelDirty(); + inline bool itemLabelDirty() const { return m_itemLabelDirty; } + void setItemLabelVisible(bool visible); QAbstract3DSeriesChangeBitField m_changeTracker; QAbstract3DSeriesThemeOverrideBitField m_themeTracker; @@ -143,6 +150,9 @@ public: QLinearGradient m_multiHighlightGradient; QString m_name; + QString m_itemLabel; + bool m_itemLabelDirty; + bool m_itemLabelVisible; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/data/qbar3dseries.cpp b/src/datavisualization/data/qbar3dseries.cpp index ed4ffaba..8a05100f 100644 --- a/src/datavisualization/data/qbar3dseries.cpp +++ b/src/datavisualization/data/qbar3dseries.cpp @@ -317,6 +317,56 @@ void QBar3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newCon } } +void QBar3DSeriesPrivate::createItemLabel() +{ + static const QString rowIndexTag(QStringLiteral("@rowIdx")); + static const QString rowLabelTag(QStringLiteral("@rowLabel")); + static const QString rowTitleTag(QStringLiteral("@rowTitle")); + static const QString colIndexTag(QStringLiteral("@colIdx")); + static const QString colLabelTag(QStringLiteral("@colLabel")); + static const QString colTitleTag(QStringLiteral("@colTitle")); + static const QString valueTitleTag(QStringLiteral("@valueTitle")); + static const QString valueLabelTag(QStringLiteral("@valueLabel")); + static const QString seriesNameTag(QStringLiteral("@seriesName")); + + if (m_selectedBar == QBar3DSeries::invalidSelectionPosition()) { + m_itemLabel = QString(); + return; + } + + QCategory3DAxis *categoryAxisZ = static_cast(m_controller->axisZ()); + QCategory3DAxis *categoryAxisX = static_cast(m_controller->axisX()); + QValue3DAxis *valueAxis = static_cast(m_controller->axisY()); + qreal selectedBarValue = qreal(qptr()->dataProxy()->itemAt(m_selectedBar)->value()); + + // Custom format expects printf format specifier. There is no tag for it. + m_itemLabel = valueAxis->formatter()->stringForValue(selectedBarValue, m_itemLabelFormat); + + int selBarPosRow = m_selectedBar.x(); + int selBarPosCol = m_selectedBar.y(); + m_itemLabel.replace(rowIndexTag, QString::number(selBarPosRow)); + if (categoryAxisZ->labels().size() > selBarPosRow) + m_itemLabel.replace(rowLabelTag, categoryAxisZ->labels().at(selBarPosRow)); + else + m_itemLabel.replace(rowLabelTag, QString()); + m_itemLabel.replace(rowTitleTag, categoryAxisZ->title()); + m_itemLabel.replace(colIndexTag, QString::number(selBarPosCol)); + if (categoryAxisX->labels().size() > selBarPosCol) + m_itemLabel.replace(colLabelTag, categoryAxisX->labels().at(selBarPosCol)); + else + m_itemLabel.replace(colLabelTag, QString()); + m_itemLabel.replace(colTitleTag, categoryAxisX->title()); + m_itemLabel.replace(valueTitleTag, valueAxis->title()); + + if (m_itemLabel.contains(valueLabelTag)) { + QString valueLabelText = valueAxis->formatter()->stringForValue(selectedBarValue, + valueAxis->labelFormat()); + m_itemLabel.replace(valueLabelTag, valueLabelText); + } + + m_itemLabel.replace(seriesNameTag, m_name); +} + void QBar3DSeriesPrivate::handleMeshRotationChanged(const QQuaternion &rotation) { emit qptr()->meshAngleChanged(quaternionAngle(rotation)); @@ -325,6 +375,7 @@ void QBar3DSeriesPrivate::handleMeshRotationChanged(const QQuaternion &rotation) void QBar3DSeriesPrivate::setSelectedBar(const QPoint &position) { if (position != m_selectedBar) { + markItemLabelDirty(); m_selectedBar = position; emit qptr()->selectedBarChanged(m_selectedBar); } diff --git a/src/datavisualization/data/qbar3dseries_p.h b/src/datavisualization/data/qbar3dseries_p.h index 718f1237..c5b51108 100644 --- a/src/datavisualization/data/qbar3dseries_p.h +++ b/src/datavisualization/data/qbar3dseries_p.h @@ -43,6 +43,7 @@ public: virtual void setDataProxy(QAbstractDataProxy *proxy); virtual void connectControllerAndProxy(Abstract3DController *newController); + virtual void createItemLabel(); void handleMeshRotationChanged(const QQuaternion &rotation); diff --git a/src/datavisualization/data/qscatter3dseries.cpp b/src/datavisualization/data/qscatter3dseries.cpp index 43bde4dd..f4509ae4 100644 --- a/src/datavisualization/data/qscatter3dseries.cpp +++ b/src/datavisualization/data/qscatter3dseries.cpp @@ -298,9 +298,54 @@ void QScatter3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *ne } } +void QScatter3DSeriesPrivate::createItemLabel() +{ + static const QString xTitleTag(QStringLiteral("@xTitle")); + static const QString yTitleTag(QStringLiteral("@yTitle")); + static const QString zTitleTag(QStringLiteral("@zTitle")); + static const QString xLabelTag(QStringLiteral("@xLabel")); + static const QString yLabelTag(QStringLiteral("@yLabel")); + static const QString zLabelTag(QStringLiteral("@zLabel")); + static const QString seriesNameTag(QStringLiteral("@seriesName")); + + if (m_selectedItem == QScatter3DSeries::invalidSelectionIndex()) { + m_itemLabel = QString(); + return; + } + + QValue3DAxis *axisX = static_cast(m_controller->axisX()); + QValue3DAxis *axisY = static_cast(m_controller->axisY()); + QValue3DAxis *axisZ = static_cast(m_controller->axisZ()); + QVector3D selectedPosition = qptr()->dataProxy()->itemAt(m_selectedItem)->position(); + + m_itemLabel = m_itemLabelFormat; + + m_itemLabel.replace(xTitleTag, axisX->title()); + m_itemLabel.replace(yTitleTag, axisY->title()); + m_itemLabel.replace(zTitleTag, axisZ->title()); + + if (m_itemLabel.contains(xLabelTag)) { + QString valueLabelText = axisX->formatter()->stringForValue( + qreal(selectedPosition.x()), axisX->labelFormat()); + m_itemLabel.replace(xLabelTag, valueLabelText); + } + if (m_itemLabel.contains(yLabelTag)) { + QString valueLabelText = axisY->formatter()->stringForValue( + qreal(selectedPosition.y()), axisY->labelFormat()); + m_itemLabel.replace(yLabelTag, valueLabelText); + } + if (m_itemLabel.contains(zLabelTag)) { + QString valueLabelText = axisZ->formatter()->stringForValue( + qreal(selectedPosition.z()), axisZ->labelFormat()); + m_itemLabel.replace(zLabelTag, valueLabelText); + } + m_itemLabel.replace(seriesNameTag, m_name); +} + void QScatter3DSeriesPrivate::setSelectedItem(int index) { if (index != m_selectedItem) { + markItemLabelDirty(); m_selectedItem = index; emit qptr()->selectedItemChanged(m_selectedItem); } diff --git a/src/datavisualization/data/qscatter3dseries_p.h b/src/datavisualization/data/qscatter3dseries_p.h index 1abbd406..8717a616 100644 --- a/src/datavisualization/data/qscatter3dseries_p.h +++ b/src/datavisualization/data/qscatter3dseries_p.h @@ -43,6 +43,7 @@ public: virtual void setDataProxy(QAbstractDataProxy *proxy); virtual void connectControllerAndProxy(Abstract3DController *newController); + virtual void createItemLabel(); void setSelectedItem(int index); void setItemSize(float size); diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp index 72967bae..60e84f38 100644 --- a/src/datavisualization/data/qsurface3dseries.cpp +++ b/src/datavisualization/data/qsurface3dseries.cpp @@ -373,9 +373,54 @@ void QSurface3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *ne } } +void QSurface3DSeriesPrivate::createItemLabel() +{ + static const QString xTitleTag(QStringLiteral("@xTitle")); + static const QString yTitleTag(QStringLiteral("@yTitle")); + static const QString zTitleTag(QStringLiteral("@zTitle")); + static const QString xLabelTag(QStringLiteral("@xLabel")); + static const QString yLabelTag(QStringLiteral("@yLabel")); + static const QString zLabelTag(QStringLiteral("@zLabel")); + static const QString seriesNameTag(QStringLiteral("@seriesName")); + + if (m_selectedPoint == QSurface3DSeries::invalidSelectionPosition()) { + m_itemLabel = QString(); + return; + } + + QValue3DAxis *axisX = static_cast(m_controller->axisX()); + QValue3DAxis *axisY = static_cast(m_controller->axisY()); + QValue3DAxis *axisZ = static_cast(m_controller->axisZ()); + QVector3D selectedPosition = qptr()->dataProxy()->itemAt(m_selectedPoint)->position(); + + m_itemLabel = m_itemLabelFormat; + + m_itemLabel.replace(xTitleTag, axisX->title()); + m_itemLabel.replace(yTitleTag, axisY->title()); + m_itemLabel.replace(zTitleTag, axisZ->title()); + + if (m_itemLabel.contains(xLabelTag)) { + QString valueLabelText = axisX->formatter()->stringForValue( + qreal(selectedPosition.x()), axisX->labelFormat()); + m_itemLabel.replace(xLabelTag, valueLabelText); + } + if (m_itemLabel.contains(yLabelTag)) { + QString valueLabelText = axisY->formatter()->stringForValue( + qreal(selectedPosition.y()), axisY->labelFormat()); + m_itemLabel.replace(yLabelTag, valueLabelText); + } + if (m_itemLabel.contains(zLabelTag)) { + QString valueLabelText = axisZ->formatter()->stringForValue( + qreal(selectedPosition.z()), axisZ->labelFormat()); + m_itemLabel.replace(zLabelTag, valueLabelText); + } + m_itemLabel.replace(seriesNameTag, m_name); +} + void QSurface3DSeriesPrivate::setSelectedPoint(const QPoint &position) { if (position != m_selectedPoint) { + markItemLabelDirty(); m_selectedPoint = position; emit qptr()->selectedPointChanged(m_selectedPoint); } diff --git a/src/datavisualization/data/qsurface3dseries_p.h b/src/datavisualization/data/qsurface3dseries_p.h index bc8157bd..d4cc2820 100644 --- a/src/datavisualization/data/qsurface3dseries_p.h +++ b/src/datavisualization/data/qsurface3dseries_p.h @@ -43,6 +43,7 @@ public: virtual void setDataProxy(QAbstractDataProxy *proxy); virtual void connectControllerAndProxy(Abstract3DController *newController); + virtual void createItemLabel(); void setSelectedPoint(const QPoint &position); void setFlatShadingEnabled(bool enabled); diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index 7f905243..8c94a9a4 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -783,6 +783,8 @@ Q3DScene *Abstract3DController::scene() void Abstract3DController::markDataDirty() { m_isDataDirty = true; + + markSeriesItemLabelsDirty(); emitNeedRender(); } @@ -813,6 +815,8 @@ void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender) m_changeTracker.axisZTitleChanged = true; else qWarning() << __FUNCTION__ << "invoked for invalid axis"; + + markSeriesItemLabelsDirty(); emitNeedRender(); } @@ -831,6 +835,8 @@ void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender) m_changeTracker.axisZLabelsChanged = true; else qWarning() << __FUNCTION__ << "invoked for invalid axis"; + + markSeriesItemLabelsDirty(); emitNeedRender(); } @@ -992,6 +998,12 @@ void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender emitNeedRender(); } +void Abstract3DController::markSeriesItemLabelsDirty() +{ + for (int i = 0; i < m_seriesList.size(); i++) + m_seriesList.at(i)->d_ptr->markItemLabelDirty(); +} + void Abstract3DController::setAxisHelper(QAbstract3DAxis::AxisOrientation orientation, QAbstract3DAxis *axis, QAbstract3DAxis **axisPtr) { diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index 13c334be..e433c97e 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -242,6 +242,8 @@ public: virtual void handleSeriesVisibilityChangedBySender(QObject *sender); virtual void handlePendingClick() = 0; + void markSeriesItemLabelsDirty(); + public slots: void handleAxisTitleChanged(const QString &title); void handleAxisLabelsChanged(); diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index f0aec0cc..6b3393ab 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -379,14 +379,8 @@ void Abstract3DRenderer::updateSeries(const QList &seriesLi visibleCount = 0; } foreach (QAbstract3DSeries *current, seriesList) { - if (current->isVisible()) { - // Item selection label may need update - if (current->d_ptr->m_changeTracker.nameChanged - || current->d_ptr->m_changeTracker.itemLabelFormatChanged) { - m_selectionLabelDirty = true; - } + if (current->isVisible()) m_visibleSeriesList[visibleCount++].populate(current, this); - } } } diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 0b2a4834..ec170129 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -106,6 +106,7 @@ void Bars3DController::handleArrayReset() if (series->isVisible()) { adjustAxisRanges(); m_isDataDirty = true; + series->d_ptr->markItemLabelDirty(); } // Clear selection unless still valid setSelectedBar(m_selectedBar, m_selectedBarSeries, false); @@ -132,6 +133,7 @@ void Bars3DController::handleRowsChanged(int startIndex, int count) if (series->isVisible()) { adjustAxisRanges(); m_isDataDirty = true; + series->d_ptr->markItemLabelDirty(); } emitNeedRender(); } @@ -193,6 +195,7 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) if (series->isVisible()) { adjustAxisRanges(); m_isDataDirty = true; + series->d_ptr->markItemLabelDirty(); } emitNeedRender(); } diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 15aa526f..127cfb0e 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -260,6 +260,26 @@ void Bars3DRenderer::updateData() updateSelectedBar(m_selectedBarPos, m_selectedBarSeries); } +void Bars3DRenderer::updateSeries(const QList &seriesList, + bool updateVisibility) +{ + Abstract3DRenderer::updateSeries(seriesList, updateVisibility); + + bool noSelection = true; + int seriesCount = m_visibleSeriesList.size(); + for (int i = 0; i < seriesCount; i++) { + QBar3DSeries *barSeries = static_cast(m_visibleSeriesList.at(i).series()); + if (noSelection + && barSeries->selectedBar() != QBar3DSeries::invalidSelectionPosition() + && selectionLabel() != m_visibleSeriesList.at(i).itemLabel()) { + m_selectionLabelDirty = true; + noSelection = false; + } + } + if (noSelection && !selectionLabel().isEmpty()) + m_selectionLabelDirty = true; +} + void Bars3DRenderer::updateScene(Q3DScene *scene) { if (m_hasNegativeValues) @@ -1002,7 +1022,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } glCullFace(GL_BACK); drawLabels(true, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor, - columnScaleFactor, false, selectedBar); + columnScaleFactor); glEnable(GL_DITHER); // Read color under cursor @@ -1643,7 +1663,41 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } drawLabels(false, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor, - columnScaleFactor, barSelectionFound, selectedBar); + columnScaleFactor); + + // Handle selected bar label generation + if (barSelectionFound) { + // Print value of selected bar + glDisable(GL_DEPTH_TEST); + // Draw the selection label + LabelItem &labelItem = selectionLabelItem(); + if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId() + || m_selectionLabelDirty) { + QString labelText = selectionLabel(); + if (labelText.isNull() || m_selectionLabelDirty) { + labelText = m_visibleSeriesList[m_visualSelectedBarSeriesIndex].itemLabel(); + setSelectionLabel(labelText); + m_selectionLabelDirty = false; + } + m_drawer->generateLabelItem(labelItem, labelText); + m_selectedBar = selectedBar; + } + + m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix, + zeroVector, zeroVector, selectedBar->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, activeCamera, true, false); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + + glEnable(GL_DEPTH_TEST); + } else { + m_selectedBar = 0; + } + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); // Release shader glUseProgram(0); @@ -1652,8 +1706,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix, - GLfloat rowScaleFactor, GLfloat columnScaleFactor, - bool barSelectionFound, BarRenderItem *selectedBar) { + GLfloat rowScaleFactor, GLfloat columnScaleFactor) { ShaderHelper *shader = 0; GLfloat alphaForValueSelection = labelValueAlpha / 255.0f; GLfloat alphaForRowSelection = labelRowAlpha / 255.0f; @@ -1830,81 +1883,6 @@ void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamer } glDisable(GL_POLYGON_OFFSET_FILL); - - // Handle selected bar label generation - if (barSelectionFound) { - // Print value of selected bar - glDisable(GL_DEPTH_TEST); - // Draw the selection label - LabelItem &labelItem = selectionLabelItem(); - if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId() - || m_selectionLabelDirty) { - QString labelText = selectionLabel(); - if (labelText.isNull() || m_selectionLabelDirty) { - static const QString rowIndexTag(QStringLiteral("@rowIdx")); - static const QString rowLabelTag(QStringLiteral("@rowLabel")); - static const QString rowTitleTag(QStringLiteral("@rowTitle")); - static const QString colIndexTag(QStringLiteral("@colIdx")); - static const QString colLabelTag(QStringLiteral("@colLabel")); - static const QString colTitleTag(QStringLiteral("@colTitle")); - static const QString valueTitleTag(QStringLiteral("@valueTitle")); - static const QString valueLabelTag(QStringLiteral("@valueLabel")); - static const QString seriesNameTag(QStringLiteral("@seriesName")); - - // Custom format expects printf format specifier. There is no tag for it. - labelText = m_axisCacheY.formatter()->stringForValue( - qreal(selectedBar->value()), - m_visibleSeriesList[m_visualSelectedBarSeriesIndex].itemLabelFormat()); - - int selBarPosRow = selectedBar->position().x(); - int selBarPosCol = selectedBar->position().y(); - labelText.replace(rowIndexTag, QString::number(selBarPosRow)); - if (m_axisCacheZ.labels().size() > selBarPosRow) - labelText.replace(rowLabelTag, m_axisCacheZ.labels().at(selBarPosRow)); - else - labelText.replace(rowLabelTag, QString()); - labelText.replace(rowTitleTag, m_axisCacheZ.title()); - labelText.replace(colIndexTag, QString::number(selBarPosCol)); - if (m_axisCacheX.labels().size() > selBarPosCol) - labelText.replace(colLabelTag, m_axisCacheX.labels().at(selBarPosCol)); - else - labelText.replace(colLabelTag, QString()); - labelText.replace(colTitleTag, m_axisCacheX.title()); - labelText.replace(valueTitleTag, m_axisCacheY.title()); - - if (labelText.contains(valueLabelTag)) { - QString valueLabelText = m_axisCacheY.formatter()->stringForValue( - qreal(selectedBar->value()), m_axisCacheY.labelFormat()); - labelText.replace(valueLabelTag, valueLabelText); - } - - labelText.replace(seriesNameTag, - m_visibleSeriesList[m_visualSelectedBarSeriesIndex].name()); - - setSelectionLabel(labelText); - m_selectionLabelDirty = false; - } - m_drawer->generateLabelItem(labelItem, labelText); - m_selectedBar = selectedBar; - } - - m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix, - zeroVector, zeroVector, selectedBar->height(), - m_cachedSelectionMode, shader, - m_labelObj, activeCamera, true, false); - - // Reset label update flag; they should have been updated when we get here - m_updateLabels = false; - - glEnable(GL_DEPTH_TEST); - } else { - m_selectedBar = 0; - } - - if (!drawSelection) { - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - } } void Bars3DRenderer::updateMultiSeriesScaling(bool uniform) diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 3e7e5178..fba5d830 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -114,6 +114,7 @@ public: ~Bars3DRenderer(); void updateData(); + void updateSeries(const QList &seriesList, bool updateVisibility); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); @@ -145,8 +146,7 @@ private: void drawScene(GLuint defaultFboHandle); void drawLabels(bool drawSelection, const Q3DCamera *activeCamera, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix, - GLfloat rowScaleFactor, GLfloat columnScaleFactor, - bool barSelectionFound, BarRenderItem *selectedBar); + GLfloat rowScaleFactor, GLfloat columnScaleFactor); void loadBackgroundMesh(); void loadGridLineMesh(); diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index bf283495..a28ee851 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -125,6 +125,7 @@ void Scatter3DController::handleArrayReset() m_isDataDirty = true; } setSelectedItem(m_selectedItem, m_selectedItemSeries); + series->d_ptr->markItemLabelDirty(); emitNeedRender(); } @@ -148,6 +149,7 @@ void Scatter3DController::handleItemsChanged(int startIndex, int count) if (series->isVisible()) { adjustValueAxisRange(); m_isDataDirty = true; + series->d_ptr->markItemLabelDirty(); } emitNeedRender(); } diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index a6633183..43c78137 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -171,18 +171,30 @@ void Scatter3DRenderer::updateSeries(const QList &seriesLis if (m_cachedItemSize.size() != seriesCount) m_cachedItemSize.resize(seriesCount); + bool noSelection = true; for (int series = 0; series < seriesCount; series++) { - itemSize = static_cast(m_visibleSeriesList.at(series).series())->itemSize(); + QScatter3DSeries *scatterSeries = + static_cast(m_visibleSeriesList.at(series).series()); + itemSize = scatterSeries->itemSize(); if (maxItemSize < itemSize) maxItemSize = itemSize; if (m_cachedItemSize.at(series) != itemSize) m_cachedItemSize[series] = itemSize; + if (noSelection + && scatterSeries->selectedItem() != QScatter3DSeries::invalidSelectionIndex() + && m_selectionLabel != m_visibleSeriesList.at(series).itemLabel()) { + m_selectionLabelDirty = true; + noSelection = false; + } } m_maxItemSize = maxItemSize; if (maxItemSize > defaultMaxSize) m_backgroundMargin = maxItemSize / itemScaler; else m_backgroundMargin = defaultMaxSize; + + if (noSelection && !selectionLabel().isEmpty()) + m_selectionLabelDirty = true; } void Scatter3DRenderer::updateData() @@ -1251,38 +1263,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) || !labelItem.textureId() || m_selectionLabelDirty) { QString labelText = selectionLabel(); if (labelText.isNull() || m_selectionLabelDirty) { - static const QString xTitleTag(QStringLiteral("@xTitle")); - static const QString yTitleTag(QStringLiteral("@yTitle")); - static const QString zTitleTag(QStringLiteral("@zTitle")); - static const QString xLabelTag(QStringLiteral("@xLabel")); - static const QString yLabelTag(QStringLiteral("@yLabel")); - static const QString zLabelTag(QStringLiteral("@zLabel")); - static const QString seriesNameTag(QStringLiteral("@seriesName")); - - labelText = m_visibleSeriesList[m_selectedItemSeriesIndex].itemLabelFormat(); - - labelText.replace(xTitleTag, m_axisCacheX.title()); - labelText.replace(yTitleTag, m_axisCacheY.title()); - labelText.replace(zTitleTag, m_axisCacheZ.title()); - - if (labelText.contains(xLabelTag)) { - QString valueLabelText = m_axisCacheX.formatter()->stringForValue( - qreal(selectedItem->position().x()), m_axisCacheX.labelFormat()); - labelText.replace(xLabelTag, valueLabelText); - } - if (labelText.contains(yLabelTag)) { - QString valueLabelText = m_axisCacheY.formatter()->stringForValue( - qreal(selectedItem->position().y()), m_axisCacheY.labelFormat()); - labelText.replace(yLabelTag, valueLabelText); - } - if (labelText.contains(zLabelTag)) { - QString valueLabelText = m_axisCacheZ.formatter()->stringForValue( - qreal(selectedItem->position().z()), m_axisCacheZ.labelFormat()); - labelText.replace(zLabelTag, valueLabelText); - } - labelText.replace(seriesNameTag, - m_visibleSeriesList[m_selectedItemSeriesIndex].name()); - + labelText = m_visibleSeriesList[m_selectedItemSeriesIndex].itemLabel(); setSelectionLabel(labelText); m_selectionLabelDirty = false; } diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp index 8cfd9b08..7e51df1e 100644 --- a/src/datavisualization/engine/seriesrendercache.cpp +++ b/src/datavisualization/engine/seriesrendercache.cpp @@ -55,11 +55,6 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * QAbstract3DSeriesChangeBitField &changeTracker = series->d_ptr->m_changeTracker; - if (seriesChanged || changeTracker.itemLabelFormatChanged) { - m_itemLabelFormat = series->itemLabelFormat(); - changeTracker.itemLabelFormatChanged = false; - } - if (seriesChanged || changeTracker.meshChanged || changeTracker.meshSmoothChanged || changeTracker.userDefinedMeshChanged) { m_mesh = series->mesh(); @@ -182,6 +177,18 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * m_name = series->name(); changeTracker.nameChanged = false; } + + if (seriesChanged || changeTracker.itemLabelChanged + || changeTracker.itemLabelVisibilityChanged) { + changeTracker.itemLabelChanged = false; + changeTracker.itemLabelVisibilityChanged = false; + // series->itemLabel() call resolves the item label and emits the changed signal + // if it is dirty, so we need to call it even if m_itemLabel is eventually set + // to an empty string. + m_itemLabel = series->itemLabel(); + if (!series->isItemLabelVisible()) + m_itemLabel = QString(); + } } void SeriesRenderCache::cleanup(TextureHelper *texHelper) diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h index 1ef67c88..a6ae03cf 100644 --- a/src/datavisualization/engine/seriesrendercache_p.h +++ b/src/datavisualization/engine/seriesrendercache_p.h @@ -51,7 +51,6 @@ public: // It is not guaranteed to be valid while rendering and should only be used as an identifier. inline QAbstract3DSeries *series() const { return m_series; } - inline const QString &itemLabelFormat() const { return m_itemLabelFormat; } inline const QAbstract3DSeries::Mesh &mesh() const { return m_mesh; } inline const QQuaternion &meshRotation() const { return m_meshRotation; } inline void setMeshRotation(const QQuaternion &rotation) { m_meshRotation = rotation; } @@ -66,10 +65,10 @@ public: inline const QVector3D &multiHighlightColor() const { return m_multiHighlightColor; } inline const GLuint &multiHighlightGradientTexture() const { return m_multiHighlightGradientTexture; } inline const QString &name() const { return m_name; } + inline const QString &itemLabel() const { return m_itemLabel; } protected: QAbstract3DSeries *m_series; - QString m_itemLabelFormat; ObjectHelper *m_object; QAbstract3DSeries::Mesh m_mesh; QQuaternion m_meshRotation; @@ -85,6 +84,7 @@ protected: GLuint m_multiHighlightGradientTexture; QString m_name; + QString m_itemLabel; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 42e408dd..2d64e87d 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -297,6 +297,7 @@ void Surface3DController::handleArrayReset() } // Clear selection unless still valid setSelectedPoint(m_selectedPoint, m_selectedSeries, false); + series->d_ptr->markItemLabelDirty(); emitNeedRender(); } @@ -321,6 +322,7 @@ void Surface3DController::handleRowsChanged(int startIndex, int count) QSurface3DSeries *series = sender->series(); int oldChangeCount = m_changedRows.size(); + int selectedRow = m_selectedPoint.x(); for (int i = 0; i < count; i++) { bool newItem = true; int candidate = startIndex + i; @@ -334,6 +336,8 @@ void Surface3DController::handleRowsChanged(int startIndex, int count) if (newItem) { ChangeRow newItem = {series, candidate}; m_changedRows.append(newItem); + if (series == m_selectedSeries && selectedRow == candidate) + series->d_ptr->markItemLabelDirty(); } } if (m_changedRows.size()) { @@ -364,6 +368,9 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex) m_changedItems.append(newItem); m_changeTracker.itemChanged = true; + if (series == m_selectedSeries && m_selectedPoint == candidate) + series->d_ptr->markItemLabelDirty(); + adjustValueAxisRange(); // Clear selection unless still valid setSelectedPoint(m_selectedPoint, m_selectedSeries, false); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index fc31cd40..a3ee0971 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -254,23 +254,25 @@ void Surface3DRenderer::updateSeries(const QList &seriesLis foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) cache->setValid(false); + bool noSelection = true; foreach (QAbstract3DSeries *series, seriesList) { - // Item selection label may need update - if (series->d_ptr->m_changeTracker.nameChanged - || series->d_ptr->m_changeTracker.itemLabelFormatChanged) { - m_selectionLabelDirty = true; - } - QSurface3DSeries *surfaceSeries = static_cast(series); SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries); if (!cache) { cache = new SurfaceSeriesRenderCache(this); m_renderCacheList[surfaceSeries] = cache; - m_selectionTexturesDirty = true; } cache->setValid(true); cache->populate(surfaceSeries, this); + + if (noSelection + && surfaceSeries->selectedPoint() != QSurface3DSeries::invalidSelectionPosition() + && selectionLabel() != cache->itemLabel()) { + m_selectionLabelDirty = true; + noSelection = false; + } + if (cache->isFlatStatusDirty() && cache->sampleSpace().width()) { checkFlatSupport(cache); updateObjects(cache, true); @@ -278,6 +280,9 @@ void Surface3DRenderer::updateSeries(const QList &seriesLis } } + if (noSelection && !selectionLabel().isEmpty()) + m_selectionLabelDirty = true; + // Remove non-valid objects from the cache list foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { if (!cache->isValid()) { @@ -2200,8 +2205,10 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co } QString selectionLabel; - if (label) - selectionLabel = createSelectionLabel(cache, column, row); + if (label) { + m_selectionLabelDirty = false; + selectionLabel = cache->itemLabel(); + } if (m_cachedIsSlicingActivated) { QVector3D subPosFront; @@ -2282,46 +2289,6 @@ QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id) return QPoint(row, column); } -QString Surface3DRenderer::createSelectionLabel(SurfaceSeriesRenderCache *cache, - int column, int row) -{ - QSurfaceDataArray &dataArray = cache->dataArray(); - QString labelText = cache->itemLabelFormat(); - static const QString xTitleTag(QStringLiteral("@xTitle")); - static const QString yTitleTag(QStringLiteral("@yTitle")); - static const QString zTitleTag(QStringLiteral("@zTitle")); - static const QString xLabelTag(QStringLiteral("@xLabel")); - static const QString yLabelTag(QStringLiteral("@yLabel")); - static const QString zLabelTag(QStringLiteral("@zLabel")); - static const QString seriesNameTag(QStringLiteral("@seriesName")); - - labelText.replace(xTitleTag, m_axisCacheX.title()); - labelText.replace(yTitleTag, m_axisCacheY.title()); - labelText.replace(zTitleTag, m_axisCacheZ.title()); - - if (labelText.contains(xLabelTag)) { - QString valueLabelText = m_axisCacheX.formatter()->stringForValue( - qreal(dataArray.at(row)->at(column).x()), m_axisCacheX.labelFormat()); - labelText.replace(xLabelTag, valueLabelText); - } - if (labelText.contains(yLabelTag)) { - QString valueLabelText = m_axisCacheY.formatter()->stringForValue( - qreal(dataArray.at(row)->at(column).y()), m_axisCacheY.labelFormat()); - labelText.replace(yLabelTag, valueLabelText); - } - if (labelText.contains(zLabelTag)) { - QString valueLabelText = m_axisCacheZ.formatter()->stringForValue( - qreal(dataArray.at(row)->at(column).z()), m_axisCacheZ.labelFormat()); - labelText.replace(zLabelTag, valueLabelText); - } - - labelText.replace(seriesNameTag, cache->name()); - - m_selectionLabelDirty = false; - - return labelText; -} - void Surface3DRenderer::updateShadowQuality(QAbstract3DGraph::ShadowQuality quality) { m_cachedShadowQuality = quality; diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 7a3b279f..39e96f55 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -160,7 +160,6 @@ private: void surfacePointSelected(const QPoint &point); void updateSelectionPoint(SurfaceSeriesRenderCache *cache, const QPoint &point, bool label); QPoint selectionIdToSurfacePoint(uint id); - QString createSelectionLabel(SurfaceSeriesRenderCache *cache, int column, int row); #if !defined(QT_OPENGL_ES_2) void loadGridLineMesh(); void updateDepthBuffer(); diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp index e0e427f3..a9b932b4 100644 --- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp @@ -24,6 +24,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION void QtDataVisualizationQml2Plugin::registerTypes(const char *uri) { + // @uri QtDataVisualization + // QtDataVisualization 1.0 qmlRegisterUncreatableType(uri, 1, 0, "AbstractItemModel", @@ -86,6 +88,8 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri) // New revisions qmlRegisterType(uri, 1, 1, "ValueAxis3D"); + qmlRegisterUncreatableType(uri, 1, 1, "Abstract3DSeries", + QLatin1String("Trying to create uncreatable: Abstract3DSeries.")); // New types qmlRegisterType(uri, 1, 1, "ValueAxis3DFormatter"); diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index f4cd02f7..112e8d4d 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -55,7 +55,7 @@ int main(int argc, char **argv) QSize screenSize = widgetchart->screen()->size(); QWidget *container = QWidget::createWindowContainer(widgetchart); - container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2)); + container->setMinimumSize(QSize(screenSize.width() / 3, screenSize.height() / 3)); container->setMaximumSize(screenSize); container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); container->setFocusPolicy(Qt::StrongFocus); -- cgit v1.2.3