diff options
48 files changed, 1659 insertions, 1483 deletions
diff --git a/examples/barchart/main.cpp b/examples/barchart/main.cpp index 827fdcf4..c55a13a6 100644 --- a/examples/barchart/main.cpp +++ b/examples/barchart/main.cpp @@ -39,7 +39,6 @@ ****************************************************************************/ #include "q3dbars.h" -#include "qdataset.h" #include "qcategoryaxis.h" #include "qitemmodelbardataproxy.h" diff --git a/examples/mapdata/mapdata.cpp b/examples/mapdata/mapdata.cpp index 0461dc56..6c7333b2 100644 --- a/examples/mapdata/mapdata.cpp +++ b/examples/mapdata/mapdata.cpp @@ -39,6 +39,7 @@ ****************************************************************************/ #include "mapdata.h" +#include "qmapdataproxy.h" #include <QImage> #include <QFile> @@ -64,6 +65,8 @@ MapsModifier::MapsModifier(Q3DMaps *maps) m_chart->setBarSpecs(m_barSpecs, Q3DMaps::AdjustAll); m_chart->setMeshFileName(QStringLiteral(":/meshes/weirdthing")); #endif + QMapDataProxy *proxy = new QMapDataProxy; + m_chart->setDataProxy(proxy); } MapsModifier::~MapsModifier() @@ -78,132 +81,156 @@ void MapsModifier::start() void MapsModifier::addData() { - QDataItem *item; - item = new QDataItem(); + QMapDataArray *dataArray = new QMapDataArray; + QMapDataItem *item; + item = new QMapDataItem(); item->setValue(191050); - item->setLabel("Oulu", true); - item->setPosition(QPoint(963, 1604)); - m_chart->addDataItem(item); + item->setLabel("Oulu"); + item->setMapPosition(QPointF(963, 1604)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(22274); - item->setLabel("Kemi", true); - item->setPosition(QPoint(857, 1383)); - m_chart->addDataItem(item); + item->setLabel("Kemi"); + item->setMapPosition(QPointF(857, 1383)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(60887); - item->setLabel("Rovaniemi", true); - item->setPosition(QPoint(1061, 1119)); - m_chart->addDataItem(item); + item->setLabel("Rovaniemi"); + item->setMapPosition(QPointF(1061, 1119)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(16176); - item->setLabel("Kuusamo", true); - item->setPosition(QPoint(1459, 1284)); - m_chart->addDataItem(item); + item->setLabel("Kuusamo"); + item->setMapPosition(QPointF(1459, 1284)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(3998); - item->setLabel("Ivalo", true); - item->setPosition(QPoint(1239, 474)); - m_chart->addDataItem(item); + item->setLabel("Ivalo"); + item->setMapPosition(QPointF(1239, 474)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(37978); - item->setLabel("Kajaani", true); - item->setPosition(QPoint(1285, 1859)); - m_chart->addDataItem(item); + item->setLabel("Kajaani"); + item->setMapPosition(QPointF(1285, 1859)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(46809); - item->setLabel("Kokkola", true); - item->setPosition(QPoint(580, 1973)); - m_chart->addDataItem(item); + item->setLabel("Kokkola"); + item->setMapPosition(QPointF(580, 1973)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(105236); - item->setLabel("Kuopio", true); - item->setPosition(QPoint(1292, 2283)); - m_chart->addDataItem(item); + item->setLabel("Kuopio"); + item->setMapPosition(QPointF(1292, 2283)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(133557); - item->setLabel("Jyväskylä", true); - item->setPosition(QPoint(991, 2496)); - m_chart->addDataItem(item); + item->setLabel("Jyväskylä"); + item->setMapPosition(QPointF(991, 2496)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(65771); - item->setLabel("Vaasa", true); - item->setPosition(QPoint(441, 2184)); - m_chart->addDataItem(item); + item->setLabel("Vaasa"); + item->setMapPosition(QPointF(441, 2184)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(217603); - item->setLabel("Tampere", true); - item->setPosition(QPoint(686, 2656)); - m_chart->addDataItem(item); + item->setLabel("Tampere"); + item->setMapPosition(QPointF(686, 2656)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(180350); - item->setLabel("Turku", true); - item->setPosition(QPoint(430, 3046)); - m_chart->addDataItem(item); + item->setLabel("Turku"); + item->setMapPosition(QPointF(430, 3046)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(72400); - item->setLabel("Lappeenranta", true); - item->setPosition(QPoint(1365, 2852)); - m_chart->addDataItem(item); + item->setLabel("Lappeenranta"); + item->setMapPosition(QPoint(1365, 2852)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(14754); - item->setLabel("Tammisaari", true); - item->setPosition(QPoint(605, 3215)); - m_chart->addDataItem(item); + item->setLabel("Tammisaari"); + item->setMapPosition(QPointF(605, 3215)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(1879); - item->setLabel("Enontekiö", true); - item->setPosition(QPoint(752, 556)); - m_chart->addDataItem(item); + item->setLabel("Enontekiö"); + item->setMapPosition(QPointF(752, 556)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(36624); - item->setLabel("Savonlinna", true); - item->setPosition(QPoint(1445, 2586)); - m_chart->addDataItem(item); + item->setLabel("Savonlinna"); + item->setMapPosition(QPointF(1445, 2586)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(605022); - item->setLabel("Helsinki", true); - item->setPosition(QPoint(822, 3130)); - m_chart->addDataItem(item); + item->setLabel("Helsinki"); + item->setMapPosition(QPointF(822, 3130)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(54887); - item->setLabel("Kotka", true); - item->setPosition(QPoint(1162, 3051)); - m_chart->addDataItem(item); + item->setLabel("Kotka"); + item->setMapPosition(QPointF(1162, 3051)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(11372); - item->setLabel("Maarianhamina", true); - item->setPosition(QPoint(56, 3101)); - m_chart->addDataItem(item); + item->setLabel("Maarianhamina"); + item->setMapPosition(QPointF(56, 3101)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(9266); - item->setLabel("Hanko", true); - item->setPosition(QPoint(527, 3228)); - m_chart->addDataItem(item); + item->setLabel("Hanko"); + item->setMapPosition(QPointF(527, 3228)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(1287); - item->setLabel("Utsjoki", true); - item->setPosition(QPoint(1180, 72)); - m_chart->addDataItem(item); + item->setLabel("Utsjoki"); + item->setMapPosition(QPointF(1180, 72)); + dataArray->append(*item); + delete item; + + static_cast<QMapDataProxy *>(m_chart->dataProxy())->resetArray(dataArray); } void MapsModifier::changeStyle() diff --git a/examples/mapdata/mapdata.h b/examples/mapdata/mapdata.h index ea25c635..03bb86a6 100644 --- a/examples/mapdata/mapdata.h +++ b/examples/mapdata/mapdata.h @@ -42,7 +42,6 @@ #define CHARTMODIFIER_H #include "q3dmaps.h" -#include "qdataset.h" #include <QFont> #include <QDebug> diff --git a/examples/qmlmaps/qml/qmlmaps/main.qml b/examples/qmlmaps/qml/qmlmaps/main.qml index cfa98d3a..d546d3a5 100644 --- a/examples/qmlmaps/qml/qmlmaps/main.qml +++ b/examples/qmlmaps/qml/qmlmaps/main.qml @@ -41,29 +41,20 @@ Item { visible: false } - DataItem { - id: testitem1 - label: "dB" - value: 76 - position: "95.0, 490.0" + MapDataMapping { + id: mapMapping + labelRole: "label" + valueRole: "value" + xPosRole: "xPos" + yPosRole: "yPos" } - DataItem { - id: testitem2 - label: "dB" - value: 88 - position: "185.0, 105.0" - } - DataItem { - id: testitem3 - label: "dB" - value: 85 - position: "700.0, 465.0" - } - DataItem { - id: testitem4 - label: "dB" - value: 92 - position: "505.0, 225.0" + + ListModel { + id: dataModel + ListElement{ label: "dB"; value: 76; xPos: 95.0; yPos: 490.0 } + ListElement{ label: "dB"; value: 88; xPos: 185.0; yPos: 105.0 } + ListElement{ label: "dB"; value: 85; xPos: 700.0; yPos: 465.0 } + ListElement{ label: "dB"; value: 92; xPos: 505.0; yPos: 225.0 } } Maps3D { @@ -71,6 +62,7 @@ Item { width: dataView.width height: dataView.height fontSize: 300.0 + mapping: mapMapping Component.onCompleted: { console.log("testmap complete"); @@ -84,10 +76,7 @@ Item { shadowQuality = Maps3D.ShadowNone selectionMode = Maps3D.ModeBar labelTransparency = Maps3D.TransparencyNoBackground//.TransparencyFromTheme - addDataItem(testitem1); - addDataItem(testitem2); - addDataItem(testitem3); - addDataItem(testitem4); + data = dataModel } } } diff --git a/examples/spectrum/spectrumapp/main.cpp b/examples/spectrum/spectrumapp/main.cpp index 2fa0be8f..11f89bc3 100644 --- a/examples/spectrum/spectrumapp/main.cpp +++ b/examples/spectrum/spectrumapp/main.cpp @@ -41,7 +41,7 @@ #include "q3dbars.h" #include "engine.h" #include "utils.h" -#include "qolddataproxy.h" +#include "qbardataproxy.h" #include <QGuiApplication> #include <QAudio> @@ -120,7 +120,7 @@ MainApp::MainApp(Q3DBars *window) m_restartTimer->setSingleShot(true); QObject::connect(m_restartTimer, &QTimer::timeout, this, &MainApp::restart); - QOldDataProxy *proxy = new QOldDataProxy; + QBarDataProxy *proxy = new QBarDataProxy; m_chart->setDataProxy(proxy); } @@ -145,22 +145,20 @@ void MainApp::spectrumChanged(qint64 position, qint64 length, const FrequencySpe Q_UNUSED(position); Q_UNUSED(length); //qDebug() << "updating bar values" << position << length; - QVector<float> data; + QBarDataRow *data = new QBarDataRow(SpectrumNumBands); for (int bar = 0; bar < SpectrumNumBands; bar++) { // init data set - data.append(0.0f); + (*data)[bar].setValue(qreal(0.0)); } FrequencySpectrum::const_iterator i = spectrum.begin(); const FrequencySpectrum::const_iterator end = spectrum.end(); for ( ; i != end; ++i) { const FrequencySpectrum::Element e = *i; if (e.frequency >= m_lowFreq && e.frequency < m_highFreq) { - data.replace(barIndex(e.frequency) - , qMax(data.at(barIndex(e.frequency)), (float)e.amplitude)); + (*data)[barIndex(e.frequency)].setValue(qMax(data->at(barIndex(e.frequency)).value(), qreal(e.amplitude))); } } - if (data.size() > 0) - static_cast<QOldDataProxy *>(m_chart->dataProxy())->addDataRow(data); + static_cast<QBarDataProxy *>(m_chart->dataProxy())->insertRow(0, data); } void MainApp::stateChanged(QAudio::Mode mode, QAudio::State state) diff --git a/examples/widget/chart.cpp b/examples/widget/chart.cpp index 39e19d4c..9db01170 100644 --- a/examples/widget/chart.cpp +++ b/examples/widget/chart.cpp @@ -114,8 +114,11 @@ void ChartModifier::restart(bool dynamicData) m_chart->columnAxis()->setTitle("Generic Column"); m_chart->valueAxis()->setTitle("Generic Value"); - m_chart->rowAxis()->setLabels(QStringList()); - m_chart->columnAxis()->setLabels(m_genericColumnLabels); + if (m_chart->rowAxis()->labels().size() < m_rowCount) + m_chart->rowAxis()->setLabels(m_genericRowLabels.mid(0, m_rowCount)); + + if (m_chart->columnAxis()->labels().size() < m_rowCount) + m_chart->columnAxis()->setLabels(m_genericRowLabels.mid(0, m_columnCount)); } } @@ -189,15 +192,12 @@ void ChartModifier::addRow() //(*dataRow)[i].setValue(i + m_chart->dataProxy()->rowCount()); } m_chart->dataProxy()->insertRow(0, dataRow); - if (m_chart->dataProxy()->rowCount() <= m_rowCount) - m_chart->rowAxis()->setLabels(m_genericRowLabels.mid(0, m_chart->dataProxy()->rowCount())); } void ChartModifier::addRows() { QTime timer; timer.start(); - int oldCount = m_chart->dataProxy()->rowCount(); QBarDataArray *dataArray = new QBarDataArray(); for (int i = 0; i < m_rowCount; i++) { QBarDataRow *dataRow = new QBarDataRow(m_columnCount); @@ -207,9 +207,6 @@ void ChartModifier::addRows() } m_chart->dataProxy()->insertRows(0, dataArray); qDebug() << "Added" << m_rowCount << "rows, time:" << timer.elapsed(); - if (oldCount < m_rowCount) - m_chart->rowAxis()->setLabels(m_genericRowLabels.mid(0, m_rowCount)); - qDebug() << "... Including Label creation, time:" << timer.elapsed(); } void ChartModifier::changeStyle() @@ -393,10 +390,14 @@ void ChartModifier::setSampleCountX(int samples) { m_columnCount = samples; m_chart->setupSampleSpace(m_rowCount, m_columnCount); + if (m_chart->columnAxis()->labels().size() < m_columnCount) + m_chart->columnAxis()->setLabels(m_genericRowLabels.mid(0, m_columnCount)); } void ChartModifier::setSampleCountZ(int samples) { m_rowCount = samples; m_chart->setupSampleSpace(m_rowCount, m_columnCount); + if (m_chart->rowAxis()->labels().size() < m_rowCount) + m_chart->rowAxis()->setLabels(m_genericRowLabels.mid(0, m_rowCount)); } diff --git a/src/datavis3d/data/barrenderitem.cpp b/src/datavis3d/data/barrenderitem.cpp index f17a5d3a..97f561c8 100644 --- a/src/datavis3d/data/barrenderitem.cpp +++ b/src/datavis3d/data/barrenderitem.cpp @@ -61,7 +61,7 @@ void BarRenderItem::formatLabel() QString numStr; numStr.setNum(m_value); // TODO actually format instead of just prepending the value - m_label.clear(); + m_label.clear(); // Just in case m_label.append(numStr); m_label.append(m_renderer->m_dataProxy->itemLabelFormat()); } diff --git a/src/datavis3d/data/barrenderitem_p.h b/src/datavis3d/data/barrenderitem_p.h index e576cbb7..00c12206 100644 --- a/src/datavis3d/data/barrenderitem_p.h +++ b/src/datavis3d/data/barrenderitem_p.h @@ -65,16 +65,16 @@ public: virtual ~BarRenderItem(); // Position relative to data window (for bar label generation) - inline const QPoint &position() { return m_position; } inline void setPosition(const QPoint &pos) { m_position = pos; } + inline const QPoint &position() const { return m_position; } // Actual cached data value of the bar (needed to trigger label reformats) inline void setValue(qreal value); - inline qreal value() { return m_value; } + inline qreal value() const { return m_value; } // Normalized bar height inline void setHeight(GLfloat height) { m_height = height; } - inline GLfloat height() { return m_height; } + inline GLfloat height() const { return m_height; } // TODO should be in abstract, but currently there is no abstract renderer inline void setRenderer(Bars3dRenderer *renderer) { m_renderer = renderer; } diff --git a/src/datavis3d/data/data.pri b/src/datavis3d/data/data.pri index 1cf90111..bd922e00 100644 --- a/src/datavis3d/data/data.pri +++ b/src/datavis3d/data/data.pri @@ -1,10 +1,4 @@ HEADERS += \ - $$PWD/qdataitem.h \ - $$PWD/qdataitem_p.h \ - $$PWD/qdatarow.h \ - $$PWD/qdatarow_p.h \ - $$PWD/qdataset.h \ - $$PWD/qdataset_p.h \ $$PWD/labelitem_p.h \ $$PWD/qabstractdataproxy.h \ $$PWD/qabstractdataproxy_p.h \ @@ -14,7 +8,6 @@ HEADERS += \ $$PWD/barrenderitem_p.h \ $$PWD/qbardataitem.h \ $$PWD/qbardataitem_p.h \ - $$PWD/qolddataproxy.h \ $$PWD/qvariantdataset_p.h \ $$PWD/qvariantdataset.h \ $$PWD/qvariantbardataproxy_p.h \ @@ -24,22 +17,31 @@ HEADERS += \ $$PWD/qitemmodelbardatamapping.h \ $$PWD/qitemmodelbardatamapping_p.h \ $$PWD/qitemmodelbardataproxy_p.h \ - $$PWD/qitemmodelbardataproxy.h - + $$PWD/qitemmodelbardataproxy.h \ + $$PWD/maprenderitem_p.h \ + $$PWD/qmapdataitem.h \ + $$PWD/qmapdataitem_p.h \ + $$PWD/qmapdataproxy.h \ + $$PWD/qmapdataproxy_p.h \ + $$PWD/qitemmodelmapdatamapping.h \ + $$PWD/qitemmodelmapdatamapping_p.h \ + $$PWD/qitemmodelmapdataproxy.h \ + $$PWD/qitemmodelmapdataproxy_p.h SOURCES += \ - $$PWD/qdataitem.cpp \ - $$PWD/qdatarow.cpp \ - $$PWD/qdataset.cpp \ $$PWD/labelitem.cpp \ $$PWD/qabstractdataproxy.cpp \ $$PWD/qbardataproxy.cpp \ $$PWD/abstractrenderitem.cpp \ $$PWD/barrenderitem.cpp \ $$PWD/qbardataitem.cpp \ - $$PWD/qolddataproxy.cpp \ $$PWD/qvariantdataset.cpp \ $$PWD/qvariantbardataproxy.cpp \ $$PWD/qvariantbardatamapping.cpp \ $$PWD/qitemmodelbardatamapping.cpp \ - $$PWD/qitemmodelbardataproxy.cpp + $$PWD/qitemmodelbardataproxy.cpp \ + $$PWD/maprenderitem.cpp \ + $$PWD/qmapdataitem.cpp \ + $$PWD/qmapdataproxy.cpp \ + $$PWD/qitemmodelmapdatamapping.cpp \ + $$PWD/qitemmodelmapdataproxy.cpp diff --git a/src/datavis3d/data/maprenderitem.cpp b/src/datavis3d/data/maprenderitem.cpp new file mode 100644 index 00000000..cff31c5c --- /dev/null +++ b/src/datavis3d/data/maprenderitem.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "maprenderitem_p.h" +#include "maps3drenderer_p.h" // TODO remove when maps refactored +#include "maps3dcontroller_p.h" // TODO should be renderer +#include "qmapdataproxy.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +MapRenderItem::MapRenderItem() + : BarRenderItem() +{ +} + +MapRenderItem::~MapRenderItem() +{ +} + +void MapRenderItem::formatLabel() +{ + // TODO The label format specified in proxy should probably have additional custom formatting + // TODO specifiers in addition to standard printf specifiers for placement of item labels + // TODO and selection data (like row/column in bar selection) + + // Format the string on first access + QString numStr; + numStr.setNum(m_value); + // TODO actually format instead of just prepending the value + m_label.clear(); // Just in case + m_label.append(m_itemLabel); + m_label.append(QStringLiteral(" ")); + m_label.append(numStr); + m_label.append(m_renderer->dataProxy()->itemLabelFormat()); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qdataitem_p.h b/src/datavis3d/data/maprenderitem_p.h index 8b5d6af9..0d5521a4 100644 --- a/src/datavis3d/data/qdataitem_p.h +++ b/src/datavis3d/data/maprenderitem_p.h @@ -49,47 +49,44 @@ // // We mean it. -#ifndef QDATAITEM_P_H -#define QDATAITEM_P_H +#ifndef MAPRENDERITEM_P_H +#define MAPRENDERITEM_P_H -#include "datavis3dglobal_p.h" -#include "qdataitem.h" -#include "labelitem_p.h" - -#include <QOpenGLFunctions> -#include <QSize> -#include <QString> -#include <QVector3D> +#include "barrenderitem_p.h" QT_DATAVIS3D_BEGIN_NAMESPACE -class QDataItemPrivate +class Maps3DRenderer; +class Maps3DController; // TODO remove when maps refactored + +class MapRenderItem : public BarRenderItem { public: - QDataItemPrivate(QDataItem *q, float value, const QString &label); - QDataItemPrivate(QDataItem *q); - ~QDataItemPrivate(); + MapRenderItem(); + virtual ~MapRenderItem(); + + inline const QPointF &mapPosition() const { return m_mapPosition; } + inline void setMapPosition(const QPointF &pos) { m_mapPosition = pos; } - // Position in 3D scene - void setTranslation(const QVector3D &translation); - QVector3D translation(); - // Value of bar - float value(); - // Value and label appended into a string. If label has prepend -flag set, append label and value - QString valueStr(); + inline const QString &itemLabel() const { return m_itemLabel; } + inline void setItemLabel(const QString &label) { m_itemLabel = label; } - QPointF position(); + // TODO should be in abstract, but currently there is no abstract renderer + // TODO change when maps refactored + inline void setRenderer(Maps3DController *renderer) { m_renderer = renderer; } -private: - QDataItem *q_ptr; - float m_value; - QString m_labelString; - bool m_prependLabel; - QVector3D m_translation; - QPointF m_position; - friend class QDataItem; +protected: + virtual void formatLabel(); + + Maps3DController *m_renderer; + QPointF m_mapPosition; + QString m_itemLabel; // from QMapDataItem::label() - unformatted item label + + friend class QMapDataItem; }; +typedef QVector<MapRenderItem> MapRenderItemArray; + QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qbardataitem.cpp b/src/datavis3d/data/qbardataitem.cpp index 467ee7f3..63e60281 100644 --- a/src/datavis3d/data/qbardataitem.cpp +++ b/src/datavis3d/data/qbardataitem.cpp @@ -63,6 +63,11 @@ QBarDataItem::QBarDataItem() { } +QBarDataItem::QBarDataItem(const QBarDataItem &other) +{ + operator=(other); +} + /*! * Destroys QBarDataItem. */ @@ -71,6 +76,17 @@ QBarDataItem::~QBarDataItem() delete d_ptr; } +QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other) +{ + m_value = other.m_value; + if (other.d_ptr) + createExtraData(); + else + d_ptr = 0; + // TODO set extra data + return *this; +} + void QBarDataItem::setValue(qreal value) { m_value = value; @@ -81,6 +97,12 @@ qreal QBarDataItem::value() const return m_value; } +void QBarDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QBarDataItemPrivate; +} + QBarDataItemPrivate::QBarDataItemPrivate() { diff --git a/src/datavis3d/data/qbardataitem.h b/src/datavis3d/data/qbardataitem.h index c8afdf33..19063003 100644 --- a/src/datavis3d/data/qbardataitem.h +++ b/src/datavis3d/data/qbardataitem.h @@ -52,16 +52,23 @@ class QT_DATAVIS3D_EXPORT QBarDataItem { public: QBarDataItem(); + QBarDataItem(const QBarDataItem &other); ~QBarDataItem(); + QBarDataItem &operator=(const QBarDataItem &other); + void setValue(qreal value); qreal value() const; // TODO Set color, label format, ...? +protected: + virtual void createExtraData(); + + QBarDataItemPrivate *d_ptr; + private: qreal m_value; - QBarDataItemPrivate *d_ptr; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataproxy.cpp b/src/datavis3d/data/qbardataproxy.cpp index 4d19c6b8..c503d2bc 100644 --- a/src/datavis3d/data/qbardataproxy.cpp +++ b/src/datavis3d/data/qbardataproxy.cpp @@ -99,7 +99,7 @@ void QBarDataProxy::insertRows(int rowIndex, QBarDataArray *rows) emit rowsInserted(rowIndex, insertCount); } -// Mutexing data accessors should be done by user +// Mutexing data accessors should be done by user, if needed int QBarDataProxy::rowCount() { return dptrc()->m_dataArray.size(); diff --git a/src/datavis3d/data/qbardataproxy_p.h b/src/datavis3d/data/qbardataproxy_p.h index 9d22a58f..dcab4a1d 100644 --- a/src/datavis3d/data/qbardataproxy_p.h +++ b/src/datavis3d/data/qbardataproxy_p.h @@ -49,13 +49,13 @@ // // We mean it. +#ifndef QBARDATAPROXY_P_H +#define QBARDATAPROXY_P_H + #include "qbardataproxy.h" #include "qabstractdataproxy_p.h" #include "qbardataitem.h" -#ifndef QBARDATAPROXY_P_H -#define QBARDATAPROXY_P_H - QT_DATAVIS3D_BEGIN_NAMESPACE class QBarDataProxyPrivate : public QAbstractDataProxyPrivate diff --git a/src/datavis3d/data/qdataitem.cpp b/src/datavis3d/data/qdataitem.cpp deleted file mode 100644 index 8a3795b9..00000000 --- a/src/datavis3d/data/qdataitem.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdataitem.h" -#include "qdataitem_p.h" - -#include <QPoint> -#include <QString> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class QDataItem - * \inmodule QtDataVis3D - * \brief The QDataItem class provides a container for data to be added to graphs. - * \since 1.0.0 - * - * A QDataItem holds data for a single bar in a Q3DMaps or Q3DBars graph. - * - * \sa QDataRow, QDataSet, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * \a value A float value of the data item. - * - * \a label A QString label for the item. - * - * Constructs QDataItem. - */ -QDataItem::QDataItem(float value, const QString &label) - : QObject(0), - d_ptr(new QDataItemPrivate(this, value, label)) -{ -} - -/*! - * \overload QDataItem::QDataItem - * - * \a item A float value of the data item. - * - * Constructs QDataItem. - */ -QDataItem::QDataItem(QDataItem &item) - : QObject(0), - d_ptr(new QDataItemPrivate(&item)) -{ - d_ptr->m_labelString = item.d_ptr->m_labelString; - d_ptr->m_position = item.d_ptr->m_position; - d_ptr->m_prependLabel = item.d_ptr->m_prependLabel; - d_ptr->m_translation = item.d_ptr->m_translation; - d_ptr->m_value = item.d_ptr->m_value; -} - -/*! - * Destroys QDataItem. - */ -QDataItem::~QDataItem() -{ -} - -/*! - * \property QDataItem::label - * - * \a label A QString label for the data item. Unit, for example. - * - * \a prepend A flag to indicate if the label is to be prepended or appended to the value. - * \c false by default. - * - * Sets label for the data item. - */ -void QDataItem::setLabel(const QString &label, bool prepend) -{ - d_ptr->m_labelString = label; - d_ptr->m_prependLabel = prepend; -} - -QString QDataItem::label() -{ - return d_ptr->m_labelString; -} - -/*! - * \property QDataItem::value - * - * \a value A float value for the data item. - * - * Sets value for the data item. - */ -void QDataItem::setValue(float value) -{ - d_ptr->m_value = value; -} - -/*! - * \overload QDataItem::value - * - * \a value An int value for the data item. - * - * Sets value for the data item. - */ -void QDataItem::setValue(int value) -{ - d_ptr->m_value = (float)value; -} - -float QDataItem::value() -{ - return d_ptr->m_value; -} - -/*! - * \property QDataItem::position - * - * \a position A QPointF position for the data item. - * - * Sets position for the data item. Has no effect in Q3DBars. - */ -void QDataItem::setPosition(const QPointF &position) -{ - d_ptr->m_position = position; -} - -/*! - * \overload QDataItem::position - * - * \a position A QPoint position for the data item. - * - * Sets position for the data item. Has no effect in Q3DBars. - */ -void QDataItem::setPosition(const QPoint &position) -{ - d_ptr->m_position = (QPointF)position; -} - -QPointF QDataItem::position() -{ - return d_ptr->m_position; -} - -QDataItemPrivate::QDataItemPrivate(QDataItem *q, float value, const QString &label) - : q_ptr(q), - m_value(value), - m_labelString(label), - m_prependLabel(false), - m_translation(QVector3D(0, 0, 0)) - -{ -} - -QDataItemPrivate::QDataItemPrivate(QDataItem *q) - : q_ptr(q), - m_value(q->value()), - m_labelString(q->label()), - m_prependLabel(false), - m_translation(QVector3D(0, 0, 0)) - -{ -} - -QDataItemPrivate::~QDataItemPrivate() -{ -} - -void QDataItemPrivate::setTranslation(const QVector3D &translation) -{ - m_translation = translation; -} - -QVector3D QDataItemPrivate::translation() -{ - return m_translation; -} - -float QDataItemPrivate::value() -{ - return m_value; -} - -QString QDataItemPrivate::valueStr() -{ - QString strVal; - QString numStr; - numStr.setNum(m_value); - if (m_prependLabel) { - strVal.append(m_labelString); - strVal.append(QStringLiteral(" ")); - strVal.append(numStr); - } else { - strVal.append(numStr); - strVal.append(m_labelString); - } - return strVal; -} - -QPointF QDataItemPrivate::position() -{ - return m_position; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qdatarow.cpp b/src/datavis3d/data/qdatarow.cpp deleted file mode 100644 index 4b4eab8f..00000000 --- a/src/datavis3d/data/qdatarow.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdatarow.h" -#include "qdatarow_p.h" -#include "qdataitem.h" -#include "qdataitem_p.h" - -#include <QString> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class QDataRow - * \inmodule QtDataVis3D - * \brief The QDataRow class provides a container for data items to be added to graphs. - * \since 1.0.0 - * - * A QDataRow is a container for all data to be added to a Q3DMaps instance, or a single row to - * be added to a QDataSet. It holds instances of QDataItem and has no knowledge of possible - * sample space sizes set for a Q3DBars instance. The ownership of QDataItem added is transferred - * to QDataRow. - * - * \sa QDataItem, QDataSet, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * \a label A QString label for the row. - * - * Constructs QDataRow. - */ -QDataRow::QDataRow() - : d_ptr(new QDataRowPrivate(this)) -{ -} - -/*! - * Destroys QDataRow and all instances of QDataItem it may hold. - */ -QDataRow::~QDataRow() -{ -} - -/*! - * \a item A QDataItem instance. - * - * Adds a QDataItem to the QDataRow. Ownership of QDataItem is transferred to QDataRow. - */ -void QDataRow::addItem(QDataItem *item) -{ - d_ptr->m_row.prepend(item); -} - -QDataRowPrivate::QDataRowPrivate(QDataRow *q) - : q_ptr(q) -{ -} - -QDataRowPrivate::~QDataRowPrivate() -{ - for (int itemCount = 0; itemCount < m_row.size(); itemCount++) - delete m_row.at(itemCount); - m_row.clear(); -} - -QVector<QDataItem*> QDataRowPrivate::row() -{ - return m_row; -} - -void QDataRowPrivate::clear() -{ - m_row.clear(); -} - -QDataItem *QDataRowPrivate::getItem(int itemIndex) -{ - QDataItem *item = NULL; - if (m_row.size() > itemIndex) - item = m_row.at(itemIndex); - return item; -} - -void QDataRowPrivate::verifySize(int size) -{ - if (size > m_row.size()) { - // QVector's resize doesn't delete data contained in it - // Delete contents of items to be removed - int nbrToBeRemoved = m_row.size() - size; - for (int itemCount = 0; itemCount < nbrToBeRemoved; itemCount++) { - int itemToBeRemoved = m_row.size() - itemCount - 1; // -1 to compensate index 0 - delete m_row.at(itemToBeRemoved); - } - // Resize vector - m_row.resize(size); - } else if (size < m_row.size()) { - qCritical("Check your sample space size! Your row is too short."); - } -} - -QPair<GLfloat, GLfloat> QDataRowPrivate::limitValues() -{ - QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); - for (int i = 0; i < m_row.size(); i++) { - QDataItem *item = m_row.at(i); - float itemValue = item->d_ptr->value(); - if (limits.second < itemValue) - limits.second = itemValue; - if (limits.first > itemValue) - limits.first = itemValue; - } - return limits; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qdataset.cpp b/src/datavis3d/data/qdataset.cpp deleted file mode 100644 index 1dcc8276..00000000 --- a/src/datavis3d/data/qdataset.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdataset.h" -#include "qdataset_p.h" -#include "qdatarow.h" -#include "qdatarow_p.h" - -#include "qvalueaxis.h" -#include "qcategoryaxis.h" -#include "qabstractaxis_p.h" - -#include <QPoint> -#include <QString> - -//#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class QDataSet - * \inmodule QtDataVis3D - * \brief The QDataSet class provides a container for data rows to be added to graphs. - * \since 1.0.0 - * - * A QDataSet is a container for data to be added into a Q3DBars instance. It holds instances of - * QDataRow and has no knowledge of sample space size set for Q3DBars. The ownership of QDataRow - * added is transferred to QDataSet. - * - * \sa QDataItem, QDataRow, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * Constructs QDataSet. - */ -QDataSet::QDataSet() - : d_ptr(new QDataSetPrivate(this)) -{ -} - -/*! - * Destroys QDataSet, including all QDataRow instances it may hold. - */ -QDataSet::~QDataSet() -{ -} - -/*! - * \a row A QDataRow instance. - * - * Adds a QDataRow instance to QDataSet. Ownership of the QDataRow instance is transferred to - * QDataSet. - */ -void QDataSet::addRow(QDataRow *row) -{ - d_ptr->m_set.prepend(row); -} - -QDataSetPrivate::QDataSetPrivate(QDataSet *q) - : q_ptr(q), - m_set(QVector<QDataRow*>()) -{ -} - -QDataSetPrivate::~QDataSetPrivate() -{ - for (int itemCount = 0; itemCount < m_set.size(); itemCount++) - delete m_set.at(itemCount); - m_set.clear(); -} - -QVector<QDataRow*> QDataSetPrivate::set() -{ - return m_set; -} - -QDataRow *QDataSetPrivate::getRow(int rowIndex) -{ - QDataRow *row = NULL; - if (m_set.size() > rowIndex) - row = m_set.at(rowIndex); - return row; -} - -void QDataSetPrivate::verifySize(int colSize, int rowSize) -{ - // First verify columns - // QVector's resize doesn't delete data contained in it - // Delete contents of rows to be removed - if (colSize < m_set.size()) { - int nbrToBeRemoved = m_set.size() - colSize; - for (int rowCount = 0; rowCount < nbrToBeRemoved; rowCount++) { - int rowToBeRemoved = m_set.size() - rowCount - 1; // -1 to compensate index 0 - delete m_set.at(rowToBeRemoved); - } - // Resize vector - m_set.resize(colSize); - } - // Then verify each row left - if (rowSize) { - for (int i = 0; i < m_set.size(); i++) - m_set.at(i)->d_ptr->verifySize(rowSize); - } -} - -QPair<GLfloat, GLfloat> QDataSetPrivate::limitValues() -{ - QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); - QPair<GLfloat, GLfloat> rowLimits; - for (int i = 0; i < m_set.size(); i++) { - rowLimits = m_set.at(i)->d_ptr->limitValues(); - if (limits.second < rowLimits.second) - limits.second = rowLimits.second; - if (limits.first > rowLimits.first) - limits.first = rowLimits.first; - } - return limits; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelbardataproxy.h b/src/datavis3d/data/qitemmodelbardataproxy.h index f9f22fa4..370fc6b3 100644 --- a/src/datavis3d/data/qitemmodelbardataproxy.h +++ b/src/datavis3d/data/qitemmodelbardataproxy.h @@ -46,7 +46,6 @@ #include "qitemmodelbardatamapping.h" #include <QAbstractItemModel> #include <QStringList> -#include <QMap> QT_DATAVIS3D_BEGIN_NAMESPACE @@ -65,7 +64,7 @@ public: void setItemModel(QAbstractItemModel *itemModel); QAbstractItemModel *itemModel(); - // Map key (row, column, value) to value index in data item (QVariantItem). + // Map bars role (row, column, value) to role in model. // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. // Modifying mapping that is set to proxy will trigger dataset re-resolving. void setMapping(QItemModelBarDataMapping *mapping); diff --git a/src/datavis3d/data/qitemmodelbardataproxy_p.h b/src/datavis3d/data/qitemmodelbardataproxy_p.h index 9ee1d1e3..a0893c96 100644 --- a/src/datavis3d/data/qitemmodelbardataproxy_p.h +++ b/src/datavis3d/data/qitemmodelbardataproxy_p.h @@ -88,7 +88,7 @@ private: QItemModelBarDataProxy *qptr(); QPointer<QAbstractItemModel> m_itemModel; // Not owned - QPointer<QItemModelBarDataMapping> m_mapping; // Not owned' + QPointer<QItemModelBarDataMapping> m_mapping; // Not owned bool resolvePending; QTimer m_resolveTimer; diff --git a/src/datavis3d/data/qitemmodelmapdatamapping.cpp b/src/datavis3d/data/qitemmodelmapdatamapping.cpp new file mode 100644 index 00000000..e37fa2db --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdatamapping.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qitemmodelmapdatamapping_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelMapDataMapping::QItemModelMapDataMapping() + : QObject(0), + d_ptr(new QItemModelMapDataMappingPrivate(this)) +{ +} + +QItemModelMapDataMapping::QItemModelMapDataMapping(const QItemModelMapDataMapping &other) + : QObject(0), + d_ptr(new QItemModelMapDataMappingPrivate(this)) +{ + operator=(other); +} + +QItemModelMapDataMapping::QItemModelMapDataMapping(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole) + : QObject(0), + d_ptr(new QItemModelMapDataMappingPrivate(this)) +{ + d_ptr->m_labelRole = labelRole; + d_ptr->m_xPosRole = xPosRole; + d_ptr->m_yPosRole = yPosRole; + d_ptr->m_valueRole = valueRole; +} + +QItemModelMapDataMapping::~QItemModelMapDataMapping() +{ +} + +QItemModelMapDataMapping &QItemModelMapDataMapping::operator=(const QItemModelMapDataMapping &other) +{ + d_ptr->m_labelRole = other.d_ptr->m_labelRole; + d_ptr->m_xPosRole = other.d_ptr->m_xPosRole; + d_ptr->m_yPosRole = other.d_ptr->m_yPosRole; + d_ptr->m_valueRole = other.d_ptr->m_valueRole; + + return *this; +} + +void QItemModelMapDataMapping::setLabelRole(const QString &role) +{ + d_ptr->m_labelRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::labelRole() const +{ + return d_ptr->m_labelRole; +} + +void QItemModelMapDataMapping::setXPosRole(const QString &role) +{ + d_ptr->m_xPosRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::xPosRole() const +{ + return d_ptr->m_xPosRole; +} + +void QItemModelMapDataMapping::setYPosRole(const QString &role) +{ + d_ptr->m_yPosRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::yPosRole() const +{ + return d_ptr->m_yPosRole; +} + +void QItemModelMapDataMapping::setValueRole(const QString &role) +{ + d_ptr->m_valueRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::valueRole() const +{ + return d_ptr->m_valueRole; +} + + +void QItemModelMapDataMapping::remap(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole) +{ + d_ptr->m_labelRole = labelRole; + d_ptr->m_xPosRole = xPosRole; + d_ptr->m_yPosRole = yPosRole; + d_ptr->m_valueRole = valueRole; + + emit mappingChanged(); +} + +// QItemModelMapDataMappingPrivate + +QItemModelMapDataMappingPrivate::QItemModelMapDataMappingPrivate(QItemModelMapDataMapping *q) + : QObject(0), + q_ptr(q) +{ +} + +QItemModelMapDataMappingPrivate::~QItemModelMapDataMappingPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE + diff --git a/src/datavis3d/data/qdataitem.h b/src/datavis3d/data/qitemmodelmapdatamapping.h index 57f1df7b..3638f878 100644 --- a/src/datavis3d/data/qdataitem.h +++ b/src/datavis3d/data/qitemmodelmapdatamapping.h @@ -39,55 +39,51 @@ ** ****************************************************************************/ -#ifndef QDATAITEM_H -#define QDATAITEM_H +#ifndef QITEMMODELMAPDATAMAPPING_H +#define QITEMMODELMAPDATAMAPPING_H #include "qdatavis3dnamespace.h" -#include <QScopedPointer> -#include <QString> -#include <QObject> -#include <QPointF> - -class QPoint; +#include <QStringList> QT_DATAVIS3D_BEGIN_NAMESPACE -class QDataItemPrivate; +class QItemModelMapDataMappingPrivate; -class QT_DATAVIS3D_EXPORT QDataItem : public QObject +class QT_DATAVIS3D_EXPORT QItemModelMapDataMapping : public QObject { Q_OBJECT - Q_PROPERTY(QString label READ label WRITE setLabel) - Q_PROPERTY(float value READ value WRITE setValue) - Q_PROPERTY(int value READ value WRITE setValue) - Q_PROPERTY(QPointF position READ position WRITE setPosition) - + Q_PROPERTY(QString labelRole READ labelRole WRITE setLabelRole) + Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole) + Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole) + Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) public: - QDataItem(float value = 0.0f, const QString &label = QString()); - QDataItem(QDataItem &item); - ~QDataItem(); + explicit QItemModelMapDataMapping(); + QItemModelMapDataMapping(const QItemModelMapDataMapping &other); + QItemModelMapDataMapping(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole); + virtual ~QItemModelMapDataMapping(); + + QItemModelMapDataMapping &operator=(const QItemModelMapDataMapping &other); - // TODO: Provide a Q_INVOKABLE version of this, or move prepend to it's own property. - void setLabel(const QString &label, bool prepend = false); // label for value, unit for example - QString label(); - void setValue(float value); - void setValue(int value); - float value(); - // Has no effect in Q3DBars - void setPosition(const QPointF &position); - void setPosition(const QPoint &position); - QPointF position(); + void setLabelRole(const QString &role); + QString labelRole() const; + void setXPosRole(const QString &role); + QString xPosRole() const; + void setYPosRole(const QString &role); + QString yPosRole() const; + void setValueRole(const QString &role); + QString valueRole() const; + + void remap(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole); +signals: + void mappingChanged(); private: - QScopedPointer<QDataItemPrivate> d_ptr; - friend class Bars3dRenderer; - friend class Bars3dController; - friend class Maps3DController; - friend class QDataRowPrivate; - friend class Drawer; - friend class QOldDataProxy; + QScopedPointer<QItemModelMapDataMappingPrivate> d_ptr; }; + QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qdatarow.h b/src/datavis3d/data/qitemmodelmapdatamapping_p.h index 25f2ba01..2f947c5b 100644 --- a/src/datavis3d/data/qdatarow.h +++ b/src/datavis3d/data/qitemmodelmapdatamapping_p.h @@ -39,37 +39,39 @@ ** ****************************************************************************/ -#ifndef QDATAROW_H -#define QDATAROW_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 "qdatavis3dnamespace.h" -#include <QScopedPointer> -#include <QObject> +#include "qitemmodelmapdatamapping.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +#ifndef QITEMMODELMAPDATAMAPPING_P_H +#define QITEMMODELMAPDATAMAPPING_P_H -class QDataRowPrivate; -class QDataItem; +QT_DATAVIS3D_BEGIN_NAMESPACE -class QT_DATAVIS3D_EXPORT QDataRow : public QObject +class QItemModelMapDataMappingPrivate : public QObject { Q_OBJECT - public: - explicit QDataRow(); - ~QDataRow(); - - Q_INVOKABLE void addItem(QDataItem *item); + QItemModelMapDataMappingPrivate(QItemModelMapDataMapping *q); + virtual ~QItemModelMapDataMappingPrivate(); private: - QScopedPointer<QDataRowPrivate> d_ptr; - friend class Bars3dRenderer; - friend class Bars3dController; - friend class Maps3DController; - friend class DeclarativeBars; - friend class DeclarativeMaps; - friend class QDataSetPrivate; - friend class QOldDataProxy; + QString m_labelRole; + QString m_xPosRole; + QString m_yPosRole; + QString m_valueRole; + + QItemModelMapDataMapping *q_ptr; + + friend class QItemModelMapDataMapping; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelmapdataproxy.cpp b/src/datavis3d/data/qitemmodelmapdataproxy.cpp new file mode 100644 index 00000000..86a3395a --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdataproxy.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qitemmodelmapdataproxy_p.h" +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelMapDataProxy::QItemModelMapDataProxy() : + QMapDataProxy(new QItemModelMapDataProxyPrivate(this)) +{ +} + +QItemModelMapDataProxy::QItemModelMapDataProxy(QAbstractItemModel *itemModel, + QItemModelMapDataMapping *mapping) : + QMapDataProxy(new QItemModelMapDataProxyPrivate(this)) +{ + dptr()->setItemModel(itemModel); + dptr()->setMapping(mapping); +} + +QItemModelMapDataProxy::~QItemModelMapDataProxy() +{ +} + +void QItemModelMapDataProxy::setItemModel(QAbstractItemModel *itemModel) +{ + dptr()->setItemModel(itemModel); +} + +QAbstractItemModel *QItemModelMapDataProxy::itemModel() +{ + return dptr()->m_itemModel.data(); +} + +void QItemModelMapDataProxy::setMapping(QItemModelMapDataMapping *mapping) +{ + dptr()->setMapping(mapping); +} + +QItemModelMapDataMapping *QItemModelMapDataProxy::mapping() +{ + return dptr()->m_mapping.data(); +} + +QItemModelMapDataProxyPrivate *QItemModelMapDataProxy::dptr() +{ + return static_cast<QItemModelMapDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelMapDataProxyPrivate + +QItemModelMapDataProxyPrivate::QItemModelMapDataProxyPrivate(QItemModelMapDataProxy *q) + : QMapDataProxyPrivate(q), + resolvePending(0) +{ + m_resolveTimer.setSingleShot(true); + QObject::connect(&m_resolveTimer, &QTimer::timeout, this, &QItemModelMapDataProxyPrivate::handlePendingResolve); +} + +QItemModelMapDataProxyPrivate::~QItemModelMapDataProxyPrivate() +{ +} + +void QItemModelMapDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) +{ + if (!m_itemModel.isNull()) + QObject::disconnect(m_itemModel, 0, this, 0); + + m_itemModel = itemModel; + + if (!m_itemModel.isNull()) { + QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, &QItemModelMapDataProxyPrivate::handleColumnsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, &QItemModelMapDataProxyPrivate::handleColumnsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, &QItemModelMapDataProxyPrivate::handleColumnsRemoved); + QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, &QItemModelMapDataProxyPrivate::handleDataChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, &QItemModelMapDataProxyPrivate::handleLayoutChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, &QItemModelMapDataProxyPrivate::handleModelReset); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, &QItemModelMapDataProxyPrivate::handleRowsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, &QItemModelMapDataProxyPrivate::handleRowsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, &QItemModelMapDataProxyPrivate::handleRowsRemoved); + } + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelMapDataProxyPrivate::setMapping(QItemModelMapDataMapping *mapping) +{ + if (!m_mapping.isNull()) + QObject::disconnect(m_mapping.data(), &QItemModelMapDataMapping::mappingChanged, this, &QItemModelMapDataProxyPrivate::handleMappingChanged); + + m_mapping = mapping; + + if (!m_mapping.isNull()) + QObject::connect(m_mapping.data(), &QItemModelMapDataMapping::mappingChanged, this, &QItemModelMapDataProxyPrivate::handleMappingChanged); + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelMapDataProxyPrivate::handleColumnsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationColumn) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleColumnsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Remove old items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + // Resolve changed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_UNUSED(parents) + Q_UNUSED(hint) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleModelReset() +{ + // Data cleared, reset array + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationRow) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleRowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve removed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleMappingChanged() +{ + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelMapDataProxyPrivate::handlePendingResolve() +{ + resolveModel(); +} + +// Resolve entire item model into QMapDataArray. +void QItemModelMapDataProxyPrivate::resolveModel() +{ + if (m_itemModel.isNull() || m_mapping.isNull()) { + qptr()->resetArray(0); + return; + } + + static const int noRoleIndex = -1; + + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + const int labelRole = roleHash.key(m_mapping->labelRole().toLatin1(), noRoleIndex); + const int xPosRole = roleHash.key(m_mapping->xPosRole().toLatin1(), noRoleIndex); + const int yPosRole = roleHash.key(m_mapping->yPosRole().toLatin1(), noRoleIndex); + // Default valueRole to display role if no mapping + const int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); + const int columnCount = m_itemModel->columnCount(); + const int rowCount = m_itemModel->rowCount(); + const int totalCount = rowCount * columnCount; + int runningCount = 0; + + // Parse data into newProxyArray + QMapDataArray *newProxyArray = new QMapDataArray(totalCount); + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + QModelIndex index = m_itemModel->index(i, j); + if (labelRole != noRoleIndex) + (*newProxyArray)[runningCount].setLabel(index.data(labelRole).toString()); + qreal xPos(qreal(0.0)); + qreal yPos(qreal(0.0)); + if (xPosRole != noRoleIndex) + xPos = index.data(xPosRole).toReal(); + if (yPosRole != noRoleIndex) + yPos = index.data(yPosRole).toReal(); + (*newProxyArray)[runningCount].setMapPosition(QPointF(xPos, yPos)); + (*newProxyArray)[runningCount].setValue(index.data(valueRole).toReal()); + runningCount++; + } + } + + qDebug() << __FUNCTION__ << "Total count:" << newProxyArray->size(); + + qptr()->resetArray(newProxyArray); +} + +QItemModelMapDataProxy *QItemModelMapDataProxyPrivate::qptr() +{ + return static_cast<QItemModelMapDataProxy *>(q_ptr); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelmapdataproxy.h b/src/datavis3d/data/qitemmodelmapdataproxy.h new file mode 100644 index 00000000..874c9532 --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdataproxy.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QITEMMODELMAPDATAPROXY_H +#define QITEMMODELMAPDATAPROXY_H + +#include "qmapdataproxy.h" +#include "qitemmodelmapdatamapping.h" +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelMapDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelMapDataProxy : public QMapDataProxy +{ + Q_OBJECT + +public: + explicit QItemModelMapDataProxy(); + explicit QItemModelMapDataProxy(QAbstractItemModel *itemModel, QItemModelMapDataMapping *mapping); + virtual ~QItemModelMapDataProxy(); + + // Doesn't gain ownership of the model, but does connect to it to listen for data changes. + void setItemModel(QAbstractItemModel *itemModel); + QAbstractItemModel *itemModel(); + + // Map maps role (label, xPos, yPos, value) to role in model + // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. + // Modifying mapping that is set to proxy will trigger dataset re-resolving. + void setMapping(QItemModelMapDataMapping *mapping); + QItemModelMapDataMapping *mapping(); + +protected: + QItemModelMapDataProxyPrivate *dptr(); + +private: + Q_DISABLE_COPY(QItemModelMapDataProxy) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelmapdataproxy_p.h b/src/datavis3d/data/qitemmodelmapdataproxy_p.h new file mode 100644 index 00000000..fa55e40d --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdataproxy_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QITEMMODELMAPDATAPROXY_P_H +#define QITEMMODELMAPDATAPROXY_P_H + +#include "qitemmodelmapdataproxy.h" +#include "qMapDataProxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelMapDataProxyPrivate : public QMapDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelMapDataProxyPrivate(QItemModelMapDataProxy *q); + virtual ~QItemModelMapDataProxyPrivate(); + + void setItemModel(QAbstractItemModel *itemModel); + void setMapping(QItemModelMapDataMapping *mapping); + +public slots: + void handleColumnsInserted(const QModelIndex & parent, int start, int end); + void handleColumnsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationColumn); + void handleColumnsRemoved(const QModelIndex & parent, int start, int end); + void handleDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ()); + void handleLayoutChanged(const QList<QPersistentModelIndex> & parents = QList<QPersistentModelIndex> (), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); + void handleModelReset(); + void handleRowsInserted(const QModelIndex & parent, int start, int end); + void handleRowsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow); + void handleRowsRemoved(const QModelIndex & parent, int start, int end); + + void handleMappingChanged(); + void handlePendingResolve(); + +private: + void resolveModel(); + QItemModelMapDataProxy *qptr(); + + QPointer<QAbstractItemModel> m_itemModel; // Not owned + QPointer<QItemModelMapDataMapping> m_mapping; // Not owned + bool resolvePending; + QTimer m_resolveTimer; + + friend class QItemModelMapDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qmapdataitem.cpp b/src/datavis3d/data/qmapdataitem.cpp new file mode 100644 index 00000000..4ec2a9e7 --- /dev/null +++ b/src/datavis3d/data/qmapdataitem.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmapdataitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +/*! + * \class QMapDataItem + * \inmodule QtDataVis3D + * \brief The QMapDataItem class provides a container for resolved data to be added to maps graphs. + * \since 1.0.0 + * + * A QMapDataItem holds data for a single rendered bar in a maps graph. + * Maps data proxies parse data into QMapDataItem instances for visualizing. + * + * \sa QMapDataProxy, {Qt Data Visualization 3D C++ Classes} + */ + +/*! + * Constructs QMapDataItem. + */ +QMapDataItem::QMapDataItem() + : QBarDataItem() +{ +} + +QMapDataItem::QMapDataItem(const QMapDataItem &other) + : QBarDataItem(other) +{ + operator=(other); +} + +/*! + * Destroys QMapDataItem. + */ +QMapDataItem::~QMapDataItem() +{ +} + +QMapDataItem &QMapDataItem::operator=(const QMapDataItem &other) +{ + QBarDataItem::operator =(other); + m_mapPosition = other.m_mapPosition; + m_label = other.m_label; + + return *this; +} + +void QMapDataItem::setMapPosition(const QPointF &position) +{ + m_mapPosition = position; +} + +const QPointF &QMapDataItem::mapPosition() const +{ + return m_mapPosition; +} + +void QMapDataItem::setLabel(const QString &label) +{ + m_label = label; +} + +const QString &QMapDataItem::label() const +{ + return m_label; +} + +void QMapDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QMapDataItemPrivate; +} + +QMapDataItemPrivate::QMapDataItemPrivate() + : QBarDataItemPrivate() +{ +} + +QMapDataItemPrivate::~QMapDataItemPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qdataset.h b/src/datavis3d/data/qmapdataitem.h index 639c5370..adcd265b 100644 --- a/src/datavis3d/data/qdataset.h +++ b/src/datavis3d/data/qmapdataitem.h @@ -39,38 +39,40 @@ ** ****************************************************************************/ -#ifndef QDATASET_H -#define QDATASET_H +#ifndef QMAPDATAITEM_H +#define QMAPDATAITEM_H #include "qdatavis3dnamespace.h" -#include "qdataitem.h" -#include "qdatarow.h" - -#include <QScopedPointer> -#include <QVector> -#include <QString> +#include "qbardataitem.h" +#include <QPointF> QT_DATAVIS3D_BEGIN_NAMESPACE -class QDataSetPrivate; +class QMapDataItemPrivate; -class QT_DATAVIS3D_EXPORT QDataSet : public QObject +class QT_DATAVIS3D_EXPORT QMapDataItem : public QBarDataItem { - Q_OBJECT - public: - explicit QDataSet(); - ~QDataSet(); + QMapDataItem(); + QMapDataItem(const QMapDataItem &other); + ~QMapDataItem(); + + QMapDataItem &operator=(const QMapDataItem &other); + + void setMapPosition(const QPointF &position); + const QPointF &mapPosition() const; + + void setLabel(const QString &label); + const QString &label() const; + +protected: + virtual void createExtraData(); - Q_INVOKABLE void addRow(QDataRow *row); + QMapDataItemPrivate *d_ptr; private: - QScopedPointer<QDataSetPrivate> d_ptr; - friend class Bars3dController; - friend class Maps3DController; - friend class Bars3dRenderer; - friend class DeclarativeBars; - friend class QOldDataProxy; + QPointF m_mapPosition; + QString m_label; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qdataset_p.h b/src/datavis3d/data/qmapdataitem_p.h index 4a52d7af..08b7128e 100644 --- a/src/datavis3d/data/qdataset_p.h +++ b/src/datavis3d/data/qmapdataitem_p.h @@ -49,38 +49,25 @@ // // We mean it. -#ifndef QDATASET_P_H -#define QDATASET_P_H +#ifndef QMAPDATAITEM_P_H +#define QMAPDATAITEM_P_H #include "datavis3dglobal_p.h" -#include "qdataset.h" -#include "drawer_p.h" -#include "labelitem_p.h" -#include <QVector> -#include <QString> +#include "qmapdataitem.h" +#include "qbardataitem_p.h" QT_DATAVIS3D_BEGIN_NAMESPACE -class QT_DATAVIS3D_EXPORT QDataSetPrivate : public QObject +class QMapDataItemPrivate : public QBarDataItemPrivate { - Q_OBJECT - public: - explicit QDataSetPrivate(QDataSet *q); - ~QDataSetPrivate(); - - QVector<QDataRow *> set(); - QDataRow *getRow(int rowIndex); - - void verifySize(int colSize, int rowSize = 0); // If rowSize is 0, don't verify rows - // first = min, second = max - QPair<GLfloat, GLfloat> limitValues(); + QMapDataItemPrivate(); + virtual ~QMapDataItemPrivate(); -private: - QDataSet *q_ptr; - QVector<QDataRow *> m_set; + // TODO stores other data for map items besides position - friend class QDataSet; +protected: + friend class QMapDataItem; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qmapdataproxy.cpp b/src/datavis3d/data/qmapdataproxy.cpp new file mode 100644 index 00000000..d9e42884 --- /dev/null +++ b/src/datavis3d/data/qmapdataproxy.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmapdataproxy.h" +#include "qmapdataproxy_p.h" +#include <QMutexLocker> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QMapDataProxy::QMapDataProxy() : + QAbstractDataProxy(new QMapDataProxyPrivate(this)) +{ +} + +QMapDataProxy::QMapDataProxy(QMapDataProxyPrivate *d) : + QAbstractDataProxy(d) +{ +} + +QMapDataProxy::~QMapDataProxy() +{ +} + +void QMapDataProxy::resetArray(QMapDataArray *newArray) +{ + if (dptr()->resetArray(newArray)) + emit arrayReset(); +} + + +// Mutexing data accessors should be done by user, if needed +int QMapDataProxy::itemCount() +{ + return dptr()->m_dataArray.size(); +} + +const QMapDataArray &QMapDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +const QMapDataItem *QMapDataProxy::itemAt(int index) const +{ + return &dptrc()->m_dataArray.at(index); +} + +QMapDataProxyPrivate *QMapDataProxy::dptr() +{ + return static_cast<QMapDataProxyPrivate *>(d_ptr.data()); +} + +const QMapDataProxyPrivate *QMapDataProxy::dptrc() const +{ + return static_cast<const QMapDataProxyPrivate *>(d_ptr.data()); +} + +// QBarDataProxyPrivate + +QMapDataProxyPrivate::QMapDataProxyPrivate(QMapDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeMap) +{ +} + +QMapDataProxyPrivate::~QMapDataProxyPrivate() +{ + m_dataArray.clear(); +} + +bool QMapDataProxyPrivate::resetArray(QMapDataArray *newArray) +{ + QMutexLocker locker(&m_mutex); + + if (!m_dataArray.size() && (!newArray || !newArray->size())) + return false; + + m_dataArray.clear(); + + if (newArray) { + m_dataArray = *newArray; + delete newArray; + } + + return true; +} + +// Protected & private functions. Do not mutex as these are used from mutexed functions. + +QPair<GLfloat, GLfloat> QMapDataProxyPrivate::limitValues() +{ + QMutexLocker locker(&m_mutex); + QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); + for (int i = 0; i < m_dataArray.size(); i++) { + const QMapDataItem &item = m_dataArray.at(i); + qreal itemValue = item.value(); + if (limits.second < itemValue) + limits.second = itemValue; + if (limits.first > itemValue) + limits.first = itemValue; + } + return limits; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qmapdataproxy.h b/src/datavis3d/data/qmapdataproxy.h new file mode 100644 index 00000000..b87b6120 --- /dev/null +++ b/src/datavis3d/data/qmapdataproxy.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMAPDATAPROXY_H +#define QMAPDATAPROXY_H + +#include "qabstractdataproxy.h" +#include "qmapdataitem.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +typedef QVector<QMapDataItem> QMapDataArray; + +class QMapDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QMapDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + +public: + explicit QMapDataProxy(); + explicit QMapDataProxy(QMapDataProxyPrivate *d); + virtual ~QMapDataProxy(); + + // QMapDataProxy is also optimized to use cases where the only defining characteristics of an individual + // map item are it's value and position. Modifying other data such as color or mesh of individual bar + // requires allocating additional data object for the bar. + + // If data is accessed from same thread that sets it, access doesn't need to be protected with mutex. + int itemCount(); + const QMapDataArray &array() const; + const QMapDataItem *itemAt(int index) const; // Index needs to exist or this crashes + + // All array/item manipulation functions are internally protected by data mutex. + + // TODO: Should we remove internal mutexing and require user to mutex also on data manipulations? + // TODO: Upside would be enabling user to mix data setters and getters within same mutex scope. + // TODO: Downside would be signal emissions from inside the mutex scope, which has potential for deadlock. + + // TODO Should data manipulation/access methods be protected rather than public to enforce subclassing use of proxy? + // TODO Leaving them public gives user more options. + + // QMapDataProxy takes ownership of all QMapDataArrays and QMapDataItems passed to it. + + // Clears the existing array and sets it data to new array. + void resetArray(QMapDataArray *newArray); + + // TODO void setItem(int index, QMapDataItem *item); + // TODO void setItems(int index, QMapDataArray *items); + + // TODO int addItem(QMapDataItem *item); // returns the index of added item + // TODO int addItems(QMapDataArray *items); // returns the index of added item + + // TODO void insertItem(int index, QMapDataItem *item); + // TODO void insertItems(int index, QMapDataArray *items); + + // TODO void removeItems(int index, int removeCount); + +signals: + void arrayReset(); + void itemsAdded(int startIndex, int count); + void itemsChanged(int startIndex, int count); + void itemsRemoved(int startIndex, int count); // Index may be over current array size if removed from end + void itemsInserted(int startIndex, int count); + +protected: + QMapDataProxyPrivate *dptr(); + const QMapDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QMapDataProxy) + + friend class Maps3DController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qdatarow_p.h b/src/datavis3d/data/qmapdataproxy_p.h index 6d4c9fff..17850e75 100644 --- a/src/datavis3d/data/qdatarow_p.h +++ b/src/datavis3d/data/qmapdataproxy_p.h @@ -49,37 +49,34 @@ // // We mean it. -#ifndef QDATAROW_P_H -#define QDATAROW_P_H +#ifndef QMAPDATAPROXY_P_H +#define QMAPDATAPROXY_P_H -#include "datavis3dglobal_p.h" -#include "qdatarow.h" -#include <QVector> +#include "qmapdataproxy.h" +#include "qabstractdataproxy_p.h" +#include "qmapdataitem.h" QT_DATAVIS3D_BEGIN_NAMESPACE -class QDataItem; - -class QT_DATAVIS3D_EXPORT QDataRowPrivate +class QMapDataProxyPrivate : public QAbstractDataProxyPrivate { + Q_OBJECT public: - explicit QDataRowPrivate(QDataRow *q); - ~QDataRowPrivate(); + QMapDataProxyPrivate(QMapDataProxy *q); + virtual ~QMapDataProxyPrivate(); + + bool resetArray(QMapDataArray *newArray); - QVector<QDataItem*> row(); - // Clears vector, doesn't delete items - void clear(); - QDataItem *getItem(int itemIndex); - void verifySize(int size); QPair<GLfloat, GLfloat> limitValues(); private: - QDataRow *q_ptr; - QVector<QDataItem*> m_row; - friend class QDataRow; - friend class QOldDataProxy; + QMapDataArray m_dataArray; + QString m_itemLabelFormat; + +private: + friend class QMapDataProxy; }; QT_DATAVIS3D_END_NAMESPACE -#endif +#endif // QBARDATAPROXY_P_H diff --git a/src/datavis3d/data/qolddataproxy.cpp b/src/datavis3d/data/qolddataproxy.cpp deleted file mode 100644 index eff920cd..00000000 --- a/src/datavis3d/data/qolddataproxy.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qolddataproxy.h" -#include "qdataset_p.h" -#include "qdatarow_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QOldDataProxy::QOldDataProxy() : - QBarDataProxy(), - m_dataSet(new QDataSet()) -{ -} - -QOldDataProxy::~QOldDataProxy() -{ -} - -void QOldDataProxy::addDataRow(const QVector<float> &dataRow) -{ - // Convert to QDataRow and add to QDataSet - QDataRow *row = new QDataRow(); - for (int i = 0; i < dataRow.size(); i++) - row->addItem(new QDataItem(dataRow.at(i))); - //row->d_ptr->verifySize(columnCount()); - m_dataSet->addRow(row); - //m_dataSet->d_ptr->verifySize(rowCount()); - addProxyRow(row); -} - -void QOldDataProxy::addDataRow(const QVector<QDataItem*> &dataRow) -{ - // Convert to QDataRow and add to QDataSet - QDataRow *row = new QDataRow(); - for (int i = 0; i < dataRow.size(); i++) - row->addItem(dataRow.at(i)); - //row->d_ptr->verifySize(columnCount()); - m_dataSet->addRow(row); - //m_dataSet->d_ptr->verifySize(rowCount()); - addProxyRow(row); -} - -void QOldDataProxy::addDataRow(QDataRow *dataRow) -{ - // Check that the input data fits into sample space, and resize if it doesn't - //dataRow->d_ptr->verifySize(columnCount()); - // With each new row, the previous data row must be moved back - // ie. we need as many vectors as we have rows in the sample space - m_dataSet->addRow(dataRow); - // if the added data pushed us over sample space, remove the oldest data set - //m_dataSet->d_ptr->verifySize(rowCount()); - addProxyRow(dataRow); -} - -void QOldDataProxy::addDataSet(const QVector< QVector<float> > &data) -{ - // Delete old data set - delete m_dataSet; - m_dataSet = new QDataSet(); - - // Convert to QDataRow and add to QDataSet - QDataRow *row; - for (int rowNr = 0; rowNr < data.size(); rowNr++) { - row = new QDataRow(); - for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++) - row->addItem(new QDataItem(data.at(rowNr).at(colNr))); - //row->d_ptr->verifySize(columnCount()); - m_dataSet->addRow(row); - row++; - } - //m_dataSet->d_ptr->verifySize(rowCount()); - addProxySet(m_dataSet); -} - -void QOldDataProxy::addDataSet(const QVector< QVector<QDataItem*> > &data) -{ - // Delete old data set - delete m_dataSet; - m_dataSet = new QDataSet(); - - // Convert to QDataRow and add to QDataSet - QDataRow *row; - for (int rowNr = 0; rowNr < data.size(); rowNr++) { - row = new QDataRow(); - for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++) - row->addItem(data.at(rowNr).at(colNr)); - //row->d_ptr->verifySize(columnCount()); - m_dataSet->addRow(row); - row++; - } - //m_dataSet->d_ptr->verifySize(rowCount()); - addProxySet(m_dataSet); -} - -void QOldDataProxy::addDataSet(QDataSet* dataSet) -{ - // Check sizes - //dataSet->d_ptr->verifySize(rowCount(), columnCount()); - - // Delete old data set - delete m_dataSet; - // Take ownership of given set - m_dataSet = dataSet; - - addProxySet(m_dataSet); -} - -void QOldDataProxy::addProxyRow(QDataRow *dataRow) -{ - QBarDataRow *newProxyRow = new QBarDataRow(dataRow->d_ptr->m_row.size()); - for (int i = 0; i < dataRow->d_ptr->m_row.size(); i++) { - QDataItem *oldItem = dataRow->d_ptr->getItem(i); - (*newProxyRow)[i].setValue(qreal(oldItem->value())); - } - - insertRow(0, newProxyRow); -} - -void QOldDataProxy::addProxySet(QDataSet *dataSet) -{ - QVector<QDataRow *> oldSet = dataSet->d_ptr->set(); - QBarDataArray *newProxyArray = new QBarDataArray(); - - for (int i = 0; i < oldSet.size(); i++) { - QDataRow *oldRow = oldSet.at(i); - QBarDataRow *newProxyRow = new QBarDataRow(oldRow->d_ptr->m_row.size()); - for (int j = 0; j < oldRow->d_ptr->m_row.size(); j++) { - QDataItem *oldItem = oldRow->d_ptr->getItem(j); - (*newProxyRow)[j].setValue(qreal(oldItem->value())); - } - newProxyArray->append(newProxyRow); - } - - resetArray(newProxyArray); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qolddataproxy.h b/src/datavis3d/data/qolddataproxy.h deleted file mode 100644 index 62f82d1e..00000000 --- a/src/datavis3d/data/qolddataproxy.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOLDBARDATAPROXY_H -#define QOLDBARDATAPROXY_H - -#include "qbardataproxy.h" -#include "qdataset.h" -#include <QOpenGLFunctions> - -// TODO: NOTE: THIS IS A TEMPORARY PROXY CLASS TO HANDLE OLD QDataSet -// TODO: To be removed once QDataSet is booted off the island. -// TODO: Until then, it serves as an example of how to customize proxy -// TODO: Therefore it doesn't implement private class either. - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QT_DATAVIS3D_EXPORT QOldDataProxy : public QBarDataProxy -{ - Q_OBJECT - -public: - explicit QOldDataProxy(); - virtual ~QOldDataProxy(); - - // Add a row of data. Each new row is added to the front of the sample space, moving previous - // rows back (if sample space is more than one row deep) - void addDataRow(const QVector<GLfloat> &dataRow); - - // ownership of dataItems is transferred - void addDataRow(const QVector<QDataItem*> &dataRow); - - // ownership of dataRow is transferred - void addDataRow(QDataRow *dataRow); - - // Add complete data set at a time, as a vector of data rows - void addDataSet(const QVector< QVector<GLfloat> > &data); - - // ownership of dataItems is transferred - void addDataSet(const QVector< QVector<QDataItem*> > &data); - - // ownership of dataSet is transferred - void addDataSet(QDataSet* dataSet); - -private: - void addProxyRow(QDataRow *dataRow); - void addProxySet(QDataSet* dataSet); - - Q_DISABLE_COPY(QOldDataProxy) - - QDataSet *m_dataSet; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif // QOLDBARDATAPROXY_H diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp index a633999e..536fd443 100644 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -114,10 +114,15 @@ void Bars3dController::render(const GLuint defaultFboHandle) return; // TODO do not give the entire data array, just the data window + // TODO Would it be enough to just mutex cache update in renderer? + // TODO --> Only if there is no need to store m_dataProxy for later, e.g. for string formatting + // TODO Also, m_valuesDirty flag setting needs to be under same mutex + QMutexLocker(m_data->mutex()); m_renderer->render(m_data, m_valuesDirty, m_cameraHelper, m_axisX->d_ptr->titleItem(), m_axisY->d_ptr->titleItem(), m_axisZ->d_ptr->titleItem(), defaultFboHandle); m_valuesDirty = false; + } QMatrix4x4 Bars3dController::calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder) diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp index bc32ed76..3ec1c0f1 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -329,9 +329,6 @@ void Bars3dRenderer::render(QBarDataProxy *dataProxy, } #endif - // TODO Would it be enough to just mutex cache update? - // TODO --> Only if there is no need to store m_dataProxy for later, e.g. for string formatting - QMutexLocker(dataProxy->mutex()); m_dataProxy = dataProxy; // Update cached data window @@ -698,7 +695,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Draw bars to depth buffer for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { - BarRenderItem &item = m_renderItemArray[row][bar]; + const BarRenderItem &item = m_renderItemArray.at(row).at(bar); if (!item.value()) continue; @@ -792,7 +789,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, 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) { - BarRenderItem &item = m_renderItemArray[row][bar]; + const BarRenderItem &item = m_renderItemArray.at(row).at(bar); if (!item.value()) continue; @@ -1386,10 +1383,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, m_previouslySelectedBar = m_selectedBar; } - m_drawer->drawLabel(*m_selectedBar, m_selectedBar->label(), + m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), m_cachedSelectionMode, m_labelShader, m_labelObj, true); #else diff --git a/src/datavis3d/engine/bars3drenderer_p.h b/src/datavis3d/engine/bars3drenderer_p.h index 9f5c9bc3..621d3592 100644 --- a/src/datavis3d/engine/bars3drenderer_p.h +++ b/src/datavis3d/engine/bars3drenderer_p.h @@ -115,8 +115,8 @@ private: // Internal state bool m_hasNegativeValues; - BarRenderItem *m_selectedBar; // TODO: Does this need to be member variable? - BarRenderItem *m_previouslySelectedBar; + BarRenderItem *m_selectedBar; // points to renderitem array + BarRenderItem *m_previouslySelectedBar; // points to renderitem array QList<BarRenderItem *> *m_sliceSelection; QAbstractAxisPrivate *m_sliceAxisP; // not owned const LabelItem *m_sliceTitleItem; // not owned diff --git a/src/datavis3d/engine/maps3dcontroller.cpp b/src/datavis3d/engine/maps3dcontroller.cpp index 81edf0b2..e30392de 100644 --- a/src/datavis3d/engine/maps3dcontroller.cpp +++ b/src/datavis3d/engine/maps3dcontroller.cpp @@ -42,16 +42,14 @@ #include "maps3dcontroller_p.h" #include "maps3drenderer_p.h" #include "camerahelper_p.h" -#include "qdataitem_p.h" -#include "qdatarow_p.h" -#include "qdataset_p.h" #include "shaderhelper_p.h" #include "objecthelper_p.h" #include "texturehelper_p.h" #include "theme_p.h" #include "utils_p.h" #include "drawer_p.h" -#include "barrenderitem_p.h" // TODO change to maprenderitem? +#include "maprenderitem_p.h" +#include "qmapdataproxy_p.h" #include <QOpenGLFunctions> #include <QMatrix4x4> @@ -108,7 +106,7 @@ Maps3DController::Maps3DController(const QRect &rect) m_isInitialized(false), m_selectionMode(ModeBar), m_selectedBar(0), - m_data(new QDataRow()), + m_previouslySelectedBar(0), m_axisLabelX(QStringLiteral("X")), m_axisLabelZ(QStringLiteral("Z")), m_axisLabelY(QStringLiteral("Y")), @@ -131,7 +129,9 @@ Maps3DController::Maps3DController(const QRect &rect) m_shadowQuality(ShadowLow), m_shadowQualityToShader(33.3f), m_bgrHasAlpha(false), - m_boundingRect(rect.x(), rect.y(), rect.width(), rect.height()) + m_boundingRect(rect.x(), rect.y(), rect.width(), rect.height()), + m_data(0), + m_valuesDirty(false) { //m_data->setDrawer(m_drawer); //QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Maps3DController::updateTextures); @@ -144,7 +144,6 @@ Maps3DController::~Maps3DController() m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); m_textureHelper->deleteTexture(&m_selectionTexture); m_textureHelper->deleteTexture(&m_bgrTexture); - delete m_data; delete m_barShader; delete m_selectionShader; delete m_backgroundShader; @@ -289,6 +288,24 @@ void Maps3DController::render(const GLuint defaultFboHandle) } #endif + QMutexLocker(m_data->mutex()); + // Update cached values + if (m_valuesDirty) { + const QMapDataArray &dataArray = m_data->array(); + int dataSize = dataArray.size(); + m_renderItemArray.resize(dataSize); + for (int i = 0; i < dataSize ; i++) { + qreal value = dataArray.at(i).value(); + m_renderItemArray[i].setValue(value); + m_renderItemArray[i].setMapPosition(dataArray.at(i).mapPosition()); + m_renderItemArray[i].setHeight(value / m_heightNormalizer); + m_renderItemArray[i].setItemLabel(dataArray.at(i).label()); + calculateTranslation(m_renderItemArray[i]); + m_renderItemArray[i].setRenderer(this); + } + m_valuesDirty = false; + } + if (defaultFboHandle) { glDepthMask(true); glEnable(GL_DEPTH_TEST); @@ -455,22 +472,20 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) } #endif // Draw bars to depth buffer - for (int bar = 0; bar < m_data->d_ptr->row().size(); bar++) { - QDataItem *item = m_data->d_ptr->getItem(bar); - if (!item) + for (int bar = 0; bar < m_renderItemArray.size(); bar++) { + const MapRenderItem &item = m_renderItemArray.at(bar); + if (!item.value()) continue; - GLfloat barHeight = item->value() / m_heightNormalizer; - QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - modelMatrix.translate(item->d_ptr->translation().x(), - heightMultiplier * barHeight + heightScaler - m_yAdjustment, - item->d_ptr->translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); + modelMatrix.translate(item.translation().x(), + heightMultiplier * item.height() + heightScaler - m_yAdjustment, + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; @@ -542,22 +557,20 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) GLint barIdxRed = 0; GLint barIdxGreen = 0; GLint barIdxBlue = 0; - for (int bar = 0; bar < m_data->d_ptr->row().size(); bar++, barIdxRed++) { - QDataItem *item = m_data->d_ptr->getItem(bar); - if (!item) + for (int bar = 0; bar < m_renderItemArray.size(); bar++, barIdxRed++) { + const MapRenderItem &item = m_renderItemArray.at(bar); + if (!item.value()) continue; - GLfloat barHeight = item->value() / m_heightNormalizer; - QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - modelMatrix.translate(item->d_ptr->translation().x(), - heightMultiplier * barHeight + heightScaler - m_yAdjustment, - item->d_ptr->translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); + modelMatrix.translate(item.translation().x(), + heightMultiplier * item.height() + heightScaler - m_yAdjustment, + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; @@ -637,27 +650,25 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) //if (!m_zoomActivated) bool barSelectionFound = false; - for (int bar = 0; bar < m_data->d_ptr->row().size(); bar++) { - QDataItem *item = m_data->d_ptr->getItem(bar); - if (!item) + for (int bar = 0; bar < m_renderItemArray.size(); bar++) { + MapRenderItem &item = m_renderItemArray[bar]; + if (!item.value()) continue; - GLfloat barHeight = item->value() / m_heightNormalizer; - QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - modelMatrix.translate(item->d_ptr->translation().x(), - heightMultiplier * barHeight + heightScaler - m_yAdjustment, - item->d_ptr->translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); - itModelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); + modelMatrix.translate(item.translation().x(), + heightMultiplier * item.height() + heightScaler - m_yAdjustment, + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); + itModelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; @@ -667,7 +678,7 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor); - QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) * barHeight; + QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) * item.height(); QVector3D barColor = baseColor + heightColor; @@ -680,7 +691,7 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) lightStrength = m_theme->m_highlightLightStrength; // Insert data to QDataItem. We have no ownership, don't delete the previous one if (!m_zoomActivated) { - m_selectedBar = item; + m_selectedBar = &item; barSelectionFound = true; } break; @@ -698,7 +709,7 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) } } - if (barHeight != 0) { + if (item.height() != 0) { // Set shader bindings m_barShader->setUniformValue(m_barShader->lightP(), lightPos); m_barShader->setUniformValue(m_barShader->view(), viewMatrix); @@ -827,7 +838,6 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) } }*/ else { // Print value of selected bar - static QDataItem *prevItem = m_selectedBar; m_labelShader->bind(); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); @@ -837,48 +847,30 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) } #ifndef DISPLAY_FULL_DATA_ON_SELECTION // Draw just the value string of the selected bar - BarRenderItem dummyItem; // TODO temporary solution - dummyItem.setValue(m_selectedBar->d_ptr->value()); - if (prevItem != m_selectedBar || m_updateLabels) { - m_drawer->generateLabelTexture(&dummyItem); - prevItem = m_selectedBar; + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { + m_drawer->generateLabelTexture(m_selectedBar); + m_previouslySelectedBar = m_selectedBar; } - m_drawer->drawLabel(dummyItem, dummyItem.labelItem(), + m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), - (m_selectedBar->d_ptr->value() / m_heightNormalizer), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), m_selectionMode, m_labelShader, m_labelObj, m_camera, true); #else - static bool firstSelection = true; // Draw the value string followed by row label and column label - LabelItem labelItem = m_selectedBar->selectionLabel(); - if (firstSelection || prevItem != m_selectedBar || m_updateLabels) { - QString labelText = m_selectedBar->valueStr(); - // if ((m_data->d_ptr->columnLabels().size() - // > m_selectedBar->position().y()) - // && (m_data->d_ptr->rowLabels().size() - // > m_selectedBar->position().x())) { - // labelText.append(QStringLiteral(" (")); - // labelText.append(m_data->d_ptr->rowLabels().at( - // m_selectedBar->position().x())); - // labelText.append(QStringLiteral(", ")); - // labelText.append(m_data->d_ptr->columnLabels().at( - // m_selectedBar->position().y())); - // labelText.append(QStringLiteral(")")); - // //qDebug() << labelText; - // } + LabelItem &labelItem = m_selectedBar->selectionLabel(); + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels || !labelItem.textureId()) { + QString labelText = m_selectedBar->label(); + // TODO More elaborate label? m_drawer->generateLabelItem(&labelItem, labelText); - m_selectedBar->setSelectionLabel(labelItem); - prevItem = m_selectedBar; - firstSelection = false; + m_previouslySelectedBar = m_selectedBar; } m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), m_selectionMode, m_labelShader, m_labelObj, true, false); #endif @@ -1437,109 +1429,7 @@ ShadowQuality Maps3DController::shadowQuality() return m_shadowQuality; } -bool Maps3DController::addDataItem(QDataItem *dataItem) -{ - // Check validity - if (!isValid(*dataItem)) - return false; - // Convert position to translation - calculateTranslation(dataItem); - // Add item - m_data->addItem(dataItem); - // Get the limits - QPair<GLfloat, GLfloat> limits = m_data->d_ptr->limitValues(); - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - return true; -} -bool Maps3DController::addData(const QVector<QDataItem *> &data) -{ - // Convert to QDataRow - for (int i = 0; i < data.size(); i++) { - QDataItem *item = data.at(i); - // Check validity - if (!isValid(*item)) { - return false; - } else { - // Convert position to translation - calculateTranslation(item); - // Add item - m_data->addItem(item); - } - } - // Get the limits - QPair<GLfloat, GLfloat> limits = m_data->d_ptr->limitValues(); - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - return true; -} - -bool Maps3DController::addData(const QDataRow &dataRow) -{ - for (int itemIdx = 0; itemIdx < dataRow.d_ptr->row().size(); itemIdx++) { - QDataItem *item = dataRow.d_ptr->getItem(itemIdx); - // Check validity - if (!isValid(*item)) { - return false; - } else { - // Convert position to translation - calculateTranslation(item); - // Add item - m_data->addItem(item); - } - } - // Get the limits - QPair<GLfloat, GLfloat> limits = m_data->d_ptr->limitValues(); - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - return true; -} - -bool Maps3DController::setData(const QVector<QDataItem *> &dataRow) -{ - // Delete previous data - delete m_data; - // Convert to QDataRow - m_data = new QDataRow(); - for (int i = 0; i < dataRow.size(); i++) { - QDataItem *item = dataRow.at(i); - // Check validity - if (!isValid(*item)) { - return false; - } else { - // Convert position to translation - calculateTranslation(item); - // Add item - m_data->addItem(item); - } - } - // Get the limits - QPair<GLfloat, GLfloat> limits = m_data->d_ptr->limitValues(); - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - return true; -} - -bool Maps3DController::setData(QDataRow *dataRow) -{ - // Check validity - for (int i = 0; i < dataRow->d_ptr->row().size(); i++) { - if (!isValid(*dataRow->d_ptr->row().at(i))) - return false; - else - calculateTranslation(dataRow->d_ptr->row()[i]); - } - // Delete previous data - delete m_data; - // Set give data as new data - m_data = dataRow; - // Get the limits - QPair<GLfloat, GLfloat> limits = m_data->d_ptr->limitValues(); - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - return true; -} const QSize Maps3DController::size() { @@ -1745,17 +1635,17 @@ void Maps3DController::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> & //qDebug() << m_yAdjustment; } -void Maps3DController::calculateTranslation(QDataItem *item) +void Maps3DController::calculateTranslation(MapRenderItem &item) { // We need to convert position (which is in coordinates), to translation (which has origin in the center and is scaled) // -> move pos(center, center) to trans(0, 0) and pos(0, 0) to trans(left, top) - GLfloat xTrans = 2.0f * (item->position().x() - (m_areaSize.width() / 2.0f)) + GLfloat xTrans = 2.0f * (item.mapPosition().x() - (m_areaSize.width() / 2.0f)) / m_scaleFactor; - GLfloat zTrans = 2.0f * (item->position().y() - (m_areaSize.height() / 2.0f)) + GLfloat zTrans = 2.0f * (item.mapPosition().y() - (m_areaSize.height() / 2.0f)) / m_scaleFactor; - //qDebug() << "x, y" << item->position().x() << item->position().y(); - item->d_ptr->setTranslation(QVector3D(xTrans, 0.0f, zTrans + zComp)); - //qDebug() << item->translation(); + //qDebug() << "x, y" << item.mapPosition().x() << item.mapPosition().y(); + item.setTranslation(QVector3D(xTrans, 0.0f, zTrans + zComp)); + //qDebug() << item.translation(); } Maps3DController::SelectionType Maps3DController::isSelected(GLint bar, const QVector3D &selection) @@ -1794,20 +1684,90 @@ Maps3DController::SelectionType Maps3DController::isSelected(GLint bar, const QV return isSelectedType; } -bool Maps3DController::isValid(const QDataItem &item) +bool Maps3DController::isValid(const MapRenderItem &item) { bool retval = true; - if (item.d_ptr->value() < 0) { + if (item.value() < 0) { qCritical("Data item value out of range"); retval = false; - } else if (item.d_ptr->position().x() < 0 || item.d_ptr->position().x() > m_areaSize.width()) { + } else if (item.mapPosition().x() < 0 || item.mapPosition().x() > m_areaSize.width()) { qCritical("Data item x position out of range"); retval = false; - } else if (item.d_ptr->position().y() < 0 || item.d_ptr->position().y() > m_areaSize.height()) { + } else if (item.mapPosition().y() < 0 || item.mapPosition().y() > m_areaSize.height()) { qCritical("Data item y position out of range"); retval = false; } return retval; } +void Maps3DController::setDataProxy(QMapDataProxy *proxy) +{ + delete m_data; + m_data = proxy; + + QObject::connect(m_data, &QMapDataProxy::arrayReset, this, &Maps3DController::handleArrayReset); + QObject::connect(m_data, &QMapDataProxy::itemsAdded, this, &Maps3DController::handleItemsAdded); + QObject::connect(m_data, &QMapDataProxy::itemsChanged, this, &Maps3DController::handleItemsChanged); + QObject::connect(m_data, &QMapDataProxy::itemsRemoved, this, &Maps3DController::handleItemsRemoved); + QObject::connect(m_data, &QMapDataProxy::itemsInserted, this, &Maps3DController::handleItemsInserted); + + // emit something? Renderer might be interested? +} + +QMapDataProxy *Maps3DController::dataProxy() +{ + return m_data; +} + +void Maps3DController::handleLimitChange() +{ + QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(); + m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + calculateHeightAdjustment(limits); + + //emit limitsChanged(limits); +} + +void Maps3DController::handleArrayReset() +{ + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsAdded(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsChanged(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsRemoved(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsInserted(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3dcontroller_p.h b/src/datavis3d/engine/maps3dcontroller_p.h index 343f4db3..12245555 100644 --- a/src/datavis3d/engine/maps3dcontroller_p.h +++ b/src/datavis3d/engine/maps3dcontroller_p.h @@ -54,7 +54,7 @@ #include "datavis3dglobal_p.h" #include "q3dmaps.h" - +#include "maprenderitem_p.h" #include <QOpenGLFunctions> #include <QFont> @@ -65,8 +65,6 @@ class QSizeF; QT_DATAVIS3D_BEGIN_NAMESPACE -class QDataItem; -class QDataRow; class ShaderHelper; class ObjectHelper; class TextureHelper; @@ -74,9 +72,11 @@ class Theme; class Drawer; class Maps3DRenderer; class CameraHelper; +class QMapDataProxy; class QT_DATAVIS3D_EXPORT Maps3DController : public QObject, public QOpenGLFunctions { + Q_OBJECT public: enum SelectionType { SelectionNone = 0, @@ -101,22 +101,6 @@ public: void initializeOpenGL(); void render(const GLuint defaultFboHandle = 0); - // Add data item. New data item is appended to old data. - // ownership of data is transferred - bool addDataItem(QDataItem *dataItem); - - // Add data set. New data is appended to old data. - // ownership of data is transferred - bool addData(const QVector<QDataItem *> &data); - // ownership of data is transferred - bool addData(const QDataRow &data); - - // Add data set. Old data is deleted. - // ownership of data is transferred - bool setData(const QVector<QDataItem *> &data); - // ownership of data is transferred - bool setData(QDataRow *data); - // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value // TODO: Start using thickness also in adjustment direction; use it as a relative value. // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to @@ -210,9 +194,22 @@ public: void updateTextures(); void calculateSceneScalingFactors(const QRect &areaRect); void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); - void calculateTranslation(QDataItem *item); + void calculateTranslation(MapRenderItem &item); SelectionType isSelected(GLint bar, const QVector3D &selection); - bool isValid(const QDataItem &item); + bool isValid(const MapRenderItem &item); + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QMapDataProxy *proxy); + QMapDataProxy *dataProxy(); + + void handleLimitChange(); + +public slots: + void handleArrayReset(); + void handleItemsAdded(int startIndex, int count); + void handleItemsChanged(int startIndex, int count); + void handleItemsRemoved(int startIndex, int count); + void handleItemsInserted(int startIndex, int count); private: void drawScene(const GLuint defaultFboHandle); @@ -243,8 +240,8 @@ private: Theme *m_theme; bool m_isInitialized; SelectionMode m_selectionMode; - QDataItem *m_selectedBar; - QDataRow *m_data; + BarRenderItem *m_selectedBar; // points to renderitem array + BarRenderItem *m_previouslySelectedBar; // points to renderitem array QString m_axisLabelX; QString m_axisLabelZ; QString m_axisLabelY; @@ -268,6 +265,9 @@ private: GLfloat m_shadowQualityToShader; bool m_bgrHasAlpha; QRect m_boundingRect; + QMapDataProxy *m_data; + bool m_valuesDirty; + MapRenderItemArray m_renderItemArray; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3drenderer.cpp b/src/datavis3d/engine/maps3drenderer.cpp index 67857120..cc18ed72 100644 --- a/src/datavis3d/engine/maps3drenderer.cpp +++ b/src/datavis3d/engine/maps3drenderer.cpp @@ -42,9 +42,6 @@ #include "maps3dcontroller_p.h" #include "maps3drenderer_p.h" #include "camerahelper_p.h" -#include "qdataitem_p.h" -#include "qdatarow_p.h" -#include "qdataset_p.h" #include "shaderhelper_p.h" #include "objecthelper_p.h" #include "texturehelper_p.h" diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp index 7d6d4e5d..d7c11540 100644 --- a/src/datavis3d/engine/q3dmaps.cpp +++ b/src/datavis3d/engine/q3dmaps.cpp @@ -268,29 +268,14 @@ ShadowQuality Q3DMaps::shadowQuality() return d_ptr->m_shared->shadowQuality(); } -bool Q3DMaps::addDataItem(QDataItem* dataItem) +void Q3DMaps::setDataProxy(QMapDataProxy *proxy) { - return d_ptr->m_shared->addDataItem(dataItem); + d_ptr->m_shared->setDataProxy(proxy); } -bool Q3DMaps::addData(const QVector<QDataItem*> &data) +QMapDataProxy *Q3DMaps::dataProxy() { - return d_ptr->m_shared->addData(data); -} - -bool Q3DMaps::addData(const QDataRow &dataRow) -{ - return d_ptr->m_shared->addData(dataRow); -} - -bool Q3DMaps::setData(const QVector<QDataItem*> &dataRow) -{ - return d_ptr->m_shared->setData(dataRow); -} - -bool Q3DMaps::setData(QDataRow *dataRow) -{ - return d_ptr->m_shared->setData(dataRow); + return d_ptr->m_shared->dataProxy(); } Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q, const QRect &rect) diff --git a/src/datavis3d/engine/q3dmaps.h b/src/datavis3d/engine/q3dmaps.h index 165a3e89..2fd4c043 100644 --- a/src/datavis3d/engine/q3dmaps.h +++ b/src/datavis3d/engine/q3dmaps.h @@ -55,8 +55,7 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class Maps3DController; class Q3DMapsPrivate; -class QDataItem; -class QDataRow; +class QMapDataProxy; class QT_DATAVIS3D_EXPORT Q3DMaps : public Q3DWindow { @@ -79,22 +78,6 @@ public: explicit Q3DMaps(); ~Q3DMaps(); - // Add data item. New data item is appended to old data. - // ownership of data is transferred - bool addDataItem(QDataItem *dataItem); - - // Add data set. New data is appended to old data. - // ownership of data is transferred - bool addData(const QVector<QDataItem*> &data); - // ownership of data is transferred - bool addData(const QDataRow &data); - - // Add data set. Old data is deleted. - // ownership of data is transferred - bool setData(const QVector<QDataItem*> &data); - // ownership of data is transferred - bool setData(QDataRow *data); - void setWidth(const int width); void setHeight(const int height); @@ -156,6 +139,10 @@ public: ShadowQuality setShadowQuality(ShadowQuality quality); ShadowQuality shadowQuality(); + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QMapDataProxy *proxy); + QMapDataProxy *dataProxy(); + protected: void render(); diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.cpp b/src/datavis3dqml2/datavis3dqml2_plugin.cpp index b6caec61..ecff3612 100644 --- a/src/datavis3dqml2/datavis3dqml2_plugin.cpp +++ b/src/datavis3dqml2/datavis3dqml2_plugin.cpp @@ -54,6 +54,7 @@ void Datavis3dqml2Plugin::registerTypes(const char *uri) QLatin1String("Trying to create uncreatable: AbstractItemModel.")); qmlRegisterType<QItemModelBarDataMapping>(uri, 1, 0, "BarDataMapping"); + qmlRegisterType<QItemModelMapDataMapping>(uri, 1, 0, "MapDataMapping"); qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars3D"); qmlRegisterType<DeclarativeMaps>(uri, 1, 0, "Maps3D"); diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.h b/src/datavis3dqml2/datavis3dqml2_plugin.h index d186006e..0869316a 100644 --- a/src/datavis3dqml2/datavis3dqml2_plugin.h +++ b/src/datavis3dqml2/datavis3dqml2_plugin.h @@ -46,6 +46,7 @@ #include "declarativebars.h" #include "declarativemaps.h" #include "qitemmodelbardatamapping.h" +#include "qitemmodelmapdatamapping.h" #include <QQmlExtensionPlugin> @@ -55,6 +56,7 @@ Q_DECLARE_METATYPE(DeclarativeBars *) Q_DECLARE_METATYPE(DeclarativeMaps *) Q_DECLARE_METATYPE(QItemModelBarDataMapping *) +Q_DECLARE_METATYPE(QItemModelMapDataMapping *) Q_DECLARE_METATYPE(QAbstractItemModel *) diff --git a/src/datavis3dqml2/declarativemaps.cpp b/src/datavis3dqml2/declarativemaps.cpp index 20ef3e7d..f8ab70cf 100644 --- a/src/datavis3dqml2/declarativemaps.cpp +++ b/src/datavis3dqml2/declarativemaps.cpp @@ -41,10 +41,7 @@ #include "declarativemaps.h" #include "maps3dcontroller_p.h" -#include "qdataitem.h" -#include "qdatarow.h" -#include "qdatarow_p.h" - +#include "qitemmodelmapdataproxy.h" #include <QQuickWindow> #include <QOpenGLFramebufferObject> #include <QOpenGLContext> @@ -83,13 +80,37 @@ void DeclarativeMaps::componentComplete() qDebug() << "componentComplete"; } +void DeclarativeMaps::setData(QAbstractItemModel *data) +{ + m_cachedState->m_model = data; +} + +QAbstractItemModel *DeclarativeMaps::data() +{ + if (m_cachedState->m_model) + return m_cachedState->m_model; + else + return static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->itemModel(); +} + QSGNode *DeclarativeMaps::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { if (!m_shared) { m_shared = new Maps3DController(boundingRect().toRect()); + m_shared->setDataProxy(new QItemModelMapDataProxy); m_shared->initializeOpenGL(); } + if (m_cachedState->m_model) { + static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->setItemModel(m_cachedState->m_model); + m_cachedState->m_model = 0; + } + + if (m_cachedState->m_mapping) { + static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->setMapping(m_cachedState->m_mapping); + m_cachedState->m_mapping = 0; + } + // Check if properites have changed that need to be applied while on the SGRenderThread if (m_cachedState->m_isAreaRectSet) { m_shared->setAreaSpecs(m_cachedState->m_arearect, m_cachedState->m_image); @@ -170,14 +191,6 @@ QSGNode *DeclarativeMaps::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData m_cachedState->m_isLabelTransparencySet = false; } - if (m_cachedState->m_data) { - if (m_cachedState->m_replaceData) - m_shared->setData(m_cachedState->m_data); - else - m_shared->addData(*m_cachedState->m_data); - m_cachedState->m_data = 0; - } - // If old node exists and has right size, reuse it. if (oldNode && m_initializedSize == boundingRect().size().toSize()) { // Update bounding rectangle (that has same size as before). @@ -349,62 +362,17 @@ DeclarativeMaps::ShadowQuality DeclarativeMaps::shadowQuality() return DeclarativeMaps::ShadowLow; } -void DeclarativeMaps::addDataItem(QDataItem *dataItem) +QItemModelMapDataMapping *DeclarativeMaps::mapping() const { - qDebug() << "Enter DeclarativeMaps::addDataItem(QDataItem *dataItem)"; - QDataItem *newItem = new QDataItem(*dataItem); - m_cachedState->appendData(newItem); - update(); -} - -void DeclarativeMaps::addData(const QVector<QDataItem *> &data) -{ - qDebug() << "Enter DeclarativeMaps::addData(const QVector<QDataItem *> &data)"; - QDataItem *newItem; - for (int i = 0; i < data.count(); i++) { - newItem = new QDataItem(*data.at(i)); - m_cachedState->appendData(newItem); - } - update(); -} - -void DeclarativeMaps::addData(const QDataRow &dataRow) -{ - qDebug() << "Enter DeclarativeMaps::addData(const QDataRow &dataRow)"; - QDataItem *newItem; - for (int i = 0; i < dataRow.d_ptr->row().count(); i++) { - newItem = new QDataItem(*dataRow.d_ptr->getItem(i)); - m_cachedState->appendData(newItem); - } - update(); -} - -void DeclarativeMaps::setData(const QVector<QDataItem *> &data) -{ - qDebug() << "Enter DeclarativeMaps::setData(const QVector<QDataItem *> &data)"; - QDataItem *newItem; - delete m_cachedState->m_data; - m_cachedState->m_data = new QDataRow(); - for (int i = 0; i < data.count(); i++) { - newItem = new QDataItem(*data.at(i)); - m_cachedState->appendData(newItem); - } - m_cachedState->m_replaceData = true; - update(); + if (m_cachedState->m_mapping) + return m_cachedState->m_mapping; + else + return static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->mapping(); } -void DeclarativeMaps::setData(QDataRow *data) +void DeclarativeMaps::setMapping(QItemModelMapDataMapping *mapping) { - qDebug() << "Enter DeclarativeMaps::setData(const QVector<QDataItem*> &data)"; - QDataItem *newItem; - delete m_cachedState->m_data; - m_cachedState->m_data = new QDataRow(); - for (int i = 0; i < data->d_ptr->row().count(); i++) { - newItem = new QDataItem(*data->d_ptr->getItem(i)); - m_cachedState->appendData(newItem); - } - m_cachedState->m_replaceData = true; - update(); + m_cachedState->m_mapping = mapping; } void DeclarativeMaps::mousePressEvent(QMouseEvent *event) @@ -488,9 +456,7 @@ void DeclarativeMapsRenderer::render() DeclarativeMapsCachedStatePrivate::DeclarativeMapsCachedStatePrivate() - : m_replaceData(false), - m_data(0), - m_isImageSet(false), + : m_isImageSet(false), m_isBarSpecsSet(false), m_isAreaRectSet(false), m_isSelectionModeSet(false), @@ -511,13 +477,4 @@ DeclarativeMapsCachedStatePrivate::~DeclarativeMapsCachedStatePrivate() { } -void DeclarativeMapsCachedStatePrivate::appendData(QDataItem *item) -{ - if (!m_data) - m_data = new QDataRow(); - - m_data->addItem(item); - m_replaceData = false; -} - QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativemaps.h b/src/datavis3dqml2/declarativemaps.h index 503ac1bf..b6c67447 100644 --- a/src/datavis3dqml2/declarativemaps.h +++ b/src/datavis3dqml2/declarativemaps.h @@ -45,8 +45,10 @@ #include "datavis3dglobal_p.h" #include "maps3dcontroller_p.h" #include "declarativemaps_p.h" +#include "qitemmodelmapdatamapping.h" #include <qsgsimpletexturenode.h> +#include <QAbstractItemModel> #include <QQuickItem> #include <QObject> @@ -59,13 +61,13 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class DeclarativeMaps : public QQuickItem { Q_OBJECT + Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) Q_PROPERTY(LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) Q_PROPERTY(ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(int width READ width WRITE setWidth) - Q_PROPERTY(int height READ height WRITE setHeight) + Q_PROPERTY(QItemModelMapDataMapping *mapping READ mapping WRITE setMapping) Q_ENUMS(SelectionMode) Q_ENUMS(ShadowQuality) Q_ENUMS(LabelTransparency) @@ -102,21 +104,8 @@ public: void classBegin(); void componentComplete(); - // Add data item. New data item is appended to old data. - // ownership of data is transferred - Q_INVOKABLE void addDataItem(QDataItem *dataItem); - - // Add data set. New data is appended to old data. - // ownership of data is transferred - Q_INVOKABLE void addData(const QVector<QDataItem *> &data); - // ownership of data is transferred - Q_INVOKABLE void addData(const QDataRow &data); - - // Add data set. Old data is deleted. - // ownership of data is transferred - Q_INVOKABLE void setData(const QVector<QDataItem *> &data); - // ownership of data is transferred - Q_INVOKABLE void setData(QDataRow *data); + void setData(QAbstractItemModel *data); + QAbstractItemModel *data(); // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value // TODO: Start using thickness also in adjustment direction; use it as a relative value. @@ -173,6 +162,9 @@ public: void setShadowQuality(ShadowQuality quality); ShadowQuality shadowQuality(); + QItemModelMapDataMapping *mapping() const; + void setMapping(QItemModelMapDataMapping *mapping); + protected: Maps3DController *m_shared; DeclarativeMapsCachedStatePrivate *m_cachedState; diff --git a/src/datavis3dqml2/declarativemaps_p.h b/src/datavis3dqml2/declarativemaps_p.h index 2d3ef6eb..7c82f723 100644 --- a/src/datavis3dqml2/declarativemaps_p.h +++ b/src/datavis3dqml2/declarativemaps_p.h @@ -54,7 +54,9 @@ #include "datavis3dglobal_p.h" #include "maps3dcontroller_p.h" +#include "qitemmodelmapdatamapping.h" #include <QString> +#include <QAbstractItemModel> QT_DATAVIS3D_BEGIN_NAMESPACE @@ -69,10 +71,8 @@ public: void appendData(QDataItem *item); - int m_cachedState; - - bool m_replaceData; - QDataRow *m_data; + QAbstractItemModel *m_model; + QItemModelMapDataMapping *m_mapping; bool m_isImageSet; QImage m_image; diff --git a/src/src.pro b/src/src.pro index d25722eb..171f9fde 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs SUBDIRS += datavis3d \ - datavis3dqml2 + datavis3dqml2 |