diff options
Diffstat (limited to 'src/datavisualization')
52 files changed, 2011 insertions, 721 deletions
diff --git a/src/datavisualization/axis/q3dcategoryaxis.cpp b/src/datavisualization/axis/q3dcategoryaxis.cpp index 63026379..6d2dec3a 100644 --- a/src/datavisualization/axis/q3dcategoryaxis.cpp +++ b/src/datavisualization/axis/q3dcategoryaxis.cpp @@ -75,7 +75,10 @@ Q3DCategoryAxis::~Q3DCategoryAxis() * * Defines labels for axis applied to categories. If there are fewer labels than categories, the * remaining ones do not have a label. If category labels are not defined explicitly, labels are - * generated from the data row and column labels. + * generated from the data row (or column) labels. + * + * \note If the graph has multiple visible series and category labels are not defined explicitly, + * changing the rows (or columns) on any of the attached series will regenerate the labels. * * \note CategoryLabels actually reads/writes the Q3DAbstractAxis::labels property, * which is read only there. Since subclass cannot have property with same name, diff --git a/src/datavisualization/data/data.pri b/src/datavisualization/data/data.pri index 770d2bd1..66ad0e3b 100644 --- a/src/datavisualization/data/data.pri +++ b/src/datavisualization/data/data.pri @@ -36,7 +36,15 @@ HEADERS += \ $$PWD/qitemmodelsurfacedataproxy_p.h \ $$PWD/surfaceitemmodelhandler_p.h \ $$PWD/qsurfacedataitem.h \ - $$PWD/qsurfacedataitem_p.h + $$PWD/qsurfacedataitem_p.h \ + $$PWD/qabstract3dseries.h \ + $$PWD/qabstract3dseries_p.h \ + $$PWD/qbar3dseries.h \ + $$PWD/qbar3dseries_p.h \ + $$PWD/qscatter3dseries.h \ + $$PWD/qscatter3dseries_p.h \ + $$PWD/qsurface3dseries.h \ + $$PWD/qsurface3dseries_p.h SOURCES += \ $$PWD/labelitem.cpp \ @@ -61,4 +69,8 @@ SOURCES += \ $$PWD/qitemmodelsurfacedatamapping.cpp \ $$PWD/qitemmodelsurfacedataproxy.cpp \ $$PWD/surfaceitemmodelhandler.cpp \ - $$PWD/qsurfacedataitem.cpp + $$PWD/qsurfacedataitem.cpp \ + $$PWD/qabstract3dseries.cpp \ + $$PWD/qbar3dseries.cpp \ + $$PWD/qscatter3dseries.cpp \ + $$PWD/qsurface3dseries.cpp diff --git a/src/datavisualization/data/qabstract3dseries.cpp b/src/datavisualization/data/qabstract3dseries.cpp new file mode 100644 index 00000000..52d3fda1 --- /dev/null +++ b/src/datavisualization/data/qabstract3dseries.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qabstract3dseries.h" +#include "qabstract3dseries_p.h" +#include "qabstractdataproxy_p.h" +#include "abstract3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QAbstract3DSeries + * \inmodule QtDataVisualization + * \brief Base class for all QtDataVisualization data proxies. + * \since Qt Data Visualization 1.0 + * + * You use the visualization type specific inherited classes instead of the base class. + * \sa QBar3DSeries, QScatter3DSeries, QSurface3DSeries, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Abstract3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QAbstract3DSeries + * \brief Base type for all QtDataVisualization data proxies. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + * \sa Bar3DSeries, Scatter3DSeries, Surface3DSeries, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty Abstract3DSeries.SeriesType Abstract3DSeries::type + * The type of the series. + */ + +/*! + * \qmlproperty string Abstract3DSeries::itemLabelFormat + * + * Label format for data items in this series. This format is used for single item labels, + * for example, when an item is selected. How the format is interpreted depends on series type. See + * each series class documentation for more information. + */ + +/*! + * \qmlproperty bool Abstract3DSeries::visible + * Sets the visibility of the series. If false, the series is not rendered. + */ + +/*! + * \enum QAbstract3DSeries::SeriesType + * + * Type of the series. + * + * \value SeriesTypeNone + * No series type. + * \value SeriesTypeBar + * Series type for Q3DBars. + * \value SeriesTypeScatter + * Series type for Q3DScatter. + * \value SeriesTypeSurface + * Series type for Q3DSurface. + */ + +/*! + * \internal + */ +QAbstract3DSeries::QAbstract3DSeries(QAbstract3DSeriesPrivate *d, QObject *parent) : + QObject(parent), + d_ptr(d) +{ +} + +/*! + * Destroys QAbstract3DSeries. + */ +QAbstract3DSeries::~QAbstract3DSeries() +{ +} + +/*! + * \property QAbstract3DSeries::type + * + * The type of the series. + */ +QAbstract3DSeries::SeriesType QAbstract3DSeries::type() const +{ + return d_ptr->m_type; +} + +/*! + * \property QAbstract3DSeries::itemLabelFormat + * + * Sets label \a format for data items in this series. This format is used for single item labels, + * for example, when an item is selected. How the format is interpreted depends on series type. See + * each series class documentation for more information. + * + * \sa QBar3DSeries, Q3DScatterSeries, Q3DSurfaceSeries + */ +void QAbstract3DSeries::setItemLabelFormat(const QString &format) +{ + if (format != itemLabelFormat()) { + d_ptr->setItemLabelFormat(format); + emit itemLabelFormatChanged(format); + } +} + +QString QAbstract3DSeries::itemLabelFormat() const +{ + return d_ptr->m_itemLabelFormat; +} + +/*! + * \property QAbstract3DSeries::visible + * + * Sets the visibility of the series. If \a visible is false, the series is not rendered. + * Defaults to true. + */ +void QAbstract3DSeries::setVisible(bool visible) +{ + d_ptr->m_visible = visible; + emit visibilityChanged(visible); +} + +bool QAbstract3DSeries::isVisible() const +{ + return d_ptr->m_visible; +} + +// QAbstract3DSeriesPrivate + +QAbstract3DSeriesPrivate::QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type) + : QObject(0), + q_ptr(q), + m_type(type), + m_dataProxy(0), + m_visible(true), + m_controller(0) +{ +} + +QAbstract3DSeriesPrivate::~QAbstract3DSeriesPrivate() +{ +} + +void QAbstract3DSeriesPrivate::setItemLabelFormat(const QString &format) +{ + m_itemLabelFormat = format; +} + +QAbstractDataProxy *QAbstract3DSeriesPrivate::dataProxy() const +{ + return m_dataProxy; +} + +void QAbstract3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy && proxy != m_dataProxy && !proxy->d_ptr->series()); + + delete m_dataProxy; + m_dataProxy = proxy; + + proxy->d_ptr->setSeries(q_ptr); // also sets parent + + if (m_controller) + connectControllerAndProxy(m_controller); +} + +void QAbstract3DSeriesPrivate::setController(Abstract3DController *controller) +{ + connectControllerAndProxy(controller); + m_controller = controller; + q_ptr->setParent(controller); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h new file mode 100644 index 00000000..3f20a161 --- /dev/null +++ b/src/datavisualization/data/qabstract3dseries.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QABSTRACT3DSERIES_H +#define QABSTRACT3DSERIES_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QObject> +#include <QScopedPointer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstract3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QAbstract3DSeries : public QObject +{ + Q_OBJECT + Q_ENUMS(SeriesType) + Q_PROPERTY(SeriesType type READ type) + Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged) + +public: + enum SeriesType { + SeriesTypeNone = 0, + SeriesTypeBar = 1, + SeriesTypeScatter = 2, + SeriesTypeSurface = 4 + }; + +protected: + explicit QAbstract3DSeries(QAbstract3DSeriesPrivate *d, QObject *parent = 0); + +public: + virtual ~QAbstract3DSeries(); + + SeriesType type() const; + + void setItemLabelFormat(const QString &format); + QString itemLabelFormat() const; + + void setVisible(bool visible); + bool isVisible() const; + +signals: + void itemLabelFormatChanged(QString format); + void visibilityChanged(bool visible); + +protected: + QScopedPointer<QAbstract3DSeriesPrivate> d_ptr; + +// QDataVis::ColorStyle m_colorStyle; +// QColor m_objectColor; +// QLinearGradient m_objectGradient; +// QColor m_singleHighlightColor; +// QLinearGradient m_singleHighlightGradient; +// QColor m_multiHighlightColor; +// QLinearGradient m_multiHighlightGradient; + +private: + Q_DISABLE_COPY(QAbstract3DSeries) + + friend class Abstract3DController; + friend class Bars3DController; + friend class Surface3DController; + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qabstract3dseries_p.h b/src/datavisualization/data/qabstract3dseries_p.h new file mode 100644 index 00000000..478fe6bb --- /dev/null +++ b/src/datavisualization/data/qabstract3dseries_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "datavisualizationglobal_p.h" +#include "qabstract3dseries.h" +#include <QString> + +#ifndef QABSTRACT3DSERIES_P_H +#define QABSTRACT3DSERIES_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataProxy; +class Abstract3DController; + +class QAbstract3DSeriesPrivate : public QObject +{ + Q_OBJECT +public: + QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type); + virtual ~QAbstract3DSeriesPrivate(); + + void setItemLabelFormat(const QString &format); + + QAbstractDataProxy *dataProxy() const; + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void setController(Abstract3DController *controller); + virtual void connectControllerAndProxy(Abstract3DController *newController) = 0; + +protected: + QAbstract3DSeries *q_ptr; + QAbstract3DSeries::SeriesType m_type; + QString m_itemLabelFormat; + QAbstractDataProxy *m_dataProxy; + bool m_visible; + Abstract3DController *m_controller; + +private: + friend class QAbstract3DSeries; + friend class Abstract3DController; + friend class Bars3DController; + friend class Surface3DController; + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QAbstract3DSeries_P_H diff --git a/src/datavisualization/data/qabstractdataproxy.cpp b/src/datavisualization/data/qabstractdataproxy.cpp index b44f365e..fa0934c3 100644 --- a/src/datavisualization/data/qabstractdataproxy.cpp +++ b/src/datavisualization/data/qabstractdataproxy.cpp @@ -18,6 +18,7 @@ #include "qabstractdataproxy.h" #include "qabstractdataproxy_p.h" +#include "qabstract3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -49,14 +50,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! - * \qmlproperty string AbstractDataProxy::itemLabelFormat - * - * Label format for data items in this proxy. This format is used for single item labels, - * for example, when an item is selected. How the format is interpreted depends on proxy type. See - * each proxy class documentation for more information. - */ - -/*! * \enum QAbstractDataProxy::DataType * * Data type of the proxy. @@ -97,44 +90,13 @@ QAbstractDataProxy::DataType QAbstractDataProxy::type() const return d_ptr->m_type; } -/*! - * \property QAbstractDataProxy::itemLabelFormat - * - * Sets label \a format for data items in this proxy. This format is used for single item labels, - * for example, when an item is selected. How the format is interpreted depends on proxy type. See - * each proxy class documentation for more information. - * - * \sa QBarDataProxy, QScatterDataProxy, QSurfaceDataProxy - */ -void QAbstractDataProxy::setItemLabelFormat(const QString &format) -{ - if (format != itemLabelFormat()) { - d_ptr->setItemLabelFormat(format); - emit itemLabelFormatChanged(format); - } -} - -/*! - * \return label format for data items in this proxy. - */ -QString QAbstractDataProxy::itemLabelFormat() const -{ - return d_ptr->m_itemLabelFormat; -} - -/*! - * \fn void QAbstractDataProxy::itemLabelFormatChanged(QString format) - * - * Emitted when label format changes. - */ - // QAbstractDataProxyPrivate QAbstractDataProxyPrivate::QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type) : QObject(0), q_ptr(q), m_type(type), - m_isDefaultProxy(false) + m_series(0) { } @@ -142,9 +104,10 @@ QAbstractDataProxyPrivate::~QAbstractDataProxyPrivate() { } -void QAbstractDataProxyPrivate::setItemLabelFormat(const QString &format) +void QAbstractDataProxyPrivate::setSeries(QAbstract3DSeries *series) { - m_itemLabelFormat = format; + setParent(series); + m_series = series; } QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstractdataproxy.h b/src/datavisualization/data/qabstractdataproxy.h index d7793824..b493052f 100644 --- a/src/datavisualization/data/qabstractdataproxy.h +++ b/src/datavisualization/data/qabstractdataproxy.h @@ -32,7 +32,6 @@ class QT_DATAVISUALIZATION_EXPORT QAbstractDataProxy : public QObject Q_OBJECT Q_ENUMS(DataType) Q_PROPERTY(DataType type READ type) - Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged) public: enum DataType { @@ -50,22 +49,17 @@ public: DataType type() const; - void setItemLabelFormat(const QString &format); - QString itemLabelFormat() const; - -signals: - void itemLabelFormatChanged(QString format); - protected: QScopedPointer<QAbstractDataProxyPrivate> d_ptr; private: Q_DISABLE_COPY(QAbstractDataProxy) - friend class Abstract3DController; - friend class Bars3DController; - friend class Scatter3DController; - friend class Surface3DController; + friend class QAbstract3DSeriesPrivate; +// friend class Abstract3DController; +// friend class Bars3DController; +// friend class Scatter3DController; +// friend class Surface3DController; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstractdataproxy_p.h b/src/datavisualization/data/qabstractdataproxy_p.h index 4aa1b678..90504ccb 100644 --- a/src/datavisualization/data/qabstractdataproxy_p.h +++ b/src/datavisualization/data/qabstractdataproxy_p.h @@ -35,6 +35,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE +class QAbstract3DSeries; + class QAbstractDataProxyPrivate : public QObject { Q_OBJECT @@ -42,16 +44,13 @@ public: QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type); virtual ~QAbstractDataProxyPrivate(); - void setItemLabelFormat(const QString &format); - - inline bool isDefaultProxy() { return m_isDefaultProxy; } - inline void setDefaultProxy(bool isDefault) { m_isDefaultProxy = isDefault; } + inline QAbstract3DSeries *series() { return m_series; } + virtual void setSeries(QAbstract3DSeries *series); protected: QAbstractDataProxy *q_ptr; QAbstractDataProxy::DataType m_type; - QString m_itemLabelFormat; - bool m_isDefaultProxy; + QAbstract3DSeries *m_series; private: friend class QAbstractDataProxy; diff --git a/src/datavisualization/data/qbar3dseries.cpp b/src/datavisualization/data/qbar3dseries.cpp new file mode 100644 index 00000000..c04f8ca2 --- /dev/null +++ b/src/datavisualization/data/qbar3dseries.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qbar3dseries_p.h" +#include "bars3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QBar3DSeries + * \inmodule QtDataVisualization + * \brief Base series class for Q3DBars. + * \since Qt Data Visualization 1.0 + * + * QBar3DSeries manages the series specific visual elements, as well as series data + * (via data proxy). + * + * If no data proxy is set explicitly for the series, QBar3DSeries creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it are destroyed. + * + * QBar3DSeries optionally keeps track of row and column labels, which Q3DCategoryAxis can utilize + * to show axis labels. The row and column labels are stored in separate array from the data and + * row manipulation methods provide an alternate versions that don't affect the row labels. + * This enables the option of having row labels that relate to the position of the data in the + * array rather than the data itself. + * + * QBar3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat(): + * \table + * \row + * \li @rowTitle \li Title from row axis + * \row + * \li @colTitle \li Title from column axis + * \row + * \li @valueTitle \li Title from value axis + * \row + * \li @rowIdx \li Visible row index + * \row + * \li @colIdx \li Visible Column index + * \row + * \li @rowLabel \li Label from row axis + * \row + * \li @colLabel \li Label from column axis + * \row + * \li @valueLabel \li Item value formatted using the same format the value axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li %<format spec> \li Item value in specified format. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Bar3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QBar3DSeries + * \inherits Abstract3DSeries + * \brief Base series type for Bars3D. + * + * This type manages the series specific visual elements, as well as series data + * (via data proxy). + * + * For more complete description, see QBar3DSeries. + * + * \sa {Qt Data Visualization Data Handling} + */ + + +/*! + * Constructs QBar3DSeries with the given \a parent. + */ +QBar3DSeries::QBar3DSeries(QObject *parent) : + QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent) +{ + // Default proxy + dptr()->setDataProxy(new QBarDataProxy); +} + +QBar3DSeries::QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent) : + QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent) +{ + dptr()->setDataProxy(dataProxy); +} + +/*! + * \internal + */ +QBar3DSeries::QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent) : + QAbstract3DSeries(d, parent) +{ +} + +/*! + * Destroys QBar3DSeries. + */ +QBar3DSeries::~QBar3DSeries() +{ +} + +/*! + * \property QBar3DSeries::dataProxy + * + * This property holds the active data \a proxy. The series assumes ownership of any proxy set to + * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or + * set to another series. + */ +void QBar3DSeries::setDataProxy(QBarDataProxy *proxy) +{ + d_ptr->setDataProxy(proxy); +} + +QBarDataProxy *QBar3DSeries::dataProxy() const +{ + return static_cast<QBarDataProxy *>(d_ptr->dataProxy()); +} + +/*! + * \internal + */ +QBar3DSeriesPrivate *QBar3DSeries::dptr() +{ + return static_cast<QBar3DSeriesPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QBar3DSeriesPrivate *QBar3DSeries::dptrc() const +{ + return static_cast<const QBar3DSeriesPrivate *>(d_ptr.data()); +} + +// QBar3DSeriesPrivate + +QBar3DSeriesPrivate::QBar3DSeriesPrivate(QBar3DSeries *q) + : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeBar) +{ + m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); +} + +QBar3DSeriesPrivate::~QBar3DSeriesPrivate() +{ +} + +QBar3DSeries *QBar3DSeriesPrivate::qptr() +{ + return static_cast<QBar3DSeries *>(q_ptr); +} + +void QBar3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar); + + QAbstract3DSeriesPrivate::setDataProxy(proxy); + + emit qptr()->dataProxyChanged(static_cast<QBarDataProxy *>(proxy)); +} + +void QBar3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController) +{ + QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_dataProxy); + + if (m_controller && barDataProxy) { + //Disconnect old controller/old proxy + QObject::disconnect(barDataProxy, 0, m_controller, 0); + QObject::disconnect(q_ptr, 0, m_controller, 0); + } + + if (newController && barDataProxy) { + Bars3DController *controller = static_cast<Bars3DController *>(newController); + + QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, controller, + &Bars3DController::handleArrayReset); + QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, controller, + &Bars3DController::handleRowsAdded); + QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, controller, + &Bars3DController::handleRowsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, controller, + &Bars3DController::handleRowsRemoved); + QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, controller, + &Bars3DController::handleRowsInserted); + QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, controller, + &Bars3DController::handleItemChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, controller, + &Bars3DController::handleDataRowLabelsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, controller, + &Bars3DController::handleDataColumnLabelsChanged); + + QObject::connect(q_ptr, &QAbstract3DSeries::visibilityChanged, controller, + &Abstract3DController::handleSeriesVisibilityChanged); + + // Always clear selection on proxy change + // TODO: setSelectedBar(noSelectionPoint()); + + newController->handleSeriesVisibilityChanged(m_visible); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qbar3dseries.h b/src/datavisualization/data/qbar3dseries.h new file mode 100644 index 00000000..ebb37838 --- /dev/null +++ b/src/datavisualization/data/qbar3dseries.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QBAR3DSERIES_H +#define QBAR3DSERIES_H + +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qbardataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBar3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QBar3DSeries : public QAbstract3DSeries +{ + Q_OBJECT + Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged) + +public: + explicit QBar3DSeries(QObject *parent = 0); + explicit QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent = 0); + virtual ~QBar3DSeries(); + + void setDataProxy(QBarDataProxy *proxy); + QBarDataProxy *dataProxy() const; + +signals: + void dataProxyChanged(QBarDataProxy *proxy); + +protected: + explicit QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent = 0); + QBar3DSeriesPrivate *dptr(); + const QBar3DSeriesPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QBar3DSeries) + + friend class Bars3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qbar3dseries_p.h b/src/datavisualization/data/qbar3dseries_p.h new file mode 100644 index 00000000..3ed95a69 --- /dev/null +++ b/src/datavisualization/data/qbar3dseries_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QBAR3DSERIES_P_H +#define QBAR3DSERIES_P_H + +#include "qbar3dseries.h" +#include "qabstract3dseries_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBar3DSeriesPrivate : public QAbstract3DSeriesPrivate +{ + Q_OBJECT +public: + QBar3DSeriesPrivate(QBar3DSeries *q); + virtual ~QBar3DSeriesPrivate(); + + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void connectControllerAndProxy(Abstract3DController *newController); +private: + QBar3DSeries *qptr(); + +private: + friend class QBar3DSeries; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qbardataproxy.cpp b/src/datavisualization/data/qbardataproxy.cpp index 13517b4b..26c3a36a 100644 --- a/src/datavisualization/data/qbardataproxy.cpp +++ b/src/datavisualization/data/qbardataproxy.cpp @@ -18,6 +18,7 @@ #include "qbardataproxy.h" #include "qbardataproxy_p.h" +#include "qbar3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -110,6 +111,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! + * \qmlproperty Bar3DSeries BarDataProxy::series + * + * The series this proxy is attached to. + */ + +/*! * Constructs QBarDataProxy with the given \a parent. */ QBarDataProxy::QBarDataProxy(QObject *parent) : @@ -133,6 +140,16 @@ QBarDataProxy::~QBarDataProxy() } /*! + * \property QBarDataProxy::series + * + * The series this proxy is attached to. + */ +QBar3DSeries *QBarDataProxy::series() +{ + return static_cast<QBar3DSeries *>(d_ptr->series()); +} + +/*! * Clears the existing array and row and column labels. */ void QBarDataProxy::resetArray() @@ -482,7 +499,6 @@ QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q) : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar), m_dataArray(new QBarDataArray) { - m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); } QBarDataProxyPrivate::~QBarDataProxyPrivate() @@ -704,4 +720,11 @@ QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endR return limits; } +void QBarDataProxyPrivate::setSeries(QAbstract3DSeries *series) +{ + QAbstractDataProxyPrivate::setSeries(series); + QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series); + emit qptr()->seriesChanged(barSeries); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h index 758700df..e97e6a85 100644 --- a/src/datavisualization/data/qbardataproxy.h +++ b/src/datavisualization/data/qbardataproxy.h @@ -30,6 +30,7 @@ typedef QVector<QBarDataItem> QBarDataRow; typedef QList<QBarDataRow *> QBarDataArray; class QBarDataProxyPrivate; +class QBar3DSeries; class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy { @@ -38,6 +39,7 @@ class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy Q_PROPERTY(int rowCount READ rowCount) Q_PROPERTY(QStringList rowLabels READ rowLabels WRITE setRowLabels NOTIFY rowLabelsChanged) Q_PROPERTY(QStringList columnLabels READ columnLabels WRITE setColumnLabels NOTIFY columnLabelsChanged) + Q_PROPERTY(QBar3DSeries *series READ series NOTIFY seriesChanged) public: explicit QBarDataProxy(QObject *parent = 0); virtual ~QBarDataProxy(); @@ -51,6 +53,7 @@ public: * individual bar requires allocating additional data object for the bar. */ + QBar3DSeries *series(); int rowCount() const; QStringList rowLabels() const; @@ -113,6 +116,7 @@ signals: void rowLabelsChanged(); void columnLabelsChanged(); + void seriesChanged(QBar3DSeries *series); protected: explicit QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent = 0); diff --git a/src/datavisualization/data/qbardataproxy_p.h b/src/datavisualization/data/qbardataproxy_p.h index 4d51bd5b..84726a02 100644 --- a/src/datavisualization/data/qbardataproxy_p.h +++ b/src/datavisualization/data/qbardataproxy_p.h @@ -56,6 +56,8 @@ public: QPair<GLfloat, GLfloat> limitValues(int startRow, int startColumn, int rowCount, int columnCount) const; + virtual void setSeries(QAbstract3DSeries *series); + private: QBarDataProxy *qptr(); void clearRow(int rowIndex); diff --git a/src/datavisualization/data/qscatter3dseries.cpp b/src/datavisualization/data/qscatter3dseries.cpp new file mode 100644 index 00000000..2fe61cff --- /dev/null +++ b/src/datavisualization/data/qscatter3dseries.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qscatter3dseries_p.h" +#include "scatter3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QScatter3DSeries + * \inmodule QtDataVisualization + * \brief Base series class for Q3DScatter. + * \since Qt Data Visualization 1.0 + * + * QScatter3DSeries manages the series specific visual elements, as well as series data + * (via data proxy). + * + * If no data proxy is set explicitly for the series, QScatter3DSeries creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it are destroyed. + * + * QScatter3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat(): + * \table + * \row + * \li @xTitle \li Title from X axis + * \row + * \li @yTitle \li Title from Y axis + * \row + * \li @zTitle \li Title from Z axis + * \row + * \li @xLabel \li Item value formatted using the same format the X axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @yLabel \li Item value formatted using the same format the Y axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @zLabel \li Item value formatted using the same format the Z axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Scatter3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QScatter3DSeries + * \inherits Abstract3DSeries + * \brief Base series type for Scatter3D. + * + * This type manages the series specific visual elements, as well as series data + * (via data proxy). + * + * For more complete description, see QScatter3DSeries. + * + * \sa {Qt Data Visualization Data Handling} + */ + + +/*! + * Constructs QScatter3DSeries with the given \a parent. + */ +QScatter3DSeries::QScatter3DSeries(QObject *parent) : + QAbstract3DSeries(new QScatter3DSeriesPrivate(this), parent) +{ + // Default proxy + dptr()->setDataProxy(new QScatterDataProxy); +} + +QScatter3DSeries::QScatter3DSeries(QScatterDataProxy *dataProxy, QObject *parent) : + QAbstract3DSeries(new QScatter3DSeriesPrivate(this), parent) +{ + dptr()->setDataProxy(dataProxy); +} + +/*! + * \internal + */ +QScatter3DSeries::QScatter3DSeries(QScatter3DSeriesPrivate *d, QObject *parent) : + QAbstract3DSeries(d, parent) +{ +} + +/*! + * Destroys QScatter3DSeries. + */ +QScatter3DSeries::~QScatter3DSeries() +{ +} + +/*! + * \property QScatter3DSeries::dataProxy + * + * This property holds the active data \a proxy. The series assumes ownership of any proxy set to + * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or + * set to another series. + */ +void QScatter3DSeries::setDataProxy(QScatterDataProxy *proxy) +{ + d_ptr->setDataProxy(proxy); +} + +QScatterDataProxy *QScatter3DSeries::dataProxy() const +{ + return static_cast<QScatterDataProxy *>(d_ptr->dataProxy()); +} + +/*! + * \internal + */ +QScatter3DSeriesPrivate *QScatter3DSeries::dptr() +{ + return static_cast<QScatter3DSeriesPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QScatter3DSeriesPrivate *QScatter3DSeries::dptrc() const +{ + return static_cast<const QScatter3DSeriesPrivate *>(d_ptr.data()); +} + +// QScatter3DSeriesPrivate + +QScatter3DSeriesPrivate::QScatter3DSeriesPrivate(QScatter3DSeries *q) + : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeScatter) +{ + m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); +} + +QScatter3DSeriesPrivate::~QScatter3DSeriesPrivate() +{ +} + +QScatter3DSeries *QScatter3DSeriesPrivate::qptr() +{ + return static_cast<QScatter3DSeries *>(q_ptr); +} + +void QScatter3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter); + + QAbstract3DSeriesPrivate::setDataProxy(proxy); + + emit qptr()->dataProxyChanged(static_cast<QScatterDataProxy *>(proxy)); +} + +void QScatter3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController) +{ + QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_dataProxy); + + if (m_controller && scatterDataProxy) { + //Disconnect old controller/old proxy + QObject::disconnect(scatterDataProxy, 0, m_controller, 0); + QObject::disconnect(q_ptr, 0, m_controller, 0); + } + + if (newController && scatterDataProxy) { + Scatter3DController *controller = static_cast<Scatter3DController *>(newController); + + QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset, + controller, &Scatter3DController::handleArrayReset); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded, + controller, &Scatter3DController::handleItemsAdded); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged, + controller, &Scatter3DController::handleItemsChanged); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved, + controller, &Scatter3DController::handleItemsRemoved); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted, + controller, &Scatter3DController::handleItemsInserted); + + QObject::connect(q_ptr, &QAbstract3DSeries::visibilityChanged, controller, + &Abstract3DController::handleSeriesVisibilityChanged); + + // Always clear selection on proxy change + // TODO: setSelectedScatter(noSelectionPoint()); + + newController->handleSeriesVisibilityChanged(m_visible); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qscatter3dseries.h b/src/datavisualization/data/qscatter3dseries.h new file mode 100644 index 00000000..bb24f79a --- /dev/null +++ b/src/datavisualization/data/qscatter3dseries.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSCATTER3DSERIES_H +#define QSCATTER3DSERIES_H + +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qscatterdataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatter3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QScatter3DSeries : public QAbstract3DSeries +{ + Q_OBJECT + Q_PROPERTY(QScatterDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged) + +public: + explicit QScatter3DSeries(QObject *parent = 0); + explicit QScatter3DSeries(QScatterDataProxy *dataProxy, QObject *parent = 0); + virtual ~QScatter3DSeries(); + + void setDataProxy(QScatterDataProxy *proxy); + QScatterDataProxy *dataProxy() const; + +signals: + void dataProxyChanged(QScatterDataProxy *proxy); + +protected: + explicit QScatter3DSeries(QScatter3DSeriesPrivate *d, QObject *parent = 0); + QScatter3DSeriesPrivate *dptr(); + const QScatter3DSeriesPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QScatter3DSeries) + + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatter3dseries_p.h b/src/datavisualization/data/qscatter3dseries_p.h new file mode 100644 index 00000000..001fb00c --- /dev/null +++ b/src/datavisualization/data/qscatter3dseries_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSCATTER3DSERIES_P_H +#define QSCATTER3DSERIES_P_H + +#include "qscatter3dseries.h" +#include "qabstract3dseries_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatter3DSeriesPrivate : public QAbstract3DSeriesPrivate +{ + Q_OBJECT +public: + QScatter3DSeriesPrivate(QScatter3DSeries *q); + virtual ~QScatter3DSeriesPrivate(); + + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void connectControllerAndProxy(Abstract3DController *newController); +private: + QScatter3DSeries *qptr(); + +private: + friend class QScatter3DSeries; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatterdataproxy.cpp b/src/datavisualization/data/qscatterdataproxy.cpp index 85cbb4eb..149cb1ae 100644 --- a/src/datavisualization/data/qscatterdataproxy.cpp +++ b/src/datavisualization/data/qscatterdataproxy.cpp @@ -18,6 +18,7 @@ #include "qscatterdataproxy.h" #include "qscatterdataproxy_p.h" +#include "qscatter3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -80,6 +81,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! + * \qmlproperty Scatter3DSeries ScatterDataProxy::series + * + * The series this proxy is attached to. + */ + +/*! * Constructs QScatterDataProxy with the given \a parent. */ QScatterDataProxy::QScatterDataProxy(QObject *parent) : @@ -103,6 +110,16 @@ QScatterDataProxy::~QScatterDataProxy() } /*! + * \property QScatterDataProxy::series + * + * The series this proxy is attached to. + */ +QScatter3DSeries *QScatterDataProxy::series() +{ + return static_cast<QScatter3DSeries *>(d_ptr->series()); +} + +/*! * Takes ownership of the \a newArray. Clears the existing array if the \a newArray is * different from the existing array. If it's the same array, this just triggers arrayReset() * signal. @@ -277,7 +294,6 @@ QScatterDataProxyPrivate::QScatterDataProxyPrivate(QScatterDataProxy *q) : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeScatter), m_dataArray(new QScatterDataArray) { - m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)"); } QScatterDataProxyPrivate::~QScatterDataProxyPrivate() @@ -346,7 +362,7 @@ void QScatterDataProxyPrivate::removeItems(int index, int removeCount) m_dataArray->remove(index, removeCount); } -void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) +void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const { if (m_dataArray->isEmpty()) return; @@ -393,4 +409,16 @@ void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV maxValues.setZ(maxZ); } +void QScatterDataProxyPrivate::setSeries(QAbstract3DSeries *series) +{ + QAbstractDataProxyPrivate::setSeries(series); + QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series); + emit qptr()->seriesChanged(scatterSeries); +} + +QScatterDataProxy *QScatterDataProxyPrivate::qptr() +{ + return static_cast<QScatterDataProxy *>(q_ptr); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qscatterdataproxy.h b/src/datavisualization/data/qscatterdataproxy.h index 178bc900..e17154c0 100644 --- a/src/datavisualization/data/qscatterdataproxy.h +++ b/src/datavisualization/data/qscatterdataproxy.h @@ -27,12 +27,14 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE typedef QVector<QScatterDataItem> QScatterDataArray; class QScatterDataProxyPrivate; +class QScatter3DSeries; class QT_DATAVISUALIZATION_EXPORT QScatterDataProxy : public QAbstractDataProxy { Q_OBJECT Q_PROPERTY(int itemCount READ itemCount) + Q_PROPERTY(QScatter3DSeries *series READ series NOTIFY seriesChanged) public: explicit QScatterDataProxy(QObject *parent = 0); @@ -46,6 +48,7 @@ public: * added in the future such as color requires allocating additional data object for the bar. */ + QScatter3DSeries *series(); int itemCount() const; const QScatterDataArray *array() const; const QScatterDataItem *itemAt(int index) const; @@ -69,6 +72,7 @@ signals: void itemsChanged(int startIndex, int count); void itemsRemoved(int startIndex, int count); void itemsInserted(int startIndex, int count); + void seriesChanged(QScatter3DSeries *series); protected: explicit QScatterDataProxy(QScatterDataProxyPrivate *d, QObject *parent = 0); diff --git a/src/datavisualization/data/qscatterdataproxy_p.h b/src/datavisualization/data/qscatterdataproxy_p.h index 24b5eb67..322c8937 100644 --- a/src/datavisualization/data/qscatterdataproxy_p.h +++ b/src/datavisualization/data/qscatterdataproxy_p.h @@ -51,9 +51,11 @@ public: void insertItems(int index, const QScatterDataArray &items); void removeItems(int index, int removeCount); - void limitValues(QVector3D &minValues, QVector3D &maxValues); + void limitValues(QVector3D &minValues, QVector3D &maxValues) const; + virtual void setSeries(QAbstract3DSeries *series); private: + QScatterDataProxy *qptr(); QScatterDataArray *m_dataArray; friend class QScatterDataProxy; diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp new file mode 100644 index 00000000..a4622580 --- /dev/null +++ b/src/datavisualization/data/qsurface3dseries.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qsurface3dseries_p.h" +#include "surface3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QSurface3DSeries + * \inmodule QtDataVisualization + * \brief Base series class for Q3DSurface. + * \since Qt Data Visualization 1.0 + * + * QSurface3DSeries manages the series specific visual elements, as well as series data + * (via data proxy). + * + * If no data proxy is set explicitly for the series, QSurface3DSeries creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it are destroyed. + * + * QSurface3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat(): + * \table + * \row + * \li @xTitle \li Title from X axis + * \row + * \li @yTitle \li Title from Y axis + * \row + * \li @zTitle \li Title from Z axis + * \row + * \li @xLabel \li Item value formatted using the same format as the X axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @yLabel \li Item value formatted using the same format as the Y axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @zLabel \li Item value formatted using the same format as the Z axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Surface3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QSurface3DSeries + * \inherits Abstract3DSeries + * \brief Base series type for Surfaces3D. + * + * This type manages the series specific visual elements, as well as series data + * (via data proxy). + * + * For more complete description, see QSurface3DSeries. + * + * \sa {Qt Data Visualization Data Handling} + */ + + +/*! + * Constructs QSurface3DSeries with the given \a parent. + */ +QSurface3DSeries::QSurface3DSeries(QObject *parent) : + QAbstract3DSeries(new QSurface3DSeriesPrivate(this), parent) +{ + // Default proxy + dptr()->setDataProxy(new QSurfaceDataProxy); +} + +QSurface3DSeries::QSurface3DSeries(QSurfaceDataProxy *dataProxy, QObject *parent) : + QAbstract3DSeries(new QSurface3DSeriesPrivate(this), parent) +{ + dptr()->setDataProxy(dataProxy); +} + +/*! + * \internal + */ +QSurface3DSeries::QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent) : + QAbstract3DSeries(d, parent) +{ +} + +/*! + * Destroys QSurface3DSeries. + */ +QSurface3DSeries::~QSurface3DSeries() +{ +} + +/*! + * \property QSurface3DSeries::dataProxy + * + * This property holds the active data \a proxy. The series assumes ownership of any proxy set to + * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or + * set to another series. + */ +void QSurface3DSeries::setDataProxy(QSurfaceDataProxy *proxy) +{ + d_ptr->setDataProxy(proxy); +} + +QSurfaceDataProxy *QSurface3DSeries::dataProxy() const +{ + return static_cast<QSurfaceDataProxy *>(d_ptr->dataProxy()); +} + +/*! + * \internal + */ +QSurface3DSeriesPrivate *QSurface3DSeries::dptr() +{ + return static_cast<QSurface3DSeriesPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QSurface3DSeriesPrivate *QSurface3DSeries::dptrc() const +{ + return static_cast<const QSurface3DSeriesPrivate *>(d_ptr.data()); +} + +// QSurface3DSeriesPrivate + +QSurface3DSeriesPrivate::QSurface3DSeriesPrivate(QSurface3DSeries *q) + : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeSurface) +{ + m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)"); +} + +QSurface3DSeriesPrivate::~QSurface3DSeriesPrivate() +{ +} + +QSurface3DSeries *QSurface3DSeriesPrivate::qptr() +{ + return static_cast<QSurface3DSeries *>(q_ptr); +} + +void QSurface3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface); + + QAbstract3DSeriesPrivate::setDataProxy(proxy); + + emit qptr()->dataProxyChanged(static_cast<QSurfaceDataProxy *>(proxy)); +} + +void QSurface3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController) +{ + QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_dataProxy); + + if (m_controller && surfaceDataProxy) { + //Disconnect old controller/old proxy + QObject::disconnect(surfaceDataProxy, 0, m_controller, 0); + QObject::disconnect(q_ptr, 0, m_controller, 0); + } + + if (newController && surfaceDataProxy) { + Surface3DController *controller = static_cast<Surface3DController *>(newController); + + QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, controller, + &Surface3DController::handleArrayReset); + + QObject::connect(q_ptr, &QAbstract3DSeries::visibilityChanged, controller, + &Abstract3DController::handleSeriesVisibilityChanged); + + // Always clear selection on proxy change + // TODO: setSelectedPoint(noSelectionPoint()); + + newController->handleSeriesVisibilityChanged(m_visible); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qsurface3dseries.h b/src/datavisualization/data/qsurface3dseries.h new file mode 100644 index 00000000..db432e41 --- /dev/null +++ b/src/datavisualization/data/qsurface3dseries.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSURFACE3DSERIES_H +#define QSURFACE3DSERIES_H + +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qsurfacedataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurface3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QSurface3DSeries : public QAbstract3DSeries +{ + Q_OBJECT + Q_PROPERTY(QSurfaceDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged) + +public: + explicit QSurface3DSeries(QObject *parent = 0); + explicit QSurface3DSeries(QSurfaceDataProxy *dataProxy, QObject *parent = 0); + virtual ~QSurface3DSeries(); + + void setDataProxy(QSurfaceDataProxy *proxy); + QSurfaceDataProxy *dataProxy() const; + +signals: + void dataProxyChanged(QSurfaceDataProxy *proxy); + +protected: + explicit QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent = 0); + QSurface3DSeriesPrivate *dptr(); + const QSurface3DSeriesPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QSurface3DSeries) + + friend class Surface3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qsurface3dseries_p.h b/src/datavisualization/data/qsurface3dseries_p.h new file mode 100644 index 00000000..6e5d9337 --- /dev/null +++ b/src/datavisualization/data/qsurface3dseries_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSURFACE3DSERIES_P_H +#define QSURFACE3DSERIES_P_H + +#include "qsurface3dseries.h" +#include "qabstract3dseries_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurface3DSeriesPrivate : public QAbstract3DSeriesPrivate +{ + Q_OBJECT +public: + QSurface3DSeriesPrivate(QSurface3DSeries *q); + virtual ~QSurface3DSeriesPrivate(); + + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void connectControllerAndProxy(Abstract3DController *newController); +private: + QSurface3DSeries *qptr(); + +private: + friend class QSurface3DSeries; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index 7fe44464..e3c2714c 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -18,6 +18,7 @@ #include "qsurfacedataproxy.h" #include "qsurfacedataproxy_p.h" +#include "qsurface3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -94,6 +95,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! + * \qmlproperty Surface3DSeries SurfaceDataProxy::series + * + * The series this proxy is attached to. + */ + +/*! * Constructs QSurfaceDataProxy with the given \a parent. */ QSurfaceDataProxy::QSurfaceDataProxy(QObject *parent) : @@ -117,6 +124,16 @@ QSurfaceDataProxy::~QSurfaceDataProxy() } /*! + * \property QSurfaceDataProxy::series + * + * The series this proxy is attached to. + */ +QSurface3DSeries *QSurfaceDataProxy::series() +{ + return static_cast<QSurface3DSeries *>(d_ptr->series()); +} + +/*! * Takes ownership of the \a newArray. Clears the existing array if the \a newArray is * different from the existing array. If it's the same array, this just triggers arrayReset() * signal. @@ -203,7 +220,6 @@ QSurfaceDataProxyPrivate::QSurfaceDataProxyPrivate(QSurfaceDataProxy *q) : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeSurface), m_dataArray(new QSurfaceDataArray) { - m_itemLabelFormat = QStringLiteral("@yLabel (@xLabel, @zLabel)"); } QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate() @@ -227,7 +243,7 @@ QSurfaceDataProxy *QSurfaceDataProxyPrivate::qptr() return static_cast<QSurfaceDataProxy *>(q_ptr); } -void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) +void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const { qreal min = 0.0; qreal max = 0.0; @@ -286,4 +302,11 @@ void QSurfaceDataProxyPrivate::clearArray() delete m_dataArray; } +void QSurfaceDataProxyPrivate::setSeries(QAbstract3DSeries *series) +{ + QAbstractDataProxyPrivate::setSeries(series); + QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series); + emit qptr()->seriesChanged(surfaceSeries); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qsurfacedataproxy.h b/src/datavisualization/data/qsurfacedataproxy.h index 460fa437..ed594963 100644 --- a/src/datavisualization/data/qsurfacedataproxy.h +++ b/src/datavisualization/data/qsurfacedataproxy.h @@ -28,6 +28,7 @@ typedef QVector<QSurfaceDataItem> QSurfaceDataRow; typedef QList<QSurfaceDataRow *> QSurfaceDataArray; class QSurfaceDataProxyPrivate; +class QSurface3DSeries; class QT_DATAVISUALIZATION_EXPORT QSurfaceDataProxy : public QAbstractDataProxy { @@ -35,11 +36,13 @@ class QT_DATAVISUALIZATION_EXPORT QSurfaceDataProxy : public QAbstractDataProxy Q_PROPERTY(int rowCount READ rowCount) Q_PROPERTY(int columnCount READ columnCount) + Q_PROPERTY(QSurface3DSeries *series READ series NOTIFY seriesChanged) public: explicit QSurfaceDataProxy(QObject *parent = 0); virtual ~QSurfaceDataProxy(); + QSurface3DSeries *series(); int rowCount() const; int columnCount() const; const QSurfaceDataArray *array() const; @@ -49,6 +52,7 @@ public: signals: void arrayReset(); + void seriesChanged(QSurface3DSeries *series); protected: explicit QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent = 0); diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h index 4c8c2820..066df629 100644 --- a/src/datavisualization/data/qsurfacedataproxy_p.h +++ b/src/datavisualization/data/qsurfacedataproxy_p.h @@ -45,7 +45,9 @@ public: void resetArray(QSurfaceDataArray *newArray); - void limitValues(QVector3D &minValues, QVector3D &maxValues); + void limitValues(QVector3D &minValues, QVector3D &maxValues) const; + + virtual void setSeries(QAbstract3DSeries *series); protected: QSurfaceDataArray *m_dataArray; diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc index 59331bf9..989bcc9b 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc @@ -70,8 +70,3 @@ \qmlproperty bool AbstractGraph3D::backgroundVisible Background visibility. If false, background is not drawn. */ - -/*! - \qmlproperty string AbstractGraph3D::itemLabelFormat - Label format of single item labels, e.g. a selected datapoint. - */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc index c81e5aac..45324b8a 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc @@ -36,7 +36,7 @@ * * See \l{Qt Quick 2 Bars Example} for more thorough usage example. * - * \sa ItemModelBarDataProxy, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} + * \sa Bar3DSeries, ItemModelBarData, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} */ /*! @@ -53,14 +53,6 @@ */ /*! - * \qmlproperty BarDataProxy Bars3D::dataProxy - * The active data proxy. - * - * If a proxy is not given, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another proxy is explicitly set active via this property. - */ - -/*! * \qmlproperty CategoryAxis3D Bars3D::rowAxis * A user-defined row axis. * @@ -134,3 +126,20 @@ * Position of the selected bar in data window. Only one bar can be selected at a time. * To clear selection, specify an illegal position, e.g. Qt.point(-1.0, -1.0). */ + +/*! + * \qmlproperty list<QBar3DSeries> seriesList + * This property holds the series of the graph. + * By default, this property contains an empty list. + * To set the series, either use the addSeries() function or define them as children of the graph. + */ + +/*! + * \qmlmethod void addSeries(QBar3DSeries *series) + * Add the \a series to the graph. + */ + +/*! + * \qmlmethod void removeSeries(QBar3DSeries *series) + * Remove the \a series from the graph. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc index e9661b60..7ad9d470 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc @@ -36,7 +36,7 @@ See \l{Qt Quick 2 Scatter Example} for more thorough usage example. - \sa ItemModelScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes} + \sa Scatter3DSeries, ScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes} */ /*! @@ -53,14 +53,6 @@ */ /*! - \qmlproperty ScatterDataProxy Scatter3D::dataProxy - The active data proxy. - - If a proxy is not given, a temporary default proxy is created and activated. - This temporary proxy is destroyed if another proxy is explicitly set active via this property. - */ - -/*! \qmlproperty ValueAxis3D Scatter3D::axisX A user-defined X axis. @@ -109,3 +101,20 @@ Selects an item in the \a index. Only one item can be selected at a time. To clear selection, specify an illegal \a index, e.g. -1. */ + +/*! + * \qmlproperty list<QScatter3DSeries> seriesList + * This property holds the series of the graph. + * By default, this property contains an empty list. + * To set the series, either use the addSeries() function or define them as children of the graph. + */ + +/*! + * \qmlmethod void addSeries(QScatter3DSeries *series) + * Add the \a series to the graph. + */ + +/*! + * \qmlmethod void removeSeries(QScatter3DSeries *series) + * Remove the \a series from the graph. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc index 55a0d1d1..d1422b10 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc @@ -36,15 +36,7 @@ See \l{Qt Quick 2 Surface Example} for more thorough usage example. - \sa ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes} - */ - -/*! - \qmlproperty SurfaceDataProxy Surface3D::dataProxy - The active data proxy. - - If a proxy is not given, a temporary default proxy is created and activated. - This temporary proxy is destroyed if another proxy is explicitly set active via this property. + \sa Surface3DSeries, ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes} */ /*! @@ -99,7 +91,25 @@ \qmlproperty point Surface3D::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. + the data array of the series. Only one point can be selected at a time. To clear selection, specify an illegal \a position, e.g. (-1, -1). */ + +/*! + * \qmlproperty list<QSurface3DSeries> seriesList + * This property holds the series of the graph. + * By default, this property contains an empty list. + * To set the series, either use the addSeries() function or define them as children of the graph. + * \note The surface graph currently supports only a single series at a time. + */ + +/*! + * \qmlmethod void addSeries(QSurface3DSeries *series) + * Add the \a series to the graph. + */ + +/*! + * \qmlmethod void removeSeries(QSurface3DSeries *series) + * Remove the \a series from the graph. + */ diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index ab2d0ac2..c1f3a4b7 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -27,6 +27,7 @@ #include "qabstractdataproxy_p.h" #include "qabstract3dinputhandler_p.h" #include "qtouch3dinputhandler.h" +#include "qabstract3dseries_p.h" #include <QThread> @@ -50,7 +51,6 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : m_axisZ(0), m_renderer(0), m_isDataDirty(true), - m_data(0), m_renderPending(false) { // Set initial theme @@ -82,11 +82,39 @@ Abstract3DController::~Abstract3DController() delete m_scene; } +/** + * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards. + * @param renderer Renderer to be used. + */ void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) { m_renderer = renderer; } +void Abstract3DController::addSeries(QAbstract3DSeries *series) +{ + if (series && !m_seriesList.contains(series)) { + m_seriesList.append(series); + series->d_ptr->setController(this); + } +} + +void Abstract3DController::removeSeries(QAbstract3DSeries *series) +{ + if (series && series->d_ptr->m_controller == this) { + m_seriesList.removeAll(series); + series->d_ptr->setController(0); + } +} + +QList<QAbstract3DSeries *> Abstract3DController::seriesList() +{ + return m_seriesList; +} + +/** + * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering. + */ void Abstract3DController::synchDataToRenderer() { // If we don't have a renderer, don't do anything @@ -334,6 +362,12 @@ void Abstract3DController::synchDataToRenderer() valueAxisZ->labelFormat()); } } + + // TODO: Another (per-series?) flag about series visuals being dirty? + if (m_isDataDirty) { + m_renderer->updateSeriesData(m_seriesList); + m_isDataDirty = false; + } } void Abstract3DController::render(const GLuint defaultFboHandle) @@ -582,64 +616,6 @@ QList<Q3DAbstractAxis *> Abstract3DController::axes() const return m_axes; } -QAbstractDataProxy *Abstract3DController::activeDataProxy() const -{ - return m_data; -} - -void Abstract3DController::addDataProxy(QAbstractDataProxy *proxy) -{ - Q_ASSERT(proxy); - Abstract3DController *owner = qobject_cast<Abstract3DController *>(proxy->parent()); - if (owner != this) { - Q_ASSERT_X(!owner, "addDataProxy", "Proxy already attached to a graph."); - proxy->setParent(this); - } - if (!m_dataProxies.contains(proxy)) - m_dataProxies.append(proxy); -} - -void Abstract3DController::releaseDataProxy(QAbstractDataProxy *proxy) -{ - if (proxy && m_dataProxies.contains(proxy)) { - // Clear the default status from released default proxies - if (proxy->d_ptr->isDefaultProxy()) - proxy->d_ptr->setDefaultProxy(false); - - // If the proxy is in use, replace it with a temporary one - if (m_data == proxy) - setActiveDataProxy(0); - - m_dataProxies.removeAll(proxy); - proxy->setParent(0); - } -} - -QList<QAbstractDataProxy *> Abstract3DController::dataProxies() const -{ - return m_dataProxies; -} - -void Abstract3DController::setActiveDataProxy(QAbstractDataProxy *proxy) -{ - // If existing proxy is the default proxy, delete it - if (m_data) { - if (m_data->d_ptr->isDefaultProxy()) { - m_dataProxies.removeAll(m_data); - delete m_data; - } else { - // Disconnect the old proxy from use - QObject::disconnect(m_data, 0, this, 0); - } - } - - // Assume ownership and activate - addDataProxy(proxy); - m_data = proxy; - m_isDataDirty = true; - emitNeedRender(); -} - void Abstract3DController::addInputHandler(QAbstract3DInputHandler *inputHandler) { Q_ASSERT(inputHandler); @@ -1113,6 +1089,13 @@ void Abstract3DController::handleInputPositionChanged(const QPoint &position) emitNeedRender(); } +void Abstract3DController::handleSeriesVisibilityChanged(bool visible) +{ + Q_UNUSED(visible) + + handleSeriesVisibilityChangedBySender(sender()); +} + void Abstract3DController::handleRequestShadowQuality(QDataVis::ShadowQuality quality) { setShadowQuality(quality); @@ -1136,6 +1119,14 @@ void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender) emitNeedRender(); } +void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender) +{ + Q_UNUSED(sender) + + m_isDataDirty = true; + emitNeedRender(); +} + void Abstract3DController::setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis, Q3DAbstractAxis **axisPtr) { diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index d68d33e2..39e0abe6 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -47,6 +47,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class CameraHelper; class Abstract3DRenderer; +class QAbstract3DSeries; struct Abstract3DChangeBitField { bool positionChanged : 1; @@ -195,32 +196,24 @@ protected: QList<Q3DAbstractAxis *> m_axes; // List of all added axes Abstract3DRenderer *m_renderer; bool m_isDataDirty; - - QAbstractDataProxy *m_data; - QList<QAbstractDataProxy *> m_dataProxies; - bool m_renderPending; + QList<QAbstract3DSeries *> m_seriesList; + explicit Abstract3DController(QRect boundRect, QObject *parent = 0); virtual ~Abstract3DController(); public: inline bool isInitialized() { return (m_renderer != 0); } - - /** - * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering. - */ virtual void synchDataToRenderer(); - virtual void render(const GLuint defaultFboHandle = 0); - - /** - * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards. - * @param renderer Renderer to be used. - */ void setRenderer(Abstract3DRenderer *renderer); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + QList<QAbstract3DSeries *> seriesList(); + // Size virtual void setSize(const int width, const int height); virtual const QSize size(); @@ -256,11 +249,6 @@ public: virtual void setActiveInputHandler(QAbstract3DInputHandler *inputHandler); virtual QAbstract3DInputHandler *activeInputHandler(); - virtual QAbstractDataProxy *activeDataProxy() const; - virtual void addDataProxy(QAbstractDataProxy *proxy); - virtual void releaseDataProxy(QAbstractDataProxy *proxy); - virtual QList<QAbstractDataProxy *> dataProxies() const; - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); virtual void updateDevicePixelRatio(qreal ratio); virtual int zoomLevel(); @@ -324,6 +312,9 @@ public: Q3DScene *scene(); + inline void setDataDirty() { m_isDataDirty = true; } + void emitNeedRender(); + virtual void mouseDoubleClickEvent(QMouseEvent *event); virtual void touchEvent(QTouchEvent *event); virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); @@ -339,6 +330,7 @@ public: virtual void handleAxisAutoAdjustRangeChangedInOrientation( Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0; virtual void handleAxisLabelFormatChangedBySender(QObject *sender); + virtual void handleSeriesVisibilityChangedBySender(QObject *sender); public slots: void handleAxisTitleChanged(const QString &title); @@ -350,6 +342,7 @@ public slots: void handleAxisLabelFormatChanged(const QString &format); void handleInputStateChanged(QDataVis::InputState state); void handleInputPositionChanged(const QPoint &position); + void handleSeriesVisibilityChanged(bool visible); // Renderer callback handlers void handleRequestShadowQuality(QDataVis::ShadowQuality quality); @@ -377,7 +370,6 @@ protected: virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation); Q3DValueAxis *createDefaultValueAxis(); Q3DCategoryAxis *createDefaultCategoryAxis(); - void emitNeedRender(); private: void setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis, diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index 1b1143fa..f639c6e3 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -23,6 +23,7 @@ #include "q3dscene_p.h" #include "q3dcamera_p.h" #include "q3dlight_p.h" +#include "qabstract3dseries_p.h" Q_DECLARE_METATYPE(QtDataVisualization::QDataVis::ShadowQuality) @@ -142,11 +143,6 @@ QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal valu return Utils::formatLabel(valueFormatArray, valueParamType, value); } -void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy) -{ - m_cachedItemLabelFormat = dataProxy->itemLabelFormat(); -} - QString Abstract3DRenderer::itemLabelFormat() const { return m_cachedItemLabelFormat; @@ -378,6 +374,13 @@ void Abstract3DRenderer::updateMultiHighlightGradient(const QLinearGradient &gra fixGradient(&m_cachedMultiHighlightGradient, &m_multiHighlightGradientTexture); } +void Abstract3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) +{ + // TODO: To series visuals update - just use first series format for now + if (seriesList.size()) + m_cachedItemLabelFormat = seriesList.at(0)->itemLabelFormat(); +} + AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation) { switch (orientation) { diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 838eb181..3c833956 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -99,7 +99,7 @@ protected: public: virtual ~Abstract3DRenderer(); - void updateDataModel(QAbstractDataProxy *dataProxy); + virtual void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); virtual void render(GLuint defaultFboHandle); diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 6d1ebbae..019a96be 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -23,6 +23,7 @@ #include "q3dvalueaxis_p.h" #include "q3dcategoryaxis_p.h" #include "qbardataproxy_p.h" +#include "qbar3dseries_p.h" #include <QMatrix4x4> #include <qmath.h> @@ -40,8 +41,6 @@ Bars3DController::Bars3DController(QRect boundRect) // Default bar type; specific to bars setBarType(QDataVis::MeshStyleBevelBars, false); - setActiveDataProxy(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 // functions implemented by subclasses. @@ -83,57 +82,11 @@ void Bars3DController::synchDataToRenderer() m_changeTracker.barSpecsChanged = false; } + // Needs to be done after data is set, as it needs to know the visual array. if (m_changeTracker.selectedBarChanged) { m_renderer->updateSelectedBar(m_selectedBar); m_changeTracker.selectedBarChanged = false; } - - if (m_isDataDirty) { - m_renderer->updateDataModel(static_cast<QBarDataProxy *>(m_data)); - m_isDataDirty = false; - } -} - -void Bars3DController::setActiveDataProxy(QAbstractDataProxy *proxy) -{ - // Setting null proxy indicates default proxy - if (!proxy) { - proxy = new QBarDataProxy; - proxy->d_ptr->setDefaultProxy(true); - } - - Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar); - - Abstract3DController::setActiveDataProxy(proxy); - - QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_data); - - QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, this, - &Bars3DController::handleArrayReset); - QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, this, - &Bars3DController::handleRowsAdded); - QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, this, - &Bars3DController::handleRowsChanged); - QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, this, - &Bars3DController::handleRowsRemoved); - QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, this, - &Bars3DController::handleRowsInserted); - QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, this, - &Bars3DController::handleItemChanged); - QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, this, - &Bars3DController::handleDataRowLabelsChanged); - QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, this, - &Bars3DController::handleDataColumnLabelsChanged); - - adjustAxisRanges(); - - // Always clear selection on proxy change - setSelectedBar(noSelectionPoint()); - - handleDataRowLabelsChanged(); - handleDataColumnLabelsChanged(); - m_isDataDirty = true; - emitNeedRender(); } void Bars3DController::handleArrayReset() @@ -196,22 +149,29 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) void Bars3DController::handleDataRowLabelsChanged() { - if (m_axisX && m_data) { + QBar3DSeries *firstSeries = 0; + if (m_seriesList.size()) + firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0)); + if (m_axisX && firstSeries && firstSeries->dataProxy()) { // Grab a sublist equal to data window (no need to have more labels in axis) int min = int(m_axisX->min()); int count = int(m_axisX->max()) - min + 1; - QStringList subList = static_cast<QBarDataProxy *>(m_data)->rowLabels().mid(min, count); + QStringList subList = firstSeries->dataProxy()->rowLabels().mid(min, count); static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList); } } void Bars3DController::handleDataColumnLabelsChanged() { - if (m_axisZ && m_data) { + QBar3DSeries *firstSeries = 0; + if (m_seriesList.size()) + firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0)); + if (m_axisZ && firstSeries && firstSeries->dataProxy()) { // Grab a sublist equal to data window (no need to have more labels in axis) int min = int(m_axisZ->min()); int count = int(m_axisZ->max()) - min + 1; - QStringList subList = static_cast<QBarDataProxy *>(m_data)->columnLabels().mid(min, count); + QStringList subList = static_cast<QBarDataProxy *>(firstSeries->dataProxy()) + ->columnLabels().mid(min, count); static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList); } } @@ -249,6 +209,55 @@ void Bars3DController::setAxisZ(Q3DAbstractAxis *axis) handleDataColumnLabelsChanged(); } +void Bars3DController::addSeries(QAbstract3DSeries *series) +{ + Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeBar); + + bool firstAdded = !m_seriesList.size(); + + Abstract3DController::addSeries(series); + + if (firstAdded) { + adjustAxisRanges(); + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); + + // TODO: Temp until selection by series is properly implemented + setSelectedBar(noSelectionPoint()); + } +} + +void Bars3DController::removeSeries(QAbstract3DSeries *series) +{ + bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series); + + Abstract3DController::removeSeries(series); + + if (firstRemoved) { + adjustAxisRanges(); + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); + + // TODO: Temp until selection by series is properly implemented + setSelectedBar(noSelectionPoint()); + } +} + +QList<QBar3DSeries *> Bars3DController::barSeriesList() +{ + QList<QAbstract3DSeries *> abstractSeriesList = seriesList(); + QList<QBar3DSeries *> barSeriesList; + foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) { + QBar3DSeries *barSeries = qobject_cast<QBar3DSeries *>(abstractSeries); + if (barSeries) + barSeriesList.append(barSeries); + } + + return barSeriesList; +} + void Bars3DController::handleAxisRangeChangedBySender(QObject *sender) { // Data window changed @@ -334,8 +343,14 @@ void Bars3DController::setSelectedBar(const QPoint &position) // If the selection targets non-existent bar, clear selection instead. QPoint pos = position; + // TODO: Selection needs to be refactored to be handled by series + const QBarDataProxy *proxy = 0; + if (m_seriesList.size()) + proxy = static_cast<QBar3DSeries *>(m_seriesList.at(0))->dataProxy(); + else + return; + if (pos != noSelectionPoint()) { - const QBarDataProxy *proxy = static_cast<const QBarDataProxy *>(m_data); int maxRow = proxy->rowCount() - 1; int maxCol = (pos.x() <= maxRow && pos.x() >= 0 && proxy->rowAt(pos.x())) ? proxy->rowAt(pos.x())->size() - 1 : -1; @@ -370,43 +385,45 @@ QPoint Bars3DController::selectedBar() const void Bars3DController::adjustAxisRanges() { - const QBarDataProxy *proxy = static_cast<QBarDataProxy *>(m_data); - const QBarDataArray *array = proxy->array(); - - Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX); - if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) { - int rowCount = proxy->rowCount(); - if (rowCount) - rowCount--; - categoryAxisX->dptr()->setRange(0.0, qreal(rowCount)); - } + if (m_seriesList.size()) { + const QBarDataProxy *proxy = static_cast<QBar3DSeries *>(m_seriesList.at(0))->dataProxy(); + const QBarDataArray *array = proxy->array(); + + Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX); + if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) { + int rowCount = proxy->rowCount(); + if (rowCount) + rowCount--; + categoryAxisX->dptr()->setRange(0.0, qreal(rowCount)); + } - Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ); - if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) { - int columnCount = 0; - for (int i = 0; i < array->size(); i++) { - if (columnCount < array->at(i)->size()) - columnCount = array->at(i)->size(); + Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ); + if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) { + int columnCount = 0; + for (int i = 0; i < array->size(); i++) { + if (columnCount < array->at(i)->size()) + columnCount = array->at(i)->size(); + } + if (columnCount) + columnCount--; + categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount)); } - if (columnCount) - columnCount--; - categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount)); - } - Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY); - if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) { - QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(), - categoryAxisX->max(), - categoryAxisZ->min(), - categoryAxisZ->max()); - if (limits.first < 0) { - // Call private implementation to avoid unsetting auto adjust flag - valueAxis->dptr()->setRange(limits.first, limits.second); - } else if (limits.second == 0.0) { - // Only zero value values in data set, set range to something. - valueAxis->dptr()->setRange(0.0, 1.0); - } else { - valueAxis->dptr()->setRange(0.0, limits.second); + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY); + if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) { + QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(), + categoryAxisX->max(), + categoryAxisZ->min(), + categoryAxisZ->max()); + if (limits.first < 0) { + // Call private implementation to avoid unsetting auto adjust flag + valueAxis->dptr()->setRange(limits.first, limits.second); + } else if (limits.second == 0.0) { + // Only zero value values in data set, set range to something. + valueAxis->dptr()->setRange(0.0, 1.0); + } else { + valueAxis->dptr()->setRange(0.0, limits.second); + } } } } diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 652aeb48..f1eda225 100644 --- a/src/datavisualization/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -37,7 +37,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Bars3DRenderer; -class QBarDataProxy; +class QBar3DSeries; struct Bars3DChangeBitField { bool slicingActiveChanged : 1; @@ -92,8 +92,6 @@ public: void setSelectedBar(const QPoint &position); QPoint selectedBar() const; - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); static QPoint noSelectionPoint(); @@ -101,6 +99,10 @@ public: virtual void setAxisX(Q3DAbstractAxis *axis); virtual void setAxisZ(Q3DAbstractAxis *axis); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + virtual QList<QBar3DSeries *> barSeriesList(); + virtual void handleAxisRangeChangedBySender(QObject *sender); public slots: diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index be844a43..c7dac4f9 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -27,6 +27,7 @@ #include "drawer_p.h" #include "qbardataitem.h" #include "q3dlight.h" +#include "qbar3dseries_p.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -46,12 +47,6 @@ const int smallerVPSize = 5; const bool sliceGridLabels = true; // TODO: Make this user controllable (QTRD-2546) -// TODO: These will be based on sets (QTRD-2548) -const int seriesCount = 1; -const float seriesScale = 1.0f / float(seriesCount); -const float seriesStep = 1.0f / float(seriesCount); -const float seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * seriesStep; - Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) : Abstract3DRenderer(controller), m_cachedIsSlicingActivated(false), @@ -95,7 +90,11 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_clickedBarColor(invalidColorVector), m_hasHeightAdjustmentChanged(true), m_selectedBarPos(Bars3DController::noSelectionPoint()), - m_noZeroInRange(false) + m_noZeroInRange(false), + m_seriesCount(0), + m_seriesScale(0.0f), + m_seriesStep(0.0f), + m_seriesStart(0.0f) { initializeOpenGLFunctions(); initializeOpenGL(); @@ -153,8 +152,15 @@ void Bars3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) +void Bars3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) { + QList<QBar3DSeries *> visibleSeries; + foreach (QAbstract3DSeries *current, seriesList) { + if (current->isVisible()) + visibleSeries.append(static_cast<QBar3DSeries *>(current)); + } + + int seriesCount = visibleSeries.size(); int minRow = m_axisCacheX.min(); int maxRow = m_axisCacheX.max(); int minCol = m_axisCacheZ.min(); @@ -163,38 +169,43 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) int newColumns = maxCol - minCol + 1; int updateSize = 0; int dataRowCount = 0; - // TODO: Dummy series, replace with actual after QTRD-2548 - // TODO: Check if resize is needed - m_renderingArrays.clear(); - m_renderingArrays.resize(seriesCount); - for (int series = 0; series < seriesCount; series++) { + + if (m_seriesCount != seriesCount) { + m_seriesCount = seriesCount; + m_renderingArrays.resize(m_seriesCount); + m_seriesScale = 1.0f / float(m_seriesCount); + m_seriesStep = 1.0f / float(m_seriesCount); + m_seriesStart = -((float(m_seriesCount) - 1.0f) / 2.0f) * m_seriesStep; + } + + if (m_cachedRowCount != newRows || m_cachedColumnCount != newColumns) { + // Force update for selection related items + m_sliceCache = 0; + m_sliceTitleItem = 0; + if (m_sliceSelection) + m_sliceSelection->clear(); + + m_cachedColumnCount = newColumns; + m_cachedRowCount = newRows; + // Calculate max scene size + GLfloat sceneRatio = qMin(GLfloat(newColumns) / GLfloat(newRows), + GLfloat(newRows) / GLfloat(newColumns)); + m_maxSceneSize = 2.0f * qSqrt(sceneRatio * newColumns * newRows); + // Calculate here and at setting bar specs + calculateSceneScalingFactors(); + } + + for (int series = 0; series < m_seriesCount; series++) { if (newRows != m_renderingArrays.at(series).size() || newColumns != m_renderingArrays.at(series).at(0).size()) { // Destroy old render items and reallocate new array - m_renderingArrays[series].clear(); m_renderingArrays[series].resize(newRows); for (int i = 0; i < newRows; i++) m_renderingArrays[series][i].resize(newColumns); - - if (series == 0) { - // Force update for selection related items - m_sliceCache = 0; - m_sliceTitleItem = 0; - if (m_sliceSelection) - m_sliceSelection->clear(); - - m_cachedColumnCount = newColumns; - m_cachedRowCount = newRows; - // Calculate max scene size - GLfloat sceneRatio = qMin(GLfloat(newColumns) / GLfloat(newRows), - GLfloat(newRows) / GLfloat(newColumns)); - m_maxSceneSize = 2.0f * qSqrt(sceneRatio * newColumns * newRows); - // Calculate here and at setting bar specs - calculateSceneScalingFactors(); - } } // Update cached data window + QBarDataProxy *dataProxy = visibleSeries.at(series)->dataProxy(); dataRowCount = dataProxy->rowCount(); int dataRowIndex = minRow; GLfloat heightValue = 0.0f; @@ -222,9 +233,8 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) heightValue = 0.0f; } } - // TODO: Dummy values for replicated series, replace with actual after QTRD-2548 - m_renderingArrays[series][i][j].setValue(value * ((series + 1.0f) / float(seriesCount))); - m_renderingArrays[series][i][j].setHeight((heightValue / m_heightNormalizer) * ((series + 1.0f) / float(seriesCount))); + m_renderingArrays[series][i][j].setValue(value); + m_renderingArrays[series][i][j].setHeight(heightValue / m_heightNormalizer); dataColIndex++; } } @@ -238,12 +248,15 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) } m_renderColumns = updateSize; - m_renderRows = qMin((dataRowCount - minRow), m_renderingArrays[0].size()); + if (m_renderingArrays.size()) + m_renderRows = qMin((dataRowCount - minRow), newRows); + else + m_renderRows = 0; // Reset selected bar to update selection updateSelectedBar(m_selectedBarPos); - Abstract3DRenderer::updateDataModel(dataProxy); + Abstract3DRenderer::updateSeriesData(seriesList); } void Bars3DRenderer::updateScene(Q3DScene *scene) @@ -459,9 +472,9 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel, GLuint gradientTexture = 0; QVector3D modelMatrixScaler(m_scaleX, 0.0f, m_scaleZ); if (rowMode) - modelMatrixScaler.setX(m_scaleX * seriesScale); + modelMatrixScaler.setX(m_scaleX * m_seriesScale); else - modelMatrixScaler.setZ(m_scaleZ * seriesScale); + modelMatrixScaler.setZ(m_scaleZ * m_seriesScale); // Set common bar shader bindings m_barShader->setUniformValue(m_barShader->lightP(), lightPos); @@ -596,7 +609,7 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel, int labelCount = m_sliceCache->labelItems().size(); for (int labelNo = 0; labelNo < labelCount; labelNo++) { // Get labels from first series only - BarRenderItem *item = m_sliceSelection->at(labelNo * seriesCount); + BarRenderItem *item = m_sliceSelection->at(labelNo * m_seriesCount); // TODO: Make user controllable (QTRD-2546) // Draw labels int labelIndex = flipped ? m_sliceCache->labelItems().size() - 1 - labelNo : labelNo; @@ -760,12 +773,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix; // Draw bars to depth buffer - QVector3D shadowScaler(m_scaleX * seriesScale * 0.9f, 0.0f, m_scaleZ * 0.9f); + QVector3D shadowScaler(m_scaleX * m_seriesScale * 0.9f, 0.0f, m_scaleZ * 0.9f); for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { GLfloat shadowOffset = 0.0f; - float seriesPos = seriesStart; - for (int series = 0; series < seriesCount; series++) { + float seriesPos = m_seriesStart; + for (int series = 0; series < m_seriesCount; series++) { const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar); if (!item.value()) continue; @@ -818,7 +831,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableVertexAttribArray(m_depthShader->posAtt()); - seriesPos += seriesStep; + seriesPos += m_seriesStep; } } } @@ -867,8 +880,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { - float seriesPos = seriesStart; - for (int series = 0; series < seriesCount; series++) { + float seriesPos = m_seriesStart; + for (int series = 0; series < m_seriesCount; series++) { const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar); if (!item.value()) continue; @@ -887,7 +900,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, item.height(), (m_columnDepth - rowPos) / m_scaleFactor); - modelMatrix.scale(QVector3D(m_scaleX * seriesScale, + modelMatrix.scale(QVector3D(m_scaleX * m_seriesScale, item.height(), m_scaleZ)); @@ -925,7 +938,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glDisableVertexAttribArray(m_selectionShader->posAtt()); - seriesPos += seriesStep; + seriesPos += m_seriesStep; } } } @@ -1008,12 +1021,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) bool barSelectionFound = false; BarRenderItem *selectedBar(0); - QVector3D modelScaler(m_scaleX * seriesScale, 0.0f, m_scaleZ); + QVector3D modelScaler(m_scaleX * m_seriesScale, 0.0f, m_scaleZ); bool somethingSelected = (m_visualSelectedBarPos != Bars3DController::noSelectionPoint()); for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { - float seriesPos = seriesStart; - for (int series = 0; series < seriesCount; series++) { + float seriesPos = m_seriesStart; + for (int series = 0; series < m_seriesCount; series++) { BarRenderItem &item = m_renderingArrays[series][row][bar]; if (item.height() < 0) @@ -1072,7 +1085,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) if (m_selectionDirty && m_cachedIsSlicingActivated) { QVector3D translation = modelMatrix.column(3).toVector3D(); if (m_cachedSelectionMode & QDataVis::SelectionColumn - && seriesCount > 1) { + && m_seriesCount > 1) { translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos) * (m_cachedBarSpacing.height()))) / m_scaleFactor); @@ -1115,7 +1128,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) shadowLightStrength = adjustedHighlightStrength; if (m_cachedIsSlicingActivated) { QVector3D translation = modelMatrix.column(3).toVector3D(); - if (seriesCount > 1) { + if (m_seriesCount > 1) { translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos) * (m_cachedBarSpacing.height()))) / m_scaleFactor); @@ -1172,7 +1185,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_drawer->drawObject(m_barShader, m_barObj, gradientTexture); } } - seriesPos += seriesStep; + seriesPos += m_seriesStep; } } } diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 00b3510a..98fdf92e 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -105,12 +105,16 @@ private: BarRenderItem m_dummyBarRenderItem; QVector<BarRenderItemArray> m_renderingArrays; bool m_noZeroInRange; + int m_seriesCount; + float m_seriesScale; + float m_seriesStep; + float m_seriesStart; public: explicit Bars3DRenderer(Bars3DController *controller); ~Bars3DRenderer(); - void updateDataModel(QBarDataProxy *dataProxy); + void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp index 1eded43a..3baff904 100644 --- a/src/datavisualization/engine/q3dbars.cpp +++ b/src/datavisualization/engine/q3dbars.cpp @@ -21,8 +21,8 @@ #include "bars3dcontroller_p.h" #include "q3dvalueaxis.h" #include "q3dcategoryaxis.h" -#include "qbardataproxy.h" #include "q3dcamera.h" +#include "qbar3dseries_p.h" #include <QMouseEvent> @@ -46,11 +46,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * These default axes can be modified via axis accessors, but as soon any axis is set explicitly * for the orientation, the default axis for that orientation is destroyed. * - * Data proxies work similarly: If no data proxy is set explicitly, Q3DBars creates a default - * proxy. If any other proxy is set as active data proxy later, the default proxy and all data - * added to it is destroyed. + * Q3DBars supports more than one series visible at the same time, but all series added to the + * graph must have proxies with identical row and column counts for the graph to draw properly. + * Row and column labels are taken from the first added series, unless explicitly defined to + * row and column axes. * - * Methods are provided for changing bar types, themes, bar selection modes and so on. See the + * Methods are provided for changing themes, bar selection modes and so on. See the * methods for more detailed descriptions. * * \section1 How to construct a minimal Q3DBars graph @@ -61,7 +62,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * * After constructing Q3DBars, you can set the data window by changing the range on the row and * column axes. It is not mandatory, as data window will default to showing all of the data in - * the data proxy. If the amount of data is large, it is usually preferable to show just a + * the series. If the amount of data is large, it is usually preferable to show just a * portion of it. For the example, let's set the data window to show first five rows and columns: * * \snippet doc_src_q3dbars_construction.cpp 0 @@ -139,13 +140,41 @@ Q3DBars::Q3DBars() } /*! - * Destroys the 3D bar window. + * Destroys the 3D bar window. */ Q3DBars::~Q3DBars() { } /*! + * Adds the \a series to the graph. A graph can contain multiple series, but only one set of axes, + * so the rows and columns of all series must match for the visualized data to be meaningful. + * If the graph has multiple visible series, only the first one added will + * generate the row or column labels on the axes in cases where the labels are not explicitly set + * to the axes. + */ +void Q3DBars::addSeries(QBar3DSeries *series) +{ + d_ptr->m_shared->addSeries(series); +} + +/*! + * Removes the \a series from the graph. + */ +void Q3DBars::removeSeries(QBar3DSeries *series) +{ + d_ptr->m_shared->removeSeries(series); +} + +/*! + * \return list of series added to this graph. + */ +QList<QBar3DSeries *> Q3DBars::seriesList() +{ + return d_ptr->m_shared->barSeriesList(); +} + +/*! * \internal */ void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event) @@ -424,7 +453,7 @@ bool Q3DBars::isBackgroundVisible() const * \property Q3DBars::selectedBar * * Selects a bar in a \a position. The position is the (row, column) position in - * the data array of the active data proxy. + * the data array of the series. * Only one bar can be selected at a time. * To clear selection, specify an illegal \a position, e.g. (-1, -1). */ @@ -689,68 +718,6 @@ QList<Q3DAbstractAxis *> Q3DBars::axes() const return d_ptr->m_shared->axes(); } -/*! - * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of - * the \a proxy to this graph. - * - * If the \a proxy is null, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method. - * - * \sa addDataProxy(), releaseDataProxy() - */ -void Q3DBars::setActiveDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->setActiveDataProxy(proxy); -} - -/*! - * \return active data proxy. - */ -QBarDataProxy *Q3DBars::activeDataProxy() const -{ - return static_cast<QBarDataProxy *>(d_ptr->m_shared->activeDataProxy()); -} - -/*! - * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, - * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. - * The \a proxy must not be null or added to another graph. - * - * \sa releaseDataProxy(), setActiveDataProxy() - */ -void Q3DBars::addDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->addDataProxy(proxy); -} - -/*! - * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. - * If the released \a proxy is in use, a new empty default proxy is created and taken to use. - * - * If the default \a proxy is released and added back later, it behaves as any other proxy would. - * - * \sa addDataProxy(), setActiveDataProxy() - */ -void Q3DBars::releaseDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->releaseDataProxy(proxy); -} - -/*! - * \return list of all added data proxies. - * - * \sa addDataProxy() - */ -QList<QBarDataProxy *> Q3DBars::dataProxies() const -{ - QList<QBarDataProxy *> retList; - QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); - foreach (QAbstractDataProxy *proxy, abstractList) - retList.append(static_cast<QBarDataProxy *>(proxy)); - - return retList; -} - Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) : q_ptr(q), m_shared(new Bars3DController(rect)) diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h index 96fce909..cba54dce 100644 --- a/src/datavisualization/engine/q3dbars.h +++ b/src/datavisualization/engine/q3dbars.h @@ -30,8 +30,8 @@ class Q3DBarsPrivate; class Q3DAbstractAxis; class Q3DCategoryAxis; class Q3DValueAxis; -class QBarDataProxy; class Q3DScene; +class QBar3DSeries; class QT_DATAVISUALIZATION_EXPORT Q3DBars : public Q3DWindow { @@ -61,6 +61,10 @@ public: explicit Q3DBars(); ~Q3DBars(); + void addSeries(QBar3DSeries *series); + void removeSeries(QBar3DSeries *series); + QList<QBar3DSeries *> seriesList(); + // TODO: Move to dataset object once that is done QTRD-2121 void setBarType(QDataVis::MeshStyle style, bool smooth = false); @@ -132,13 +136,6 @@ public: void releaseAxis(Q3DAbstractAxis *axis); QList<Q3DAbstractAxis *> axes() const; - // TODO: Move to dataset object once that is done QTRD-2121 - void setActiveDataProxy(QBarDataProxy *proxy); - QBarDataProxy *activeDataProxy() const; - void addDataProxy(QBarDataProxy *proxy); - void releaseDataProxy(QBarDataProxy *proxy); - QList<QBarDataProxy *> dataProxies() const; - signals: void selectionModeChanged(QDataVis::SelectionFlags mode); void labelStyleChanged(QDataVis::LabelStyle style); diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp index 195660a9..7aaa0e6b 100644 --- a/src/datavisualization/engine/q3dscatter.cpp +++ b/src/datavisualization/engine/q3dscatter.cpp @@ -20,8 +20,8 @@ #include "q3dscatter_p.h" #include "scatter3dcontroller_p.h" #include "q3dvalueaxis.h" -#include "qscatterdataproxy.h" #include "q3dcamera.h" +#include "qscatter3dseries_p.h" #include <QMouseEvent> #include <QDebug> @@ -44,11 +44,9 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * These default axes can be modified via axis accessors, but as soon any axis is set explicitly * for the orientation, the default axis for that orientation is destroyed. * - * Data proxies work similarly: if no data proxy is set explicitly, Q3DScatter creates a default - * proxy. If any other proxy is set as active data proxy later, the default proxy and all data - * added to it is destroyed. + * Q3DScatter supports more than one series visible at the same time. * - * Methods are provided for changing item styles, themes, item selection modes and so on. See the + * Methods are provided for changing themes, item selection modes and so on. See the * methods for more detailed descriptions. * * \section1 How to construct a minimal Q3DScatter graph @@ -125,13 +123,38 @@ Q3DScatter::Q3DScatter() } /*! - * Destroys the 3D scatter window. + * Destroys the 3D scatter window. */ Q3DScatter::~Q3DScatter() { } /*! + * Adds the \a series to the graph. A graph can contain multiple series, but has only one set of + * axes. + */ +void Q3DScatter::addSeries(QScatter3DSeries *series) +{ + d_ptr->m_shared->addSeries(series); +} + +/*! + * Removes the \a series from the graph. + */ +void Q3DScatter::removeSeries(QScatter3DSeries *series) +{ + d_ptr->m_shared->removeSeries(series); +} + +/*! + * \return list of series added to this graph. + */ +QList<QScatter3DSeries *> Q3DScatter::seriesList() +{ + return d_ptr->m_shared->scatterSeriesList(); +} + +/*! * \internal */ void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event) @@ -620,68 +643,6 @@ QList<Q3DValueAxis *> Q3DScatter::axes() const } /*! - * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of - * the \a proxy to this graph. - * - * If the \a proxy is null, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method. - * - * \sa addDataProxy(), releaseDataProxy() - */ -void Q3DScatter::setActiveDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->setActiveDataProxy(proxy); -} - -/*! - * \return active data proxy. - */ -QScatterDataProxy *Q3DScatter::activeDataProxy() const -{ - return static_cast<QScatterDataProxy *>(d_ptr->m_shared->activeDataProxy()); -} - -/*! - * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, - * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. - * The \a proxy must not be null or added to another graph. - * - * \sa releaseDataProxy(), setActiveDataProxy() - */ -void Q3DScatter::addDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->addDataProxy(proxy); -} - -/*! - * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. - * If the released \a proxy is in use, a new empty default proxy is created and taken to use. - * - * If the default \a proxy is released and added back later, it behaves as any other proxy would. - * - * \sa addDataProxy(), setActiveDataProxy() - */ -void Q3DScatter::releaseDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->releaseDataProxy(proxy); -} - -/*! - * \return list of all added data proxies. - * - * \sa addDataProxy() - */ -QList<QScatterDataProxy *> Q3DScatter::dataProxies() const -{ - QList<QScatterDataProxy *> retList; - QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); - foreach (QAbstractDataProxy *proxy, abstractList) - retList.append(static_cast<QScatterDataProxy *>(proxy)); - - return retList; -} - -/*! * \fn void Q3DScatter::shadowQualityChanged(QDataVis::ShadowQuality quality) * * This signal is emitted when shadow \a quality changes. diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h index 49397a56..2f403ce1 100644 --- a/src/datavisualization/engine/q3dscatter.h +++ b/src/datavisualization/engine/q3dscatter.h @@ -31,7 +31,7 @@ class Q3DScatterPrivate; class LabelItem; class Q3DValueAxis; class Q3DCategoryAxis; -class QScatterDataProxy; +class QScatter3DSeries; class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public Q3DWindow { @@ -58,6 +58,10 @@ public: explicit Q3DScatter(); ~Q3DScatter(); + void addSeries(QScatter3DSeries *series); + void removeSeries(QScatter3DSeries *series); + QList<QScatter3DSeries *> seriesList(); + void setObjectType(QDataVis::MeshStyle style, bool smooth = false); void setTheme(QDataVis::Theme theme); @@ -118,12 +122,6 @@ public: void releaseAxis(Q3DValueAxis *axis); QList<Q3DValueAxis *> axes() const; - void setActiveDataProxy(QScatterDataProxy *proxy); - QScatterDataProxy *activeDataProxy() const; - void addDataProxy(QScatterDataProxy *proxy); - void releaseDataProxy(QScatterDataProxy *proxy); - QList<QScatterDataProxy *> dataProxies() const; - signals: void selectionModeChanged(QDataVis::SelectionFlags mode); void labelStyleChanged(QDataVis::LabelStyle style); diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp index ac451ad2..26f82611 100644 --- a/src/datavisualization/engine/q3dsurface.cpp +++ b/src/datavisualization/engine/q3dsurface.cpp @@ -21,6 +21,7 @@ #include "q3dvalueaxis.h" #include "qsurfacedataproxy.h" #include "q3dcamera.h" +#include "qsurface3dseries_p.h" #include <QMouseEvent> @@ -42,8 +43,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * 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. - * The Q3DSurface supports only a grid with fixed steps, so when setting ranges set a value that matches - * the grid step. To calculate the steps divide the whole data range with the number of segments. * * To rotate the graph, hold down the right mouse button and move the mouse. Zooming is done using mouse * wheel. Both assume the default input handler is in use. @@ -52,9 +51,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * These default axes can be modified via axis accessors, but as soon any axis is set explicitly * for the orientation, the default axis for that orientation is destroyed. * - * Data proxies work similarly: if no data proxy is set explicitly, Q3DSurface creates a default - * proxy. If any other proxy is set as active data proxy later, the default proxy and all data - * added to it is destroyed. + * Q3DSurface supports only single series at a time. * * \section1 How to construct a minimal Q3DSurface graph * @@ -135,6 +132,34 @@ Q3DSurface::~Q3DSurface() } /*! + * Adds the \a series to the graph. + * + * \note The surface graph currently supports only a single series at a time. + */ +void Q3DSurface::addSeries(QSurface3DSeries *series) +{ + d_ptr->m_shared->addSeries(series); +} + +/*! + * Removes the \a series from the graph. + */ +void Q3DSurface::removeSeries(QSurface3DSeries *series) +{ + d_ptr->m_shared->removeSeries(series); +} + +/*! + * \return list of series added to this graph. + * + * \note The surface graph currently supports only a single series at a time. + */ +QList<QSurface3DSeries *> Q3DSurface::seriesList() +{ + return d_ptr->m_shared->surfaceSeriesList(); +} + +/*! * \internal */ void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event) @@ -297,21 +322,6 @@ QDataVis::SelectionFlags Q3DSurface::selectionMode() const } /*! - * \property Q3DSurface::surfaceVisible - * - * Sets surface to \a visible. It is preset to \c true by default. - */ -void Q3DSurface::setSurfaceVisible(bool visible) -{ - d_ptr->m_shared->setSurfaceVisible(visible); -} - -bool Q3DSurface::isSurfaceVisible() const -{ - return d_ptr->m_shared->surfaceVisible(); -} - -/*! * \property Q3DSurface::surfaceGridEnabled * * Sets surface grid to \a enabled. It is preset to \c true by default. @@ -511,69 +521,6 @@ QList<Q3DValueAxis *> Q3DSurface::axes() const } /*! - * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of - * the \a proxy to this graph. - * - * If the \a proxy is null, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method. - * - * \sa addDataProxy(), releaseDataProxy() - */ -void Q3DSurface::setActiveDataProxy(QSurfaceDataProxy *proxy) -{ - d_ptr->m_shared->setActiveDataProxy(proxy); -} - -/*! - * \return active data proxy. - */ -QSurfaceDataProxy *Q3DSurface::activeDataProxy() const -{ - return static_cast<QSurfaceDataProxy *>(d_ptr->m_shared->activeDataProxy()); -} - -/*! - * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, - * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. - * The \a proxy must not be null or added to another graph. - * - * \sa releaseDataProxy(), setActiveDataProxy() - */ -void Q3DSurface::addDataProxy(QSurfaceDataProxy *proxy) -{ - d_ptr->m_shared->addDataProxy(proxy); -} - -/*! - * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. - * If the released \a proxy is in use, a new empty default proxy is created and taken to use. - * - * If the default \a proxy is released and added back later, it behaves as any other proxy would. - * - * \sa addDataProxy(), setActiveDataProxy() - */ -void Q3DSurface::releaseDataProxy(QSurfaceDataProxy *proxy) -{ - d_ptr->m_shared->releaseDataProxy(proxy); -} - -/*! - * \return list of all added data proxies. - * - * \sa addDataProxy() - */ -QList<QSurfaceDataProxy *> Q3DSurface::dataProxies() const -{ - QList<QSurfaceDataProxy *> retList; - QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); - foreach (QAbstractDataProxy *proxy, abstractList) - retList.append(static_cast<QSurfaceDataProxy *>(proxy)); - - return retList; -} - - -/*! * Modifies the current surface gradient. Sets gradient color to \a color at \a pos. */ void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h index 85b87589..29166362 100644 --- a/src/datavisualization/engine/q3dsurface.h +++ b/src/datavisualization/engine/q3dsurface.h @@ -29,7 +29,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DSurfacePrivate; class Q3DValueAxis; -class QSurfaceDataProxy; +class QSurface3DSeries; class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow { @@ -38,7 +38,6 @@ class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle NOTIFY labelStyleChanged) Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme NOTIFY themeChanged) Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) - Q_PROPERTY(bool surfaceVisible READ isSurfaceVisible WRITE setSurfaceVisible NOTIFY surfaceVisibleChanged) Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible NOTIFY gridVisibleChanged) Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible NOTIFY backgroundVisibleChanged) Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled NOTIFY smoothSurfaceEnabledChanged) @@ -53,8 +52,9 @@ public: explicit Q3DSurface(); ~Q3DSurface(); - void setSurfaceVisible(bool visible); - bool isSurfaceVisible() const; + void addSeries(QSurface3DSeries *series); + void removeSeries(QSurface3DSeries *series); + QList<QSurface3DSeries *> seriesList(); void setGridVisible(bool visible); bool isGridVisible() const; @@ -92,12 +92,6 @@ public: void releaseAxis(Q3DValueAxis *axis); QList<Q3DValueAxis *> axes() const; - void setActiveDataProxy(QSurfaceDataProxy *proxy); - QSurfaceDataProxy *activeDataProxy() const; - void addDataProxy(QSurfaceDataProxy *proxy); - void releaseDataProxy(QSurfaceDataProxy *proxy); - QList<QSurfaceDataProxy *> dataProxies() const; - void setFont(const QFont &font); QFont font() const; diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index a894101f..11a2d03f 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -22,6 +22,7 @@ #include "q3dabstractaxis_p.h" #include "q3dvalueaxis_p.h" #include "qscatterdataproxy_p.h" +#include "qscatter3dseries_p.h" #include <QMatrix4x4> #include <qmath.h> @@ -36,8 +37,6 @@ Scatter3DController::Scatter3DController(QRect boundRect) // Default object type; specific to scatter setObjectType(QDataVis::MeshStyleSpheres, false); - setActiveDataProxy(new QScatterDataProxy); - // Setting a null axis creates a new default axis according to orientation and graph type. // Note: These cannot be set in Abstract3DController constructor, as they will call virtual // functions implemented by subclasses. @@ -77,42 +76,47 @@ void Scatter3DController::synchDataToRenderer() m_renderer->updateSelectedItemIndex(m_selectedItemIndex); m_changeTracker.selectedItemIndexChanged = false; } - - if (m_isDataDirty) { - m_renderer->updateSeriesData(static_cast<QScatterDataProxy *>(m_data)); - m_isDataDirty = false; - } } -void Scatter3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +void Scatter3DController::addSeries(QAbstract3DSeries *series) { - // Setting null proxy indicates default proxy - if (!proxy) { - proxy = new QScatterDataProxy; - proxy->d_ptr->setDefaultProxy(true); + Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeScatter); + + bool firstAdded = !m_seriesList.size(); + + Abstract3DController::addSeries(series); + + if (firstAdded) { + adjustValueAxisRange(); + // TODO: Temp until selection by series is properly implemented + setSelectedItemIndex(noSelectionIndex()); } +} - Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter); +void Scatter3DController::removeSeries(QAbstract3DSeries *series) +{ + bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series); - Abstract3DController::setActiveDataProxy(proxy); + Abstract3DController::removeSeries(series); - QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_data); + if (firstRemoved) { + adjustValueAxisRange(); + // TODO: Temp until selection by series is properly implemented + setSelectedItemIndex(noSelectionIndex()); + } +} - QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset, - this, &Scatter3DController::handleArrayReset); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded, - this, &Scatter3DController::handleItemsAdded); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged, - this, &Scatter3DController::handleItemsChanged); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved, - this, &Scatter3DController::handleItemsRemoved); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted, - this, &Scatter3DController::handleItemsInserted); +QList<QScatter3DSeries *> Scatter3DController::scatterSeriesList() +{ + QList<QAbstract3DSeries *> abstractSeriesList = seriesList(); + QList<QScatter3DSeries *> scatterSeriesList; + foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) { + QScatter3DSeries *scatterSeries = qobject_cast<QScatter3DSeries *>(abstractSeries); + if (scatterSeries) + scatterSeriesList.append(scatterSeries); + } - adjustValueAxisRange(); - setSelectedItemIndex(noSelectionIndex()); - m_isDataDirty = true; - emitNeedRender(); + return scatterSeriesList; } void Scatter3DController::handleArrayReset() @@ -150,7 +154,8 @@ void Scatter3DController::handleItemsRemoved(int startIndex, int count) // TODO should dirty only affected values? adjustValueAxisRange(); m_isDataDirty = true; - if (startIndex >= static_cast<QScatterDataProxy *>(m_data)->itemCount()) + QScatterDataProxy *proxy = qobject_cast<QScatterDataProxy *>(sender()); + if (!proxy || startIndex >= proxy->itemCount()) setSelectedItemIndex(noSelectionIndex()); emitNeedRender(); } @@ -243,8 +248,9 @@ void Scatter3DController::adjustValueAxisRange() { QVector3D minLimits; QVector3D maxLimits; - if (m_data) { - static_cast<QScatterDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits); + if (m_seriesList.size()) { + const QScatterDataProxy *proxy = static_cast<QScatter3DSeries *>(m_seriesList.at(0))->dataProxy(); + proxy->dptrc()->limitValues(minLimits, maxLimits); Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX); if (valueAxis && valueAxis->isAutoAdjustRange()) { if (minLimits.x() != maxLimits.x()) diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h index d593d010..a75b61ac 100644 --- a/src/datavisualization/engine/scatter3dcontroller_p.h +++ b/src/datavisualization/engine/scatter3dcontroller_p.h @@ -38,6 +38,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Scatter3DRenderer; class QScatterDataProxy; +class QScatter3DSeries; struct Scatter3DChangeBitField { bool selectedItemIndexChanged : 1; @@ -75,10 +76,12 @@ public: int selectedItemIndex() const; static inline int noSelectionIndex() { return -1; } - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); - void synchDataToRenderer(); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + virtual QList<QScatter3DSeries *> scatterSeriesList(); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); virtual void handleAxisRangeChangedBySender(QObject *sender); diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 449809c8..e87c1435 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -25,6 +25,7 @@ #include "texturehelper_p.h" #include "utils_p.h" #include "q3dlight.h" +#include "qscatter3dseries_p.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -141,15 +142,14 @@ void Scatter3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -//void Scatter3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) -void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) +void Scatter3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) { - //QList<QScatter3DSeries *> visibleSeries; - //foreach (QAbstract3DSeries *current, seriesList) { - // if (current->isVisible()) - // visibleSeries.append(static_cast<QScatter3DSeries *>(current)); - //} - int seriesCount = 3;//visibleSeries.size(); // TODO: Use a number for testing until QTRD-2548 is done + QList<QScatter3DSeries *> visibleSeries; + foreach (QAbstract3DSeries *current, seriesList) { + if (current->isVisible()) + visibleSeries.append(static_cast<QScatter3DSeries *>(current)); + } + int seriesCount = visibleSeries.size(); calculateSceneScalingFactors(); float minX = float(m_axisCacheX.min()); float maxX = float(m_axisCacheX.max()); @@ -165,7 +165,7 @@ void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) } for (int series = 0; series < m_seriesCount; series++) { - //QScatterDataProxy *dataProxy = visibleSeries.at(series)->dataProxy(); + QScatterDataProxy *dataProxy = visibleSeries.at(series)->dataProxy(); const QScatterDataArray &dataArray = *dataProxy->array(); int dataSize = dataArray.size(); totalDataSize += dataSize; @@ -179,9 +179,7 @@ void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) if ((dotPos.x() >= minX && dotPos.x() <= maxX ) && (dotPos.y() >= minY && dotPos.y() <= maxY) && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) { - //m_renderingArrays[series][i].setPosition(dotPos); - // TODO: Hack different values for sets until QTRD-2548 - m_renderingArrays[series][i].setPosition(dotPos * (1.0f - (series * 0.25f))); + m_renderingArrays[series][i].setPosition(dotPos); m_renderingArrays[series][i].setVisible(true); calculateTranslation(m_renderingArrays[series][i]); } else { @@ -192,8 +190,7 @@ void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) m_dotSizeScale = (GLfloat)qBound(0.01, (2.0 / qSqrt((qreal)totalDataSize)), 0.1); m_selectedItem = 0; - Abstract3DRenderer::updateDataModel(dataProxy); - //Abstract3DRenderer::updateSeriesData(seriesList); + Abstract3DRenderer::updateSeriesData(seriesList); } void Scatter3DRenderer::updateScene(Q3DScene *scene) @@ -514,7 +511,6 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) glEnable(GL_DITHER); // Read color under cursor - // TODO: Can't call back to controller here! (QTRD-2216) QVector3D clickedColor = Utils::getSelection(m_inputPosition, m_cachedBoundingRect.height()); if (m_clickedColor == invalidColorVector) { @@ -585,7 +581,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) int dotNo = 0; for (int series = 0; series < m_seriesCount; series++) { - // TODO: Color per series. Let's just hack it while testing with 2 series + // TODO: Color per series. Let's just hack it while testing with 2 series QTRD-2557 QVector3D baseColor = Utils::vectorFromColor(m_cachedObjectColor) * (series + 0.25f); QVector3D dotColor = baseColor; diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index c6a627d0..4050f89b 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -96,8 +96,7 @@ public: explicit Scatter3DRenderer(Scatter3DController *controller); ~Scatter3DRenderer(); - //void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); - void updateSeriesData(QScatterDataProxy *dataProxy); + void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); void updateScene(Q3DScene *scene); void updateInputState(QDataVis::InputState state); diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 9e82017a..060e688f 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -23,6 +23,7 @@ #include "q3dvalueaxis_p.h" #include "q3dcategoryaxis.h" #include "qsurfacedataproxy_p.h" +#include "qsurface3dseries_p.h" #include <QMatrix4x4> @@ -38,8 +39,6 @@ Surface3DController::Surface3DController(QRect rect) m_isSurfaceGridEnabled(true), m_selectedPoint(noSelectionPoint()) { - setActiveDataProxy(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 // functions implemented by subclasses. @@ -73,11 +72,16 @@ void Surface3DController::initializeOpenGL() void Surface3DController::synchDataToRenderer() { - Abstract3DController::synchDataToRenderer(); - if (!isInitialized()) return; + if (m_changeTracker.surfaceGridChanged) { + m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled); + m_changeTracker.surfaceGridChanged = false; + } + + Abstract3DController::synchDataToRenderer(); + // Notify changes to renderer if (m_changeTracker.gradientColorChanged) { m_renderer->updateSurfaceGradient(m_userDefinedGradient); @@ -92,25 +96,10 @@ void Surface3DController::synchDataToRenderer() emit smoothSurfaceEnabledChanged(m_isSmoothSurfaceEnabled); } - if (m_changeTracker.surfaceVisibilityChanged) { - m_renderer->updateSurfaceVisibilityStatus(m_isSurfaceEnabled); - m_changeTracker.surfaceVisibilityChanged = false; - } - - if (m_changeTracker.surfaceGridChanged) { - m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled); - m_changeTracker.surfaceGridChanged = false; - } - if (m_changeTracker.selectedPointChanged) { m_renderer->updateSelectedPoint(m_selectedPoint); m_changeTracker.selectedPointChanged = false; } - - if (m_isDataDirty) { - m_renderer->updateDataModel(static_cast<QSurfaceDataProxy *>(m_data)); - m_isDataDirty = false; - } } void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) @@ -135,34 +124,60 @@ QPoint Surface3DController::noSelectionPoint() return noSelectionPoint; } -void Surface3DController::setSmoothSurface(bool enable) +void Surface3DController::addSeries(QAbstract3DSeries *series) { - if (enable != m_isSmoothSurfaceEnabled) { - m_isSmoothSurfaceEnabled = enable; - m_changeTracker.smoothStatusChanged = true; - emit smoothSurfaceEnabledChanged(enable); - emitNeedRender(); + Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface); + + if (!m_seriesList.size()) { + Abstract3DController::addSeries(series); + + adjustValueAxisRange(); + + // TODO: Temp until selection by series is properly implemented + setSelectedPoint(noSelectionPoint()); + } else { + qWarning("Surface graph only supports a single series."); } } -bool Surface3DController::smoothSurface() +void Surface3DController::removeSeries(QAbstract3DSeries *series) { - return m_isSmoothSurfaceEnabled; + if (series && series->d_ptr->m_controller == this) { + Abstract3DController::removeSeries(series); + + adjustValueAxisRange(); + + // TODO: Temp until selection by series is properly implemented + setSelectedPoint(noSelectionPoint()); + } +} + +QList<QSurface3DSeries *> Surface3DController::surfaceSeriesList() +{ + QList<QAbstract3DSeries *> abstractSeriesList = seriesList(); + QList<QSurface3DSeries *> surfaceSeriesList; + foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) { + QSurface3DSeries *surfaceSeries = qobject_cast<QSurface3DSeries *>(abstractSeries); + if (surfaceSeries) + surfaceSeriesList.append(surfaceSeries); + } + + return surfaceSeriesList; } -void Surface3DController::setSurfaceVisible(bool visible) +void Surface3DController::setSmoothSurface(bool enable) { - if (visible != m_isSurfaceEnabled) { - m_isSurfaceEnabled = visible; - m_changeTracker.surfaceVisibilityChanged = true; - emit surfaceVisibleChanged(visible); + if (enable != m_isSmoothSurfaceEnabled) { + m_isSmoothSurfaceEnabled = enable; + m_changeTracker.smoothStatusChanged = true; + emit smoothSurfaceEnabledChanged(enable); emitNeedRender(); } } -bool Surface3DController::surfaceVisible() const +bool Surface3DController::smoothSurface() { - return m_isSurfaceEnabled; + return m_isSmoothSurfaceEnabled; } void Surface3DController::setSurfaceGrid(bool enable) @@ -172,6 +187,7 @@ void Surface3DController::setSurfaceGrid(bool enable) m_changeTracker.surfaceGridChanged = true; emit surfaceGridEnabledChanged(enable); emitNeedRender(); + m_isDataDirty = true; } } @@ -230,7 +246,15 @@ void Surface3DController::setSelectedPoint(const QPoint &position) // If the selection targets non-existent point, clear selection instead. QPoint pos = position; - const QSurfaceDataProxy *proxy = static_cast<const QSurfaceDataProxy *>(m_data); + // TODO: Selection needs to be refactored to be handled by series + const QSurfaceDataProxy *proxy = 0; + if (m_seriesList.size()) { + QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_seriesList.at(0)); + proxy = static_cast<QSurfaceDataProxy *>(series->dataProxy()); + } else { + return; + } + if (pos != noSelectionPoint()) { int maxRow = proxy->rowCount() - 1; int maxCol = proxy->columnCount() - 1; @@ -284,32 +308,6 @@ QPoint Surface3DController::selectedPoint() const return m_selectedPoint; } -void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy) -{ - // Setting null proxy indicates default proxy - if (!proxy) { - proxy = new QSurfaceDataProxy; - proxy->d_ptr->setDefaultProxy(true); - } - - Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface); - - Abstract3DController::setActiveDataProxy(proxy); - - QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_data); - - QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, - this, &Surface3DController::handleArrayReset); - - adjustValueAxisRange(); - - // Always clear selection on proxy change - setSelectedPoint(noSelectionPoint()); - - m_isDataDirty = true; - emitNeedRender(); -} - void Surface3DController::handleArrayReset() { adjustValueAxisRange(); @@ -334,10 +332,12 @@ void Surface3DController::handleRequestSmoothSurface(bool enable) void Surface3DController::adjustValueAxisRange() { - if (m_data) { + if (m_seriesList.size()) { QVector3D minLimits; QVector3D maxLimits; - static_cast<QSurfaceDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits); + QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_seriesList.at(0)); + static_cast<QSurfaceDataProxy *>(series->dataProxy())->dptrc()->limitValues(minLimits, + maxLimits); Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX); if (valueAxis && valueAxis->isAutoAdjustRange()) { if (minLimits.x() != maxLimits.x()) diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index f9617ad4..09c0ca5b 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -37,18 +37,17 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Surface3DRenderer; +class QSurface3DSeries; struct Surface3DChangeBitField { bool gradientColorChanged : 1; bool smoothStatusChanged : 1; - bool surfaceVisibilityChanged : 1; bool surfaceGridChanged : 1; bool selectedPointChanged : 1; Surface3DChangeBitField() : gradientColorChanged(true), smoothStatusChanged(true), - surfaceVisibilityChanged(true), surfaceGridChanged(true), selectedPointChanged(true) { @@ -75,9 +74,6 @@ public: void initializeOpenGL(); virtual void synchDataToRenderer(); - void setSurfaceVisible(bool visible); - bool surfaceVisible() const; - void setSmoothSurface(bool enable); bool smoothSurface(); @@ -94,13 +90,15 @@ public: void setSelectedPoint(const QPoint &position); QPoint selectedPoint() const; - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); virtual void handleAxisRangeChangedBySender(QObject *sender); static QPoint noSelectionPoint(); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + virtual QList<QSurface3DSeries *> surfaceSeriesList(); + public slots: void handleArrayReset(); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 8bb16f86..3a6e3560 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -29,6 +29,7 @@ #include "utils_p.h" #include "drawer_p.h" #include "q3dlight.h" +#include "qsurface3dseries_p.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -101,7 +102,7 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_shadowQualityToShader(33.3f), m_cachedSmoothSurface(true), m_flatSupported(true), - m_cachedSurfaceOn(true), + m_cachedSurfaceVisible(true), m_cachedSurfaceGridOn(true), m_selectionPointer(0), m_selectionActive(false), @@ -196,15 +197,25 @@ void Surface3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) +void Surface3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) { - calculateSceneScalingFactors(); + // Surface only supports single series for now, so we are only interested in the first series + const QSurfaceDataArray *array = 0; + if (seriesList.size()) { + QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(seriesList.at(0)); + m_cachedSurfaceVisible = firstSeries->isVisible(); // TODO: To series visuals update? + if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) { + QSurfaceDataProxy *dataProxy = firstSeries->dataProxy(); + if (dataProxy) + array = dataProxy->array(); + } + } - const QSurfaceDataArray &array = *dataProxy->array(); + calculateSceneScalingFactors(); // Need minimum of 2x2 array to draw a surface - if (array.size() >= 2 && array.at(0)->size() >= 2) { - QRect sampleSpace = calculateSampleRect(array); + if (array && array->size() >= 2 && array->at(0)->size() >= 2) { + QRect sampleSpace = calculateSampleRect(*array); bool dimensionChanged = false; if (m_sampleSpace != sampleSpace) { @@ -225,7 +236,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) } for (int i = 0; i < sampleSpace.height(); i++) { for (int j = 0; j < sampleSpace.width(); j++) - (*(m_dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(j + sampleSpace.x()); + (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(j + sampleSpace.x()); } if (m_dataArray.size() > 0) { @@ -258,7 +269,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) m_selectionDirty = true; - Abstract3DRenderer::updateDataModel(dataProxy); + Abstract3DRenderer::updateSeriesData(seriesList); } void Surface3DRenderer::updateSliceDataModel(const QPoint &point) @@ -515,7 +526,7 @@ void Surface3DRenderer::drawSlicedScene() MVPMatrix = projectionViewMatrix * modelMatrix; - if (m_cachedSurfaceOn) { + if (m_cachedSurfaceVisible) { if (m_cachedSurfaceGridOn) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.5f, 1.0f); @@ -784,7 +795,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Draw depth buffer #if !defined(QT_OPENGL_ES_2) GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f; - if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj && m_cachedSurfaceOn) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj && m_cachedSurfaceVisible) { // Render scene into a depth texture for using with shadow mapping // Enable drawing to depth framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -899,7 +910,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Draw selection buffer if (!m_cachedIsSlicingActivated && m_surfaceObj && m_inputState == QDataVis::InputStateOnScene - && m_cachedSelectionMode > QDataVis::SelectionNone) { + && m_cachedSelectionMode > QDataVis::SelectionNone + && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn)) { m_selectionShader->bind(); glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used @@ -970,7 +982,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) MVPMatrix = projectionViewMatrix * modelMatrix; #endif - if (m_cachedSurfaceOn) { + if (m_cachedSurfaceVisible) { // Set shader bindings m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos); m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix); @@ -1063,7 +1075,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_cachedTheme.m_ambientStrength * 2.0f); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_cachedSurfaceOn) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_cachedSurfaceVisible) { // Set shadow shader bindings QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), @@ -1781,11 +1793,6 @@ void Surface3DRenderer::updateSelectedPoint(const QPoint &position) m_selectionDirty = true; } -void Surface3DRenderer::updateSurfaceVisibilityStatus(bool visible) -{ - m_cachedSurfaceOn = visible; -} - void Surface3DRenderer::updateSurfaceGridStatus(bool enable) { m_cachedSurfaceGridOn = enable; diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 0cff19cd..2c5f84fb 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -111,7 +111,7 @@ private: GLfloat m_shadowQualityToShader; bool m_cachedSmoothSurface; bool m_flatSupported; - bool m_cachedSurfaceOn; + bool m_cachedSurfaceVisible; bool m_cachedSurfaceGridOn; SelectionPointer *m_selectionPointer; bool m_selectionActive; @@ -132,11 +132,10 @@ public: explicit Surface3DRenderer(Surface3DController *controller); ~Surface3DRenderer(); - void updateDataModel(QSurfaceDataProxy *dataProxy); + void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); void updateScene(Q3DScene *scene); void updateInputState(QDataVis::InputState state); bool updateSmoothStatus(bool enable); - void updateSurfaceVisibilityStatus(bool visible); void updateSurfaceGridStatus(bool enable); void updateSurfaceGradient(const QLinearGradient &gradient); void updateSlicingActive(bool isSlicing); |