diff options
87 files changed, 2526 insertions, 972 deletions
diff --git a/examples/audiolevels/audiolevels.cpp b/examples/audiolevels/audiolevels.cpp index 307240c5..4c64cbbe 100644 --- a/examples/audiolevels/audiolevels.cpp +++ b/examples/audiolevels/audiolevels.cpp @@ -23,6 +23,7 @@ #include <QtDataVisualization/q3dvalueaxis.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> #include <QAudioDeviceInfo> #include <QAudioInput> @@ -48,6 +49,7 @@ AudioLevels::AudioLevels(Q3DBars *graph, QObject *parent) m_graph->scene()->activeCamera()->setCameraPosition(-25.0, 10.0, 190.0); m_graph->setTheme(QDataVis::ThemeIsabelle); m_graph->setBarType(QDataVis::MeshStyleBars); + m_graph->addSeries(new QBar3DSeries); //! [0] QAudioFormat formatAudio; @@ -67,7 +69,7 @@ AudioLevels::AudioLevels(Q3DBars *graph, QObject *parent) m_audioInput->setBufferSize(1024); #endif - m_device = new AudioLevelsIODevice(m_graph->activeDataProxy(), this); + m_device = new AudioLevelsIODevice(m_graph->seriesList().at(0)->dataProxy(), this); m_device->open(QIODevice::WriteOnly); m_audioInput->start(m_device); diff --git a/examples/bars/graphmodifier.cpp b/examples/bars/graphmodifier.cpp index 89c651ff..efd6aa6d 100644 --- a/examples/bars/graphmodifier.cpp +++ b/examples/bars/graphmodifier.cpp @@ -22,6 +22,7 @@ #include <QtDataVisualization/qbardataproxy.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> #include <QTime> #include <QComboBox> @@ -43,7 +44,8 @@ GraphModifier::GraphModifier(Q3DBars *bargraph) m_temperatureAxis(new Q3DValueAxis), m_yearAxis(new Q3DCategoryAxis), m_monthAxis(new Q3DCategoryAxis), - m_temperatureData(new QBarDataProxy), + m_primaryData(new QBarDataProxy), + m_secondaryData(new QBarDataProxy), //! [1] m_style(QDataVis::MeshStyleBevelBars), m_smooth(false) @@ -73,10 +75,15 @@ GraphModifier::GraphModifier(Q3DBars *bargraph) m_graph->addAxis(m_monthAxis); //! [3] - m_temperatureData->setItemLabelFormat(QStringLiteral("@valueTitle for @colLabel @rowLabel: @valueLabel")); + QBar3DSeries *series = new QBar3DSeries(m_primaryData); + series->setItemLabelFormat(QStringLiteral("@valueTitle for @colLabel @rowLabel: @valueLabel")); + QBar3DSeries *series2 = new QBar3DSeries(m_secondaryData); + series2->setItemLabelFormat(QStringLiteral("@valueTitle for @colLabel @rowLabel: @valueLabel")); + series2->setVisible(false); //! [4] - m_graph->addDataProxy(m_temperatureData); + m_graph->addSeries(series); + m_graph->addSeries(series2); //! [4] changePresetCamera(); @@ -92,8 +99,6 @@ GraphModifier::~GraphModifier() void GraphModifier::start() { //! [6] - m_graph->setActiveDataProxy(m_temperatureData); - m_graph->setValueAxis(m_temperatureAxis); m_graph->setRowAxis(m_yearAxis); m_graph->setColumnAxis(m_monthAxis); @@ -113,25 +118,40 @@ void GraphModifier::resetTemperatureData() {-9.0, -15.2, -3.8, 2.6, 8.3, 15.9, 18.6, 14.9, 11.1, 5.3, 1.8, -0.2}, // 2011 {-8.7, -11.3, -2.3, 0.4, 7.5, 12.2, 16.4, 14.1, 9.2, 3.1, 0.3, -12.1} // 2012 }; + static const qreal temp2[7][12] = { + {-8.7, -11.3, -2.3, 0.4, 7.5, 12.2, 16.4, 14.1, 9.2, 3.1, 0.3, -12.1}, // 2006 + {-7.8, -8.8, -4.2, 0.7, 9.3, 13.2, 15.8, 15.5, 11.2, 0.6, 0.7, -8.4}, // 2007 + {-6.8, -13.3, 0.2, 1.5, 7.9, 13.4, 16.1, 15.5, 8.2, 5.4, -2.6, -0.8}, // 2008 + {-6.7, -11.7, -9.7, 3.3, 9.2, 14.0, 16.3, 17.8, 10.2, 2.1, -2.6, -0.3}, // 2009 + {-4.2, -4.0, -4.6, 1.9, 7.3, 12.5, 15.0, 12.8, 7.6, 5.1, -0.9, -1.3}, // 2010 + {-14.4, -12.1, -7.0, 2.3, 11.0, 12.6, 18.8, 13.8, 9.4, 3.9, -5.6, -13.0}, // 2011 + {-9.0, -15.2, -3.8, 2.6, 8.3, 15.9, 18.6, 14.9, 11.1, 5.3, 1.8, -0.2} // 2012 + }; - // Create data array + // Create data arrays QBarDataArray *dataSet = new QBarDataArray; + QBarDataArray *dataSet2 = new QBarDataArray; QBarDataRow *dataRow; + QBarDataRow *dataRow2; dataSet->reserve(m_years.size()); for (int year = 0; year < m_years.size(); year++) { // Create a data row dataRow = new QBarDataRow(m_months.size()); + dataRow2 = new QBarDataRow(m_months.size()); for (int month = 0; month < m_months.size(); month++) { // Add data to the row (*dataRow)[month].setValue(temp[year][month]); + (*dataRow2)[month].setValue(temp2[year][month]); } // Add the row to the set dataSet->append(dataRow); + dataSet2->append(dataRow2); } // Add data to the graph (the graph assumes ownership of it) - m_temperatureData->resetArray(dataSet, m_years, m_months); + m_primaryData->resetArray(dataSet, m_years, m_months); + m_secondaryData->resetArray(dataSet2, m_years, m_months); //! [5] } @@ -220,12 +240,12 @@ void GraphModifier::rotateY(int rotation) void GraphModifier::setBackgroundEnabled(int enabled) { - m_graph->setBackgroundVisible((bool)enabled); + m_graph->setBackgroundVisible(bool(enabled)); } void GraphModifier::setGridEnabled(int enabled) { - m_graph->setGridVisible((bool)enabled); + m_graph->setGridVisible(bool(enabled)); } void GraphModifier::setSmoothBars(int smooth) @@ -233,3 +253,15 @@ void GraphModifier::setSmoothBars(int smooth) m_smooth = bool(smooth); m_graph->setBarType(m_style, m_smooth); } + +void GraphModifier::setSeriesVisibility(int enabled) +{ + m_graph->seriesList().at(1)->setVisible(bool(enabled)); + if (enabled) { + m_graph->setBarThickness(2.0); + m_graph->setBarSpacing(QSizeF(1.0, 3.0)); + } else { + m_graph->setBarThickness(1.0); + m_graph->setBarSpacing(QSizeF(1.0, 1.0)); + } +} diff --git a/examples/bars/graphmodifier.h b/examples/bars/graphmodifier.h index 2e18ffd2..978558e2 100644 --- a/examples/bars/graphmodifier.h +++ b/examples/bars/graphmodifier.h @@ -20,6 +20,7 @@ #define GRAPHMODIFIER_H #include <QtDataVisualization/q3dbars.h> +#include <QtDataVisualization/qbardataproxy.h> #include <QFont> #include <QDebug> @@ -45,6 +46,7 @@ public: void setBackgroundEnabled(int enabled); void setGridEnabled(int enabled); void setSmoothBars(int smooth); + void setSeriesVisibility(int enabled); void start(); public slots: @@ -71,7 +73,8 @@ private: Q3DValueAxis *m_temperatureAxis; Q3DCategoryAxis *m_yearAxis; Q3DCategoryAxis *m_monthAxis; - QBarDataProxy *m_temperatureData; + QBarDataProxy *m_primaryData; + QBarDataProxy *m_secondaryData; QDataVis::MeshStyle m_style; bool m_smooth; }; diff --git a/examples/bars/main.cpp b/examples/bars/main.cpp index fc3737f6..ecd5d353 100644 --- a/examples/bars/main.cpp +++ b/examples/bars/main.cpp @@ -118,6 +118,10 @@ int main(int argc, char **argv) gridCheckBox->setText(QStringLiteral("Show grid")); gridCheckBox->setChecked(true); + QCheckBox *seriesCheckBox = new QCheckBox(widget); + seriesCheckBox->setText(QStringLiteral("Show second series")); + seriesCheckBox->setChecked(false); + //! [4] QSlider *rotationSliderX = new QSlider(Qt::Horizontal, widget); rotationSliderX->setTickInterval(30); @@ -163,7 +167,8 @@ int main(int argc, char **argv) vLayout->addWidget(cameraButton, 0, Qt::AlignTop); vLayout->addWidget(backgroundCheckBox); vLayout->addWidget(gridCheckBox); - vLayout->addWidget(smoothCheckBox, 0, Qt::AlignTop); + vLayout->addWidget(smoothCheckBox); + vLayout->addWidget(seriesCheckBox); vLayout->addWidget(new QLabel(QStringLiteral("Change bar style"))); vLayout->addWidget(barStyleList); vLayout->addWidget(new QLabel(QStringLiteral("Change selection mode"))); @@ -197,6 +202,8 @@ int main(int argc, char **argv) &GraphModifier::setGridEnabled); QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier, &GraphModifier::setSmoothBars); + QObject::connect(seriesCheckBox, &QCheckBox::stateChanged, modifier, + &GraphModifier::setSeriesVisibility); QObject::connect(barStyleList, SIGNAL(currentIndexChanged(int)), modifier, SLOT(changeStyle(int))); diff --git a/examples/customproxy/rainfallgraph.cpp b/examples/customproxy/rainfallgraph.cpp index 0327ecb9..36ab9786 100644 --- a/examples/customproxy/rainfallgraph.cpp +++ b/examples/customproxy/rainfallgraph.cpp @@ -21,6 +21,7 @@ #include <QtDataVisualization/q3dvalueaxis.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> #include <QGuiApplication> #include <QFont> #include <QDebug> @@ -39,7 +40,8 @@ RainfallGraph::RainfallGraph(Q3DBars *rainfall) m_columnCount = m_numericMonths.size(); m_proxy = new VariantBarDataProxy; - m_graph->setActiveDataProxy(m_proxy); + QBar3DSeries *series = new QBar3DSeries(m_proxy); + m_graph->addSeries(series); updateYearsList(2000, 2012); diff --git a/examples/itemmodel/main.cpp b/examples/itemmodel/main.cpp index 5964992d..90bac03b 100644 --- a/examples/itemmodel/main.cpp +++ b/examples/itemmodel/main.cpp @@ -22,6 +22,7 @@ #include <QtDataVisualization/q3dvalueaxis.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> #include <QApplication> #include <QVBoxLayout> @@ -268,7 +269,8 @@ int main(int argc, char **argv) QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping; mapping->setUseModelCategories(true); QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model(), mapping); - graph->setActiveDataProxy(proxy); + QBar3DSeries *series = new QBar3DSeries(proxy); + graph->addSeries(series); //! [2] //! [3] diff --git a/examples/qmlbars/qml/qmlbars/data.qml b/examples/qmlbars/qml/qmlbars/data.qml index 210eedde..522926e8 100644 --- a/examples/qmlbars/qml/qmlbars/data.qml +++ b/examples/qmlbars/qml/qmlbars/data.qml @@ -20,9 +20,13 @@ import QtQuick 2.1 import QtDataVisualization 1.0 Item { - property alias mapping: valueMapping property alias model: dataModel + property alias mapping: valueMapping property alias proxy: modelProxy + property alias series: barSeries + property alias secondaryMapping: secondaryMapping + property alias secondaryProxy: secondaryProxy + property alias secondarySeries: secondarySeries //! [1] BarDataMapping { @@ -39,6 +43,33 @@ Item { itemModel: dataModel } //! [2] + + BarDataMapping { + id: secondaryMapping + rowRole: "year" + columnRole: "month" + valueRole: "income" + } + + ItemModelBarDataProxy { + id: secondaryProxy + activeMapping: secondaryMapping + itemModel: dataModel + } + + Bar3DSeries { + id: barSeries + dataProxy: modelProxy + itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel" + } + + Bar3DSeries { + id: secondarySeries + visible: false + dataProxy: secondaryProxy + itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel" + } + //! [0] ListModel { id: dataModel diff --git a/examples/qmlbars/qml/qmlbars/main.qml b/examples/qmlbars/qml/qmlbars/main.qml index db28d569..4346f392 100644 --- a/examples/qmlbars/qml/qmlbars/main.qml +++ b/examples/qmlbars/qml/qmlbars/main.qml @@ -50,14 +50,13 @@ Item { font.pointSize: 35 theme: AbstractGraph3D.ThemeRetro labelStyle: AbstractGraph3D.LabelStyleFromTheme - dataProxy: graphData.proxy barThickness: 0.5 barSpacing: Qt.size(0.5, 0.5) barSpacingRelative: false - scene.activeCamera.cameraPreset: AbstractGraph3D.CameraPresetRight + scene.activeCamera.cameraPreset: AbstractGraph3D.CameraPresetIsometricLeftHigh columnAxis: graphAxes.column valueAxis: graphAxes.expenses - itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel" + seriesList: [graphData.series, graphData.secondarySeries] onSelectedBarChanged: { // Set tableView current row to selected bar @@ -93,12 +92,19 @@ Item { text: "Show Income" //! [0] onClicked: { - if (graphData.mapping.valueRole === "expenses") { + if (graphData.mapping.valueRole === "expenses" && !graphData.secondarySeries.visible) { + // Change mapping to change series data graphData.mapping.valueRole = "income" + text = "Show Both" + testGraph.valueAxis = graphAxes.income + } else if (graphData.mapping.valueRole === "income"){ + // Show both data set in separate series + graphData.secondarySeries.visible = true + graphData.mapping.valueRole = "expenses" text = "Show Expenses" testGraph.valueAxis = graphAxes.income } else { - graphData.mapping.valueRole = "expenses" + graphData.secondarySeries.visible = false text = "Show Income" testGraph.valueAxis = graphAxes.expenses } @@ -134,12 +140,15 @@ Item { if (testGraph.rowAxis.max !== 6) { text = "Show 2010 - 2012" graphData.mapping.autoRowCategories = true + graphData.secondaryMapping.autoRowCategories = true } else { text = "Show all years" // Explicitly defining row categories, since we do not want to show data for // all years in the model, just for the selected ones. graphData.mapping.autoRowCategories = false + graphData.secondaryMapping.autoRowCategories = false graphData.mapping.rowCategories = ["2010", "2011", "2012"] + graphData.secondaryMapping.rowCategories = ["2010", "2011", "2012"] } } //! [1] diff --git a/examples/qmlscatter/qml/qmlscatter/data.qml b/examples/qmlscatter/qml/qmlscatter/data.qml index 4ad9d7fc..74993135 100644 --- a/examples/qmlscatter/qml/qmlscatter/data.qml +++ b/examples/qmlscatter/qml/qmlscatter/data.qml @@ -22,6 +22,7 @@ import QtDataVisualization 1.0 Item { //! [3] property alias proxy: modelProxy + property alias series: scatterSeries //! [3] //! [1] @@ -41,6 +42,12 @@ Item { } //! [2] + Scatter3DSeries { + id: scatterSeries + dataProxy: modelProxy + itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel" + } + //! [0] ListModel { id: dataModel diff --git a/examples/qmlscatter/qml/qmlscatter/main.qml b/examples/qmlscatter/qml/qmlscatter/main.qml index 7fd4ec84..1e80b52a 100644 --- a/examples/qmlscatter/qml/qmlscatter/main.qml +++ b/examples/qmlscatter/qml/qmlscatter/main.qml @@ -57,10 +57,9 @@ Item { shadowQuality: AbstractGraph3D.ShadowQualitySoftLow //! [3] //! [5] - dataProxy: graphData.proxy + seriesList: [graphData.series] //! [5] //! [6] - itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel" axisX.segmentCount: 3 axisX.subSegmentCount: 2 axisX.labelFormat: "%.2f" diff --git a/examples/qmlsurface/qml/qmlsurface/data.qml b/examples/qmlsurface/qml/qmlsurface/data.qml index e5678669..36c7671a 100644 --- a/examples/qmlsurface/qml/qmlsurface/data.qml +++ b/examples/qmlsurface/qml/qmlsurface/data.qml @@ -22,8 +22,8 @@ import QtDataVisualization 1.0 Item { property alias mapping: surfaceMapping property alias model: dataModel - property alias proxy: modelProxy - property alias heightProxy: heightMapProxy + property alias series: surfaceSeries + property alias heightSeries: heightSeries //! [0] HeightMapSurfaceDataProxy { @@ -54,6 +54,16 @@ Item { } //! [3] + Surface3DSeries { + id: surfaceSeries + dataProxy: modelProxy + } + + Surface3DSeries { + id: heightSeries + dataProxy: heightMapProxy + } + //! [1] ListModel { id: dataModel diff --git a/examples/qmlsurface/qml/qmlsurface/main.qml b/examples/qmlsurface/qml/qmlsurface/main.qml index 600d75c1..f91b6a76 100644 --- a/examples/qmlsurface/qml/qmlsurface/main.qml +++ b/examples/qmlsurface/qml/qmlsurface/main.qml @@ -40,7 +40,7 @@ Item { ColorGradient { id: surfaceGradient ColorGradientStop { position: 0.0; color: "darkslategray" } - ColorGradientStop { id: middleGradient; position: 0.55; color: "peru" } + ColorGradientStop { id: middleGradient; position: 0.25; color: "peru" } ColorGradientStop { position: 1.0; color: "red" } } //! [0] @@ -57,9 +57,9 @@ Item { font.family: "STCaiyun" font.pointSize: 35 scene.activeCamera.cameraPreset: AbstractGraph3D.CameraPresetIsometricLeft - dataProxy: surfaceData.heightProxy + seriesList: [surfaceData.series] axisY.min: 0.0 - axisY.max: 250.0 + axisY.max: 500.0 axisX.segmentCount: 10 axisX.subSegmentCount: 2 axisX.labelFormat: "%i" @@ -109,11 +109,13 @@ Item { width: surfaceGridToggle.width text: "Hide Surface" onClicked: { - if (surfaceplot.surfaceVisible === true) { - surfaceplot.surfaceVisible = false; + if (surfaceplot.seriesList[0].visible === true) { + surfaceData.series.visible = false; + surfaceData.heightSeries.visible = false; text = "Show Surface" } else { - surfaceplot.surfaceVisible = true; + surfaceData.series.visible = true; + surfaceData.heightSeries.visible = true; text = "Hide Surface" } } @@ -168,20 +170,20 @@ Item { } NewButton { - id: proxyToggle + id: seriesToggle anchors.top: gridToggle.bottom width: gridToggle.width text: "Switch to Item Model Proxy" //! [3] onClicked: { - if (surfaceplot.dataProxy === surfaceData.heightProxy) { + if (surfaceplot.seriesList[0] === surfaceData.heightSeries) { surfaceplot.axisY.max = 500.0 - surfaceplot.dataProxy = surfaceData.proxy + surfaceplot.seriesList = [surfaceData.series] middleGradient.position = 0.25 text = "Switch to Height Map Proxy" } else { surfaceplot.axisY.max = 250.0 - surfaceplot.dataProxy = surfaceData.heightProxy + surfaceplot.seriesList = [surfaceData.heightSeries] middleGradient.position = 0.55 text = "Switch to Item Model Proxy" } diff --git a/examples/scatter/scatterdatamodifier.cpp b/examples/scatter/scatterdatamodifier.cpp index ce5a1bd7..1bdd089d 100644 --- a/examples/scatter/scatterdatamodifier.cpp +++ b/examples/scatter/scatterdatamodifier.cpp @@ -21,6 +21,7 @@ #include <QtDataVisualization/q3dvalueaxis.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qscatter3dseries.h> #include <qmath.h> using namespace QtDataVisualization; @@ -52,8 +53,9 @@ ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter) //! [2] QScatterDataProxy *proxy = new QScatterDataProxy; - proxy->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel"); - m_graph->setActiveDataProxy(proxy); + QScatter3DSeries *series = new QScatter3DSeries(proxy); + series->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel"); + m_graph->addSeries(series); //! [2] changeLabelStyle(); @@ -107,7 +109,7 @@ void ScatterDataModifier::addData() #endif //! [7] - m_graph->activeDataProxy()->resetArray(dataArray); + m_graph->seriesList().at(0)->dataProxy()->resetArray(dataArray); //! [7] } diff --git a/examples/surface/surfacegraph.cpp b/examples/surface/surfacegraph.cpp index bb07cb96..f5a2e00b 100644 --- a/examples/surface/surfacegraph.cpp +++ b/examples/surface/surfacegraph.cpp @@ -40,13 +40,15 @@ SurfaceGraph::SurfaceGraph(Q3DSurface *surface) m_graph->setLabelStyle(QDataVis::LabelStyleFromTheme); //! [0] - sqrtSinProxy = new QSurfaceDataProxy(); + m_sqrtSinProxy = new QSurfaceDataProxy(); + m_sqrtSinSeries = new QSurface3DSeries(m_sqrtSinProxy); //! [0] fillSqrtSinProxy(); //! [2] QImage heightMapImage(":/maps/mountain"); m_heightMapProxy = new QHeightMapSurfaceDataProxy(heightMapImage); + m_heightMapSeries = new QSurface3DSeries(m_heightMapProxy); m_heightMapProxy->setValueRanges(34.0, 40.0, 18.0, 24.0); //! [2] m_heightMapWidth = heightMapImage.width(); @@ -79,70 +81,76 @@ void SurfaceGraph::fillSqrtSinProxy() *dataArray << newRow; } - sqrtSinProxy->resetArray(dataArray); + m_sqrtSinProxy->resetArray(dataArray); } //! [1] -void SurfaceGraph::enableSqrtSinModel() +void SurfaceGraph::enableSqrtSinModel(bool enable) { - //! [3] - m_graph->setSurfaceGridEnabled(true); - m_graph->setSmoothSurfaceEnabled(false); - - m_graph->axisX()->setLabelFormat("%.2f"); - m_graph->axisZ()->setLabelFormat("%.2f"); - m_graph->axisX()->setRange(sampleMin, sampleMax); - m_graph->axisY()->setRange(0.0, 2.0); - m_graph->axisZ()->setRange(sampleMin, sampleMax); - - m_graph->setActiveDataProxy(sqrtSinProxy); - //! [3] - - // Reset range sliders for Sqrt&Sin - m_rangeMinX = sampleMin; - m_rangeMinZ = sampleMin; - m_stepX = (sampleMax - sampleMin) / qreal(sampleCountX - 1); - m_stepZ = (sampleMax - sampleMin) / qreal(sampleCountZ - 1); - m_axisMinSliderX->setMaximum(sampleCountX - 2); - m_axisMinSliderX->setValue(0); - m_axisMaxSliderX->setMaximum(sampleCountX - 1); - m_axisMaxSliderX->setValue(sampleCountX - 1); - m_axisMinSliderZ->setMaximum(sampleCountZ - 2); - m_axisMinSliderZ->setValue(0); - m_axisMaxSliderZ->setMaximum(sampleCountZ - 1); - m_axisMaxSliderZ->setValue(sampleCountZ - 1); + if (enable) { + //! [3] + m_graph->setSurfaceGridEnabled(true); + m_graph->setSmoothSurfaceEnabled(false); + + m_graph->axisX()->setLabelFormat("%.2f"); + m_graph->axisZ()->setLabelFormat("%.2f"); + m_graph->axisX()->setRange(sampleMin, sampleMax); + m_graph->axisY()->setRange(0.0, 2.0); + m_graph->axisZ()->setRange(sampleMin, sampleMax); + + m_graph->removeSeries(m_heightMapSeries); + m_graph->addSeries(m_sqrtSinSeries); + //! [3] + + // Reset range sliders for Sqrt&Sin + m_rangeMinX = sampleMin; + m_rangeMinZ = sampleMin; + m_stepX = (sampleMax - sampleMin) / qreal(sampleCountX - 1); + m_stepZ = (sampleMax - sampleMin) / qreal(sampleCountZ - 1); + m_axisMinSliderX->setMaximum(sampleCountX - 2); + m_axisMinSliderX->setValue(0); + m_axisMaxSliderX->setMaximum(sampleCountX - 1); + m_axisMaxSliderX->setValue(sampleCountX - 1); + m_axisMinSliderZ->setMaximum(sampleCountZ - 2); + m_axisMinSliderZ->setValue(0); + m_axisMaxSliderZ->setMaximum(sampleCountZ - 1); + m_axisMaxSliderZ->setValue(sampleCountZ - 1); + } } -void SurfaceGraph::enableHeightMapModel() +void SurfaceGraph::enableHeightMapModel(bool enable) { - //! [4] - m_graph->setSurfaceGridEnabled(false); - m_graph->setSmoothSurfaceEnabled(true); - - m_graph->axisX()->setLabelFormat("%.1f N"); - m_graph->axisZ()->setLabelFormat("%.1f E"); - m_graph->axisX()->setRange(34.0, 40.0); - m_graph->axisY()->setAutoAdjustRange(true); - m_graph->axisZ()->setRange(18.0, 24.0); - - m_graph->setActiveDataProxy(m_heightMapProxy); - //! [4] - - // Reset range sliders for height map - int mapGridCountX = m_heightMapWidth / heightMapGridStepX; - int mapGridCountZ = m_heightMapHeight / heightMapGridStepZ; - m_rangeMinX = 34.0; - m_rangeMinZ = 18.0; - m_stepX = 6.0 / qreal(mapGridCountX - 1); - m_stepZ = 6.0 / qreal(mapGridCountZ - 1); - m_axisMinSliderX->setMaximum(mapGridCountX - 2); - m_axisMinSliderX->setValue(0); - m_axisMaxSliderX->setMaximum(mapGridCountX - 1); - m_axisMaxSliderX->setValue(mapGridCountX - 1); - m_axisMinSliderZ->setMaximum(mapGridCountZ - 2); - m_axisMinSliderZ->setValue(0); - m_axisMaxSliderZ->setMaximum(mapGridCountZ - 1); - m_axisMaxSliderZ->setValue(mapGridCountZ - 1); + if (enable) { + //! [4] + m_graph->setSurfaceGridEnabled(false); + m_graph->setSmoothSurfaceEnabled(true); + + m_graph->axisX()->setLabelFormat("%.1f N"); + m_graph->axisZ()->setLabelFormat("%.1f E"); + m_graph->axisX()->setRange(34.0, 40.0); + m_graph->axisY()->setAutoAdjustRange(true); + m_graph->axisZ()->setRange(18.0, 24.0); + + m_graph->removeSeries(m_sqrtSinSeries); + m_graph->addSeries(m_heightMapSeries); + //! [4] + + // Reset range sliders for height map + int mapGridCountX = m_heightMapWidth / heightMapGridStepX; + int mapGridCountZ = m_heightMapHeight / heightMapGridStepZ; + m_rangeMinX = 34.0; + m_rangeMinZ = 18.0; + m_stepX = 6.0 / qreal(mapGridCountX - 1); + m_stepZ = 6.0 / qreal(mapGridCountZ - 1); + m_axisMinSliderX->setMaximum(mapGridCountX - 2); + m_axisMinSliderX->setValue(0); + m_axisMaxSliderX->setMaximum(mapGridCountX - 1); + m_axisMaxSliderX->setValue(mapGridCountX - 1); + m_axisMinSliderZ->setMaximum(mapGridCountZ - 2); + m_axisMinSliderZ->setValue(0); + m_axisMaxSliderZ->setMaximum(mapGridCountZ - 1); + m_axisMaxSliderZ->setValue(mapGridCountZ - 1); + } } void SurfaceGraph::adjustXMin(int min) diff --git a/examples/surface/surfacegraph.h b/examples/surface/surfacegraph.h index ff0e5fc4..92b06e54 100644 --- a/examples/surface/surfacegraph.h +++ b/examples/surface/surfacegraph.h @@ -22,6 +22,7 @@ #include <QtDataVisualization/Q3DSurface> #include <QtDataVisualization/QSurfaceDataProxy> #include <QtDataVisualization/QHeightMapSurfaceDataProxy> +#include <QtDataVisualization/QSurface3DSeries> #include <QtWidgets/QSlider> using namespace QtDataVisualization; @@ -33,8 +34,8 @@ public: explicit SurfaceGraph(Q3DSurface *surface); ~SurfaceGraph(); - void enableHeightMapModel(); - void enableSqrtSinModel(); + void enableHeightMapModel(bool enable); + void enableSqrtSinModel(bool enable); //! [0] void toggleModeNone() { m_graph->setSelectionMode(QDataVis::SelectionNone); } @@ -64,7 +65,9 @@ public slots: private: Q3DSurface *m_graph; QHeightMapSurfaceDataProxy *m_heightMapProxy; - QSurfaceDataProxy *sqrtSinProxy; + QSurfaceDataProxy *m_sqrtSinProxy; + QSurface3DSeries *m_heightMapSeries; + QSurface3DSeries *m_sqrtSinSeries; QSlider *m_axisMinSliderX; QSlider *m_axisMaxSliderX; diff --git a/src/datavisualization/axis/q3dcategoryaxis.cpp b/src/datavisualization/axis/q3dcategoryaxis.cpp index 63026379..6d2dec3a 100644 --- a/src/datavisualization/axis/q3dcategoryaxis.cpp +++ b/src/datavisualization/axis/q3dcategoryaxis.cpp @@ -75,7 +75,10 @@ Q3DCategoryAxis::~Q3DCategoryAxis() * * Defines labels for axis applied to categories. If there are fewer labels than categories, the * remaining ones do not have a label. If category labels are not defined explicitly, labels are - * generated from the data row and column labels. + * generated from the data row (or column) labels. + * + * \note If the graph has multiple visible series and category labels are not defined explicitly, + * changing the rows (or columns) on any of the attached series will regenerate the labels. * * \note CategoryLabels actually reads/writes the Q3DAbstractAxis::labels property, * which is read only there. Since subclass cannot have property with same name, diff --git a/src/datavisualization/data/data.pri b/src/datavisualization/data/data.pri index 770d2bd1..66ad0e3b 100644 --- a/src/datavisualization/data/data.pri +++ b/src/datavisualization/data/data.pri @@ -36,7 +36,15 @@ HEADERS += \ $$PWD/qitemmodelsurfacedataproxy_p.h \ $$PWD/surfaceitemmodelhandler_p.h \ $$PWD/qsurfacedataitem.h \ - $$PWD/qsurfacedataitem_p.h + $$PWD/qsurfacedataitem_p.h \ + $$PWD/qabstract3dseries.h \ + $$PWD/qabstract3dseries_p.h \ + $$PWD/qbar3dseries.h \ + $$PWD/qbar3dseries_p.h \ + $$PWD/qscatter3dseries.h \ + $$PWD/qscatter3dseries_p.h \ + $$PWD/qsurface3dseries.h \ + $$PWD/qsurface3dseries_p.h SOURCES += \ $$PWD/labelitem.cpp \ @@ -61,4 +69,8 @@ SOURCES += \ $$PWD/qitemmodelsurfacedatamapping.cpp \ $$PWD/qitemmodelsurfacedataproxy.cpp \ $$PWD/surfaceitemmodelhandler.cpp \ - $$PWD/qsurfacedataitem.cpp + $$PWD/qsurfacedataitem.cpp \ + $$PWD/qabstract3dseries.cpp \ + $$PWD/qbar3dseries.cpp \ + $$PWD/qscatter3dseries.cpp \ + $$PWD/qsurface3dseries.cpp diff --git a/src/datavisualization/data/qabstract3dseries.cpp b/src/datavisualization/data/qabstract3dseries.cpp new file mode 100644 index 00000000..52d3fda1 --- /dev/null +++ b/src/datavisualization/data/qabstract3dseries.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qabstract3dseries.h" +#include "qabstract3dseries_p.h" +#include "qabstractdataproxy_p.h" +#include "abstract3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QAbstract3DSeries + * \inmodule QtDataVisualization + * \brief Base class for all QtDataVisualization data proxies. + * \since Qt Data Visualization 1.0 + * + * You use the visualization type specific inherited classes instead of the base class. + * \sa QBar3DSeries, QScatter3DSeries, QSurface3DSeries, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Abstract3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QAbstract3DSeries + * \brief Base type for all QtDataVisualization data proxies. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + * \sa Bar3DSeries, Scatter3DSeries, Surface3DSeries, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty Abstract3DSeries.SeriesType Abstract3DSeries::type + * The type of the series. + */ + +/*! + * \qmlproperty string Abstract3DSeries::itemLabelFormat + * + * Label format for data items in this series. This format is used for single item labels, + * for example, when an item is selected. How the format is interpreted depends on series type. See + * each series class documentation for more information. + */ + +/*! + * \qmlproperty bool Abstract3DSeries::visible + * Sets the visibility of the series. If false, the series is not rendered. + */ + +/*! + * \enum QAbstract3DSeries::SeriesType + * + * Type of the series. + * + * \value SeriesTypeNone + * No series type. + * \value SeriesTypeBar + * Series type for Q3DBars. + * \value SeriesTypeScatter + * Series type for Q3DScatter. + * \value SeriesTypeSurface + * Series type for Q3DSurface. + */ + +/*! + * \internal + */ +QAbstract3DSeries::QAbstract3DSeries(QAbstract3DSeriesPrivate *d, QObject *parent) : + QObject(parent), + d_ptr(d) +{ +} + +/*! + * Destroys QAbstract3DSeries. + */ +QAbstract3DSeries::~QAbstract3DSeries() +{ +} + +/*! + * \property QAbstract3DSeries::type + * + * The type of the series. + */ +QAbstract3DSeries::SeriesType QAbstract3DSeries::type() const +{ + return d_ptr->m_type; +} + +/*! + * \property QAbstract3DSeries::itemLabelFormat + * + * Sets label \a format for data items in this series. This format is used for single item labels, + * for example, when an item is selected. How the format is interpreted depends on series type. See + * each series class documentation for more information. + * + * \sa QBar3DSeries, Q3DScatterSeries, Q3DSurfaceSeries + */ +void QAbstract3DSeries::setItemLabelFormat(const QString &format) +{ + if (format != itemLabelFormat()) { + d_ptr->setItemLabelFormat(format); + emit itemLabelFormatChanged(format); + } +} + +QString QAbstract3DSeries::itemLabelFormat() const +{ + return d_ptr->m_itemLabelFormat; +} + +/*! + * \property QAbstract3DSeries::visible + * + * Sets the visibility of the series. If \a visible is false, the series is not rendered. + * Defaults to true. + */ +void QAbstract3DSeries::setVisible(bool visible) +{ + d_ptr->m_visible = visible; + emit visibilityChanged(visible); +} + +bool QAbstract3DSeries::isVisible() const +{ + return d_ptr->m_visible; +} + +// QAbstract3DSeriesPrivate + +QAbstract3DSeriesPrivate::QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type) + : QObject(0), + q_ptr(q), + m_type(type), + m_dataProxy(0), + m_visible(true), + m_controller(0) +{ +} + +QAbstract3DSeriesPrivate::~QAbstract3DSeriesPrivate() +{ +} + +void QAbstract3DSeriesPrivate::setItemLabelFormat(const QString &format) +{ + m_itemLabelFormat = format; +} + +QAbstractDataProxy *QAbstract3DSeriesPrivate::dataProxy() const +{ + return m_dataProxy; +} + +void QAbstract3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy && proxy != m_dataProxy && !proxy->d_ptr->series()); + + delete m_dataProxy; + m_dataProxy = proxy; + + proxy->d_ptr->setSeries(q_ptr); // also sets parent + + if (m_controller) + connectControllerAndProxy(m_controller); +} + +void QAbstract3DSeriesPrivate::setController(Abstract3DController *controller) +{ + connectControllerAndProxy(controller); + m_controller = controller; + q_ptr->setParent(controller); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h new file mode 100644 index 00000000..3f20a161 --- /dev/null +++ b/src/datavisualization/data/qabstract3dseries.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QABSTRACT3DSERIES_H +#define QABSTRACT3DSERIES_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QObject> +#include <QScopedPointer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstract3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QAbstract3DSeries : public QObject +{ + Q_OBJECT + Q_ENUMS(SeriesType) + Q_PROPERTY(SeriesType type READ type) + Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged) + +public: + enum SeriesType { + SeriesTypeNone = 0, + SeriesTypeBar = 1, + SeriesTypeScatter = 2, + SeriesTypeSurface = 4 + }; + +protected: + explicit QAbstract3DSeries(QAbstract3DSeriesPrivate *d, QObject *parent = 0); + +public: + virtual ~QAbstract3DSeries(); + + SeriesType type() const; + + void setItemLabelFormat(const QString &format); + QString itemLabelFormat() const; + + void setVisible(bool visible); + bool isVisible() const; + +signals: + void itemLabelFormatChanged(QString format); + void visibilityChanged(bool visible); + +protected: + QScopedPointer<QAbstract3DSeriesPrivate> d_ptr; + +// QDataVis::ColorStyle m_colorStyle; +// QColor m_objectColor; +// QLinearGradient m_objectGradient; +// QColor m_singleHighlightColor; +// QLinearGradient m_singleHighlightGradient; +// QColor m_multiHighlightColor; +// QLinearGradient m_multiHighlightGradient; + +private: + Q_DISABLE_COPY(QAbstract3DSeries) + + friend class Abstract3DController; + friend class Bars3DController; + friend class Surface3DController; + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qabstract3dseries_p.h b/src/datavisualization/data/qabstract3dseries_p.h new file mode 100644 index 00000000..478fe6bb --- /dev/null +++ b/src/datavisualization/data/qabstract3dseries_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "datavisualizationglobal_p.h" +#include "qabstract3dseries.h" +#include <QString> + +#ifndef QABSTRACT3DSERIES_P_H +#define QABSTRACT3DSERIES_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataProxy; +class Abstract3DController; + +class QAbstract3DSeriesPrivate : public QObject +{ + Q_OBJECT +public: + QAbstract3DSeriesPrivate(QAbstract3DSeries *q, QAbstract3DSeries::SeriesType type); + virtual ~QAbstract3DSeriesPrivate(); + + void setItemLabelFormat(const QString &format); + + QAbstractDataProxy *dataProxy() const; + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void setController(Abstract3DController *controller); + virtual void connectControllerAndProxy(Abstract3DController *newController) = 0; + +protected: + QAbstract3DSeries *q_ptr; + QAbstract3DSeries::SeriesType m_type; + QString m_itemLabelFormat; + QAbstractDataProxy *m_dataProxy; + bool m_visible; + Abstract3DController *m_controller; + +private: + friend class QAbstract3DSeries; + friend class Abstract3DController; + friend class Bars3DController; + friend class Surface3DController; + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QAbstract3DSeries_P_H diff --git a/src/datavisualization/data/qabstractdataproxy.cpp b/src/datavisualization/data/qabstractdataproxy.cpp index b44f365e..fa0934c3 100644 --- a/src/datavisualization/data/qabstractdataproxy.cpp +++ b/src/datavisualization/data/qabstractdataproxy.cpp @@ -18,6 +18,7 @@ #include "qabstractdataproxy.h" #include "qabstractdataproxy_p.h" +#include "qabstract3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -49,14 +50,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! - * \qmlproperty string AbstractDataProxy::itemLabelFormat - * - * Label format for data items in this proxy. This format is used for single item labels, - * for example, when an item is selected. How the format is interpreted depends on proxy type. See - * each proxy class documentation for more information. - */ - -/*! * \enum QAbstractDataProxy::DataType * * Data type of the proxy. @@ -97,44 +90,13 @@ QAbstractDataProxy::DataType QAbstractDataProxy::type() const return d_ptr->m_type; } -/*! - * \property QAbstractDataProxy::itemLabelFormat - * - * Sets label \a format for data items in this proxy. This format is used for single item labels, - * for example, when an item is selected. How the format is interpreted depends on proxy type. See - * each proxy class documentation for more information. - * - * \sa QBarDataProxy, QScatterDataProxy, QSurfaceDataProxy - */ -void QAbstractDataProxy::setItemLabelFormat(const QString &format) -{ - if (format != itemLabelFormat()) { - d_ptr->setItemLabelFormat(format); - emit itemLabelFormatChanged(format); - } -} - -/*! - * \return label format for data items in this proxy. - */ -QString QAbstractDataProxy::itemLabelFormat() const -{ - return d_ptr->m_itemLabelFormat; -} - -/*! - * \fn void QAbstractDataProxy::itemLabelFormatChanged(QString format) - * - * Emitted when label format changes. - */ - // QAbstractDataProxyPrivate QAbstractDataProxyPrivate::QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type) : QObject(0), q_ptr(q), m_type(type), - m_isDefaultProxy(false) + m_series(0) { } @@ -142,9 +104,10 @@ QAbstractDataProxyPrivate::~QAbstractDataProxyPrivate() { } -void QAbstractDataProxyPrivate::setItemLabelFormat(const QString &format) +void QAbstractDataProxyPrivate::setSeries(QAbstract3DSeries *series) { - m_itemLabelFormat = format; + setParent(series); + m_series = series; } QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstractdataproxy.h b/src/datavisualization/data/qabstractdataproxy.h index d7793824..b493052f 100644 --- a/src/datavisualization/data/qabstractdataproxy.h +++ b/src/datavisualization/data/qabstractdataproxy.h @@ -32,7 +32,6 @@ class QT_DATAVISUALIZATION_EXPORT QAbstractDataProxy : public QObject Q_OBJECT Q_ENUMS(DataType) Q_PROPERTY(DataType type READ type) - Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged) public: enum DataType { @@ -50,22 +49,17 @@ public: DataType type() const; - void setItemLabelFormat(const QString &format); - QString itemLabelFormat() const; - -signals: - void itemLabelFormatChanged(QString format); - protected: QScopedPointer<QAbstractDataProxyPrivate> d_ptr; private: Q_DISABLE_COPY(QAbstractDataProxy) - friend class Abstract3DController; - friend class Bars3DController; - friend class Scatter3DController; - friend class Surface3DController; + friend class QAbstract3DSeriesPrivate; +// friend class Abstract3DController; +// friend class Bars3DController; +// friend class Scatter3DController; +// friend class Surface3DController; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstractdataproxy_p.h b/src/datavisualization/data/qabstractdataproxy_p.h index 4aa1b678..90504ccb 100644 --- a/src/datavisualization/data/qabstractdataproxy_p.h +++ b/src/datavisualization/data/qabstractdataproxy_p.h @@ -35,6 +35,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE +class QAbstract3DSeries; + class QAbstractDataProxyPrivate : public QObject { Q_OBJECT @@ -42,16 +44,13 @@ public: QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type); virtual ~QAbstractDataProxyPrivate(); - void setItemLabelFormat(const QString &format); - - inline bool isDefaultProxy() { return m_isDefaultProxy; } - inline void setDefaultProxy(bool isDefault) { m_isDefaultProxy = isDefault; } + inline QAbstract3DSeries *series() { return m_series; } + virtual void setSeries(QAbstract3DSeries *series); protected: QAbstractDataProxy *q_ptr; QAbstractDataProxy::DataType m_type; - QString m_itemLabelFormat; - bool m_isDefaultProxy; + QAbstract3DSeries *m_series; private: friend class QAbstractDataProxy; diff --git a/src/datavisualization/data/qbar3dseries.cpp b/src/datavisualization/data/qbar3dseries.cpp new file mode 100644 index 00000000..c04f8ca2 --- /dev/null +++ b/src/datavisualization/data/qbar3dseries.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qbar3dseries_p.h" +#include "bars3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QBar3DSeries + * \inmodule QtDataVisualization + * \brief Base series class for Q3DBars. + * \since Qt Data Visualization 1.0 + * + * QBar3DSeries manages the series specific visual elements, as well as series data + * (via data proxy). + * + * If no data proxy is set explicitly for the series, QBar3DSeries creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it are destroyed. + * + * QBar3DSeries optionally keeps track of row and column labels, which Q3DCategoryAxis can utilize + * to show axis labels. The row and column labels are stored in separate array from the data and + * row manipulation methods provide an alternate versions that don't affect the row labels. + * This enables the option of having row labels that relate to the position of the data in the + * array rather than the data itself. + * + * QBar3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat(): + * \table + * \row + * \li @rowTitle \li Title from row axis + * \row + * \li @colTitle \li Title from column axis + * \row + * \li @valueTitle \li Title from value axis + * \row + * \li @rowIdx \li Visible row index + * \row + * \li @colIdx \li Visible Column index + * \row + * \li @rowLabel \li Label from row axis + * \row + * \li @colLabel \li Label from column axis + * \row + * \li @valueLabel \li Item value formatted using the same format the value axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li %<format spec> \li Item value in specified format. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Bar3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QBar3DSeries + * \inherits Abstract3DSeries + * \brief Base series type for Bars3D. + * + * This type manages the series specific visual elements, as well as series data + * (via data proxy). + * + * For more complete description, see QBar3DSeries. + * + * \sa {Qt Data Visualization Data Handling} + */ + + +/*! + * Constructs QBar3DSeries with the given \a parent. + */ +QBar3DSeries::QBar3DSeries(QObject *parent) : + QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent) +{ + // Default proxy + dptr()->setDataProxy(new QBarDataProxy); +} + +QBar3DSeries::QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent) : + QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent) +{ + dptr()->setDataProxy(dataProxy); +} + +/*! + * \internal + */ +QBar3DSeries::QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent) : + QAbstract3DSeries(d, parent) +{ +} + +/*! + * Destroys QBar3DSeries. + */ +QBar3DSeries::~QBar3DSeries() +{ +} + +/*! + * \property QBar3DSeries::dataProxy + * + * This property holds the active data \a proxy. The series assumes ownership of any proxy set to + * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or + * set to another series. + */ +void QBar3DSeries::setDataProxy(QBarDataProxy *proxy) +{ + d_ptr->setDataProxy(proxy); +} + +QBarDataProxy *QBar3DSeries::dataProxy() const +{ + return static_cast<QBarDataProxy *>(d_ptr->dataProxy()); +} + +/*! + * \internal + */ +QBar3DSeriesPrivate *QBar3DSeries::dptr() +{ + return static_cast<QBar3DSeriesPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QBar3DSeriesPrivate *QBar3DSeries::dptrc() const +{ + return static_cast<const QBar3DSeriesPrivate *>(d_ptr.data()); +} + +// QBar3DSeriesPrivate + +QBar3DSeriesPrivate::QBar3DSeriesPrivate(QBar3DSeries *q) + : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeBar) +{ + m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); +} + +QBar3DSeriesPrivate::~QBar3DSeriesPrivate() +{ +} + +QBar3DSeries *QBar3DSeriesPrivate::qptr() +{ + return static_cast<QBar3DSeries *>(q_ptr); +} + +void QBar3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar); + + QAbstract3DSeriesPrivate::setDataProxy(proxy); + + emit qptr()->dataProxyChanged(static_cast<QBarDataProxy *>(proxy)); +} + +void QBar3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController) +{ + QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_dataProxy); + + if (m_controller && barDataProxy) { + //Disconnect old controller/old proxy + QObject::disconnect(barDataProxy, 0, m_controller, 0); + QObject::disconnect(q_ptr, 0, m_controller, 0); + } + + if (newController && barDataProxy) { + Bars3DController *controller = static_cast<Bars3DController *>(newController); + + QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, controller, + &Bars3DController::handleArrayReset); + QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, controller, + &Bars3DController::handleRowsAdded); + QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, controller, + &Bars3DController::handleRowsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, controller, + &Bars3DController::handleRowsRemoved); + QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, controller, + &Bars3DController::handleRowsInserted); + QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, controller, + &Bars3DController::handleItemChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, controller, + &Bars3DController::handleDataRowLabelsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, controller, + &Bars3DController::handleDataColumnLabelsChanged); + + QObject::connect(q_ptr, &QAbstract3DSeries::visibilityChanged, controller, + &Abstract3DController::handleSeriesVisibilityChanged); + + // Always clear selection on proxy change + // TODO: setSelectedBar(noSelectionPoint()); + + newController->handleSeriesVisibilityChanged(m_visible); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qbar3dseries.h b/src/datavisualization/data/qbar3dseries.h new file mode 100644 index 00000000..ebb37838 --- /dev/null +++ b/src/datavisualization/data/qbar3dseries.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QBAR3DSERIES_H +#define QBAR3DSERIES_H + +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qbardataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBar3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QBar3DSeries : public QAbstract3DSeries +{ + Q_OBJECT + Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged) + +public: + explicit QBar3DSeries(QObject *parent = 0); + explicit QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent = 0); + virtual ~QBar3DSeries(); + + void setDataProxy(QBarDataProxy *proxy); + QBarDataProxy *dataProxy() const; + +signals: + void dataProxyChanged(QBarDataProxy *proxy); + +protected: + explicit QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent = 0); + QBar3DSeriesPrivate *dptr(); + const QBar3DSeriesPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QBar3DSeries) + + friend class Bars3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qbar3dseries_p.h b/src/datavisualization/data/qbar3dseries_p.h new file mode 100644 index 00000000..3ed95a69 --- /dev/null +++ b/src/datavisualization/data/qbar3dseries_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QBAR3DSERIES_P_H +#define QBAR3DSERIES_P_H + +#include "qbar3dseries.h" +#include "qabstract3dseries_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBar3DSeriesPrivate : public QAbstract3DSeriesPrivate +{ + Q_OBJECT +public: + QBar3DSeriesPrivate(QBar3DSeries *q); + virtual ~QBar3DSeriesPrivate(); + + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void connectControllerAndProxy(Abstract3DController *newController); +private: + QBar3DSeries *qptr(); + +private: + friend class QBar3DSeries; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qbardataproxy.cpp b/src/datavisualization/data/qbardataproxy.cpp index 13517b4b..26c3a36a 100644 --- a/src/datavisualization/data/qbardataproxy.cpp +++ b/src/datavisualization/data/qbardataproxy.cpp @@ -18,6 +18,7 @@ #include "qbardataproxy.h" #include "qbardataproxy_p.h" +#include "qbar3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -110,6 +111,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! + * \qmlproperty Bar3DSeries BarDataProxy::series + * + * The series this proxy is attached to. + */ + +/*! * Constructs QBarDataProxy with the given \a parent. */ QBarDataProxy::QBarDataProxy(QObject *parent) : @@ -133,6 +140,16 @@ QBarDataProxy::~QBarDataProxy() } /*! + * \property QBarDataProxy::series + * + * The series this proxy is attached to. + */ +QBar3DSeries *QBarDataProxy::series() +{ + return static_cast<QBar3DSeries *>(d_ptr->series()); +} + +/*! * Clears the existing array and row and column labels. */ void QBarDataProxy::resetArray() @@ -482,7 +499,6 @@ QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q) : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar), m_dataArray(new QBarDataArray) { - m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); } QBarDataProxyPrivate::~QBarDataProxyPrivate() @@ -704,4 +720,11 @@ QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endR return limits; } +void QBarDataProxyPrivate::setSeries(QAbstract3DSeries *series) +{ + QAbstractDataProxyPrivate::setSeries(series); + QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series); + emit qptr()->seriesChanged(barSeries); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h index 758700df..e97e6a85 100644 --- a/src/datavisualization/data/qbardataproxy.h +++ b/src/datavisualization/data/qbardataproxy.h @@ -30,6 +30,7 @@ typedef QVector<QBarDataItem> QBarDataRow; typedef QList<QBarDataRow *> QBarDataArray; class QBarDataProxyPrivate; +class QBar3DSeries; class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy { @@ -38,6 +39,7 @@ class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy Q_PROPERTY(int rowCount READ rowCount) Q_PROPERTY(QStringList rowLabels READ rowLabels WRITE setRowLabels NOTIFY rowLabelsChanged) Q_PROPERTY(QStringList columnLabels READ columnLabels WRITE setColumnLabels NOTIFY columnLabelsChanged) + Q_PROPERTY(QBar3DSeries *series READ series NOTIFY seriesChanged) public: explicit QBarDataProxy(QObject *parent = 0); virtual ~QBarDataProxy(); @@ -51,6 +53,7 @@ public: * individual bar requires allocating additional data object for the bar. */ + QBar3DSeries *series(); int rowCount() const; QStringList rowLabels() const; @@ -113,6 +116,7 @@ signals: void rowLabelsChanged(); void columnLabelsChanged(); + void seriesChanged(QBar3DSeries *series); protected: explicit QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent = 0); diff --git a/src/datavisualization/data/qbardataproxy_p.h b/src/datavisualization/data/qbardataproxy_p.h index 4d51bd5b..84726a02 100644 --- a/src/datavisualization/data/qbardataproxy_p.h +++ b/src/datavisualization/data/qbardataproxy_p.h @@ -56,6 +56,8 @@ public: QPair<GLfloat, GLfloat> limitValues(int startRow, int startColumn, int rowCount, int columnCount) const; + virtual void setSeries(QAbstract3DSeries *series); + private: QBarDataProxy *qptr(); void clearRow(int rowIndex); diff --git a/src/datavisualization/data/qscatter3dseries.cpp b/src/datavisualization/data/qscatter3dseries.cpp new file mode 100644 index 00000000..2fe61cff --- /dev/null +++ b/src/datavisualization/data/qscatter3dseries.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qscatter3dseries_p.h" +#include "scatter3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QScatter3DSeries + * \inmodule QtDataVisualization + * \brief Base series class for Q3DScatter. + * \since Qt Data Visualization 1.0 + * + * QScatter3DSeries manages the series specific visual elements, as well as series data + * (via data proxy). + * + * If no data proxy is set explicitly for the series, QScatter3DSeries creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it are destroyed. + * + * QScatter3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat(): + * \table + * \row + * \li @xTitle \li Title from X axis + * \row + * \li @yTitle \li Title from Y axis + * \row + * \li @zTitle \li Title from Z axis + * \row + * \li @xLabel \li Item value formatted using the same format the X axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @yLabel \li Item value formatted using the same format the Y axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @zLabel \li Item value formatted using the same format the Z axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Scatter3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QScatter3DSeries + * \inherits Abstract3DSeries + * \brief Base series type for Scatter3D. + * + * This type manages the series specific visual elements, as well as series data + * (via data proxy). + * + * For more complete description, see QScatter3DSeries. + * + * \sa {Qt Data Visualization Data Handling} + */ + + +/*! + * Constructs QScatter3DSeries with the given \a parent. + */ +QScatter3DSeries::QScatter3DSeries(QObject *parent) : + QAbstract3DSeries(new QScatter3DSeriesPrivate(this), parent) +{ + // Default proxy + dptr()->setDataProxy(new QScatterDataProxy); +} + +QScatter3DSeries::QScatter3DSeries(QScatterDataProxy *dataProxy, QObject *parent) : + QAbstract3DSeries(new QScatter3DSeriesPrivate(this), parent) +{ + dptr()->setDataProxy(dataProxy); +} + +/*! + * \internal + */ +QScatter3DSeries::QScatter3DSeries(QScatter3DSeriesPrivate *d, QObject *parent) : + QAbstract3DSeries(d, parent) +{ +} + +/*! + * Destroys QScatter3DSeries. + */ +QScatter3DSeries::~QScatter3DSeries() +{ +} + +/*! + * \property QScatter3DSeries::dataProxy + * + * This property holds the active data \a proxy. The series assumes ownership of any proxy set to + * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or + * set to another series. + */ +void QScatter3DSeries::setDataProxy(QScatterDataProxy *proxy) +{ + d_ptr->setDataProxy(proxy); +} + +QScatterDataProxy *QScatter3DSeries::dataProxy() const +{ + return static_cast<QScatterDataProxy *>(d_ptr->dataProxy()); +} + +/*! + * \internal + */ +QScatter3DSeriesPrivate *QScatter3DSeries::dptr() +{ + return static_cast<QScatter3DSeriesPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QScatter3DSeriesPrivate *QScatter3DSeries::dptrc() const +{ + return static_cast<const QScatter3DSeriesPrivate *>(d_ptr.data()); +} + +// QScatter3DSeriesPrivate + +QScatter3DSeriesPrivate::QScatter3DSeriesPrivate(QScatter3DSeries *q) + : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeScatter) +{ + m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); +} + +QScatter3DSeriesPrivate::~QScatter3DSeriesPrivate() +{ +} + +QScatter3DSeries *QScatter3DSeriesPrivate::qptr() +{ + return static_cast<QScatter3DSeries *>(q_ptr); +} + +void QScatter3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter); + + QAbstract3DSeriesPrivate::setDataProxy(proxy); + + emit qptr()->dataProxyChanged(static_cast<QScatterDataProxy *>(proxy)); +} + +void QScatter3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController) +{ + QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_dataProxy); + + if (m_controller && scatterDataProxy) { + //Disconnect old controller/old proxy + QObject::disconnect(scatterDataProxy, 0, m_controller, 0); + QObject::disconnect(q_ptr, 0, m_controller, 0); + } + + if (newController && scatterDataProxy) { + Scatter3DController *controller = static_cast<Scatter3DController *>(newController); + + QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset, + controller, &Scatter3DController::handleArrayReset); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded, + controller, &Scatter3DController::handleItemsAdded); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged, + controller, &Scatter3DController::handleItemsChanged); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved, + controller, &Scatter3DController::handleItemsRemoved); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted, + controller, &Scatter3DController::handleItemsInserted); + + QObject::connect(q_ptr, &QAbstract3DSeries::visibilityChanged, controller, + &Abstract3DController::handleSeriesVisibilityChanged); + + // Always clear selection on proxy change + // TODO: setSelectedScatter(noSelectionPoint()); + + newController->handleSeriesVisibilityChanged(m_visible); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qscatter3dseries.h b/src/datavisualization/data/qscatter3dseries.h new file mode 100644 index 00000000..bb24f79a --- /dev/null +++ b/src/datavisualization/data/qscatter3dseries.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSCATTER3DSERIES_H +#define QSCATTER3DSERIES_H + +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qscatterdataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatter3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QScatter3DSeries : public QAbstract3DSeries +{ + Q_OBJECT + Q_PROPERTY(QScatterDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged) + +public: + explicit QScatter3DSeries(QObject *parent = 0); + explicit QScatter3DSeries(QScatterDataProxy *dataProxy, QObject *parent = 0); + virtual ~QScatter3DSeries(); + + void setDataProxy(QScatterDataProxy *proxy); + QScatterDataProxy *dataProxy() const; + +signals: + void dataProxyChanged(QScatterDataProxy *proxy); + +protected: + explicit QScatter3DSeries(QScatter3DSeriesPrivate *d, QObject *parent = 0); + QScatter3DSeriesPrivate *dptr(); + const QScatter3DSeriesPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QScatter3DSeries) + + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatter3dseries_p.h b/src/datavisualization/data/qscatter3dseries_p.h new file mode 100644 index 00000000..001fb00c --- /dev/null +++ b/src/datavisualization/data/qscatter3dseries_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSCATTER3DSERIES_P_H +#define QSCATTER3DSERIES_P_H + +#include "qscatter3dseries.h" +#include "qabstract3dseries_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatter3DSeriesPrivate : public QAbstract3DSeriesPrivate +{ + Q_OBJECT +public: + QScatter3DSeriesPrivate(QScatter3DSeries *q); + virtual ~QScatter3DSeriesPrivate(); + + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void connectControllerAndProxy(Abstract3DController *newController); +private: + QScatter3DSeries *qptr(); + +private: + friend class QScatter3DSeries; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatterdataproxy.cpp b/src/datavisualization/data/qscatterdataproxy.cpp index 85cbb4eb..149cb1ae 100644 --- a/src/datavisualization/data/qscatterdataproxy.cpp +++ b/src/datavisualization/data/qscatterdataproxy.cpp @@ -18,6 +18,7 @@ #include "qscatterdataproxy.h" #include "qscatterdataproxy_p.h" +#include "qscatter3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -80,6 +81,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! + * \qmlproperty Scatter3DSeries ScatterDataProxy::series + * + * The series this proxy is attached to. + */ + +/*! * Constructs QScatterDataProxy with the given \a parent. */ QScatterDataProxy::QScatterDataProxy(QObject *parent) : @@ -103,6 +110,16 @@ QScatterDataProxy::~QScatterDataProxy() } /*! + * \property QScatterDataProxy::series + * + * The series this proxy is attached to. + */ +QScatter3DSeries *QScatterDataProxy::series() +{ + return static_cast<QScatter3DSeries *>(d_ptr->series()); +} + +/*! * Takes ownership of the \a newArray. Clears the existing array if the \a newArray is * different from the existing array. If it's the same array, this just triggers arrayReset() * signal. @@ -277,7 +294,6 @@ QScatterDataProxyPrivate::QScatterDataProxyPrivate(QScatterDataProxy *q) : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeScatter), m_dataArray(new QScatterDataArray) { - m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)"); } QScatterDataProxyPrivate::~QScatterDataProxyPrivate() @@ -346,7 +362,7 @@ void QScatterDataProxyPrivate::removeItems(int index, int removeCount) m_dataArray->remove(index, removeCount); } -void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) +void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const { if (m_dataArray->isEmpty()) return; @@ -393,4 +409,16 @@ void QScatterDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV maxValues.setZ(maxZ); } +void QScatterDataProxyPrivate::setSeries(QAbstract3DSeries *series) +{ + QAbstractDataProxyPrivate::setSeries(series); + QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series); + emit qptr()->seriesChanged(scatterSeries); +} + +QScatterDataProxy *QScatterDataProxyPrivate::qptr() +{ + return static_cast<QScatterDataProxy *>(q_ptr); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qscatterdataproxy.h b/src/datavisualization/data/qscatterdataproxy.h index 178bc900..e17154c0 100644 --- a/src/datavisualization/data/qscatterdataproxy.h +++ b/src/datavisualization/data/qscatterdataproxy.h @@ -27,12 +27,14 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE typedef QVector<QScatterDataItem> QScatterDataArray; class QScatterDataProxyPrivate; +class QScatter3DSeries; class QT_DATAVISUALIZATION_EXPORT QScatterDataProxy : public QAbstractDataProxy { Q_OBJECT Q_PROPERTY(int itemCount READ itemCount) + Q_PROPERTY(QScatter3DSeries *series READ series NOTIFY seriesChanged) public: explicit QScatterDataProxy(QObject *parent = 0); @@ -46,6 +48,7 @@ public: * added in the future such as color requires allocating additional data object for the bar. */ + QScatter3DSeries *series(); int itemCount() const; const QScatterDataArray *array() const; const QScatterDataItem *itemAt(int index) const; @@ -69,6 +72,7 @@ signals: void itemsChanged(int startIndex, int count); void itemsRemoved(int startIndex, int count); void itemsInserted(int startIndex, int count); + void seriesChanged(QScatter3DSeries *series); protected: explicit QScatterDataProxy(QScatterDataProxyPrivate *d, QObject *parent = 0); diff --git a/src/datavisualization/data/qscatterdataproxy_p.h b/src/datavisualization/data/qscatterdataproxy_p.h index 24b5eb67..322c8937 100644 --- a/src/datavisualization/data/qscatterdataproxy_p.h +++ b/src/datavisualization/data/qscatterdataproxy_p.h @@ -51,9 +51,11 @@ public: void insertItems(int index, const QScatterDataArray &items); void removeItems(int index, int removeCount); - void limitValues(QVector3D &minValues, QVector3D &maxValues); + void limitValues(QVector3D &minValues, QVector3D &maxValues) const; + virtual void setSeries(QAbstract3DSeries *series); private: + QScatterDataProxy *qptr(); QScatterDataArray *m_dataArray; friend class QScatterDataProxy; diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp new file mode 100644 index 00000000..a4622580 --- /dev/null +++ b/src/datavisualization/data/qsurface3dseries.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qsurface3dseries_p.h" +#include "surface3dcontroller_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QSurface3DSeries + * \inmodule QtDataVisualization + * \brief Base series class for Q3DSurface. + * \since Qt Data Visualization 1.0 + * + * QSurface3DSeries manages the series specific visual elements, as well as series data + * (via data proxy). + * + * If no data proxy is set explicitly for the series, QSurface3DSeries creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it are destroyed. + * + * QSurface3DSeries supports the following format tags for QAbstract3DSeries::setItemLabelFormat(): + * \table + * \row + * \li @xTitle \li Title from X axis + * \row + * \li @yTitle \li Title from Y axis + * \row + * \li @zTitle \li Title from Z axis + * \row + * \li @xLabel \li Item value formatted using the same format as the X axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @yLabel \li Item value formatted using the same format as the Y axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @zLabel \li Item value formatted using the same format as the Z axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype Surface3DSeries + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QSurface3DSeries + * \inherits Abstract3DSeries + * \brief Base series type for Surfaces3D. + * + * This type manages the series specific visual elements, as well as series data + * (via data proxy). + * + * For more complete description, see QSurface3DSeries. + * + * \sa {Qt Data Visualization Data Handling} + */ + + +/*! + * Constructs QSurface3DSeries with the given \a parent. + */ +QSurface3DSeries::QSurface3DSeries(QObject *parent) : + QAbstract3DSeries(new QSurface3DSeriesPrivate(this), parent) +{ + // Default proxy + dptr()->setDataProxy(new QSurfaceDataProxy); +} + +QSurface3DSeries::QSurface3DSeries(QSurfaceDataProxy *dataProxy, QObject *parent) : + QAbstract3DSeries(new QSurface3DSeriesPrivate(this), parent) +{ + dptr()->setDataProxy(dataProxy); +} + +/*! + * \internal + */ +QSurface3DSeries::QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent) : + QAbstract3DSeries(d, parent) +{ +} + +/*! + * Destroys QSurface3DSeries. + */ +QSurface3DSeries::~QSurface3DSeries() +{ +} + +/*! + * \property QSurface3DSeries::dataProxy + * + * This property holds the active data \a proxy. The series assumes ownership of any proxy set to + * it and deletes any previously set proxy when a new one is added. The \a proxy cannot be null or + * set to another series. + */ +void QSurface3DSeries::setDataProxy(QSurfaceDataProxy *proxy) +{ + d_ptr->setDataProxy(proxy); +} + +QSurfaceDataProxy *QSurface3DSeries::dataProxy() const +{ + return static_cast<QSurfaceDataProxy *>(d_ptr->dataProxy()); +} + +/*! + * \internal + */ +QSurface3DSeriesPrivate *QSurface3DSeries::dptr() +{ + return static_cast<QSurface3DSeriesPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QSurface3DSeriesPrivate *QSurface3DSeries::dptrc() const +{ + return static_cast<const QSurface3DSeriesPrivate *>(d_ptr.data()); +} + +// QSurface3DSeriesPrivate + +QSurface3DSeriesPrivate::QSurface3DSeriesPrivate(QSurface3DSeries *q) + : QAbstract3DSeriesPrivate(q, QAbstract3DSeries::SeriesTypeSurface) +{ + m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)"); +} + +QSurface3DSeriesPrivate::~QSurface3DSeriesPrivate() +{ +} + +QSurface3DSeries *QSurface3DSeriesPrivate::qptr() +{ + return static_cast<QSurface3DSeries *>(q_ptr); +} + +void QSurface3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface); + + QAbstract3DSeriesPrivate::setDataProxy(proxy); + + emit qptr()->dataProxyChanged(static_cast<QSurfaceDataProxy *>(proxy)); +} + +void QSurface3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newController) +{ + QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_dataProxy); + + if (m_controller && surfaceDataProxy) { + //Disconnect old controller/old proxy + QObject::disconnect(surfaceDataProxy, 0, m_controller, 0); + QObject::disconnect(q_ptr, 0, m_controller, 0); + } + + if (newController && surfaceDataProxy) { + Surface3DController *controller = static_cast<Surface3DController *>(newController); + + QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, controller, + &Surface3DController::handleArrayReset); + + QObject::connect(q_ptr, &QAbstract3DSeries::visibilityChanged, controller, + &Abstract3DController::handleSeriesVisibilityChanged); + + // Always clear selection on proxy change + // TODO: setSelectedPoint(noSelectionPoint()); + + newController->handleSeriesVisibilityChanged(m_visible); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qsurface3dseries.h b/src/datavisualization/data/qsurface3dseries.h new file mode 100644 index 00000000..db432e41 --- /dev/null +++ b/src/datavisualization/data/qsurface3dseries.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSURFACE3DSERIES_H +#define QSURFACE3DSERIES_H + +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qsurfacedataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurface3DSeriesPrivate; + +class QT_DATAVISUALIZATION_EXPORT QSurface3DSeries : public QAbstract3DSeries +{ + Q_OBJECT + Q_PROPERTY(QSurfaceDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged) + +public: + explicit QSurface3DSeries(QObject *parent = 0); + explicit QSurface3DSeries(QSurfaceDataProxy *dataProxy, QObject *parent = 0); + virtual ~QSurface3DSeries(); + + void setDataProxy(QSurfaceDataProxy *proxy); + QSurfaceDataProxy *dataProxy() const; + +signals: + void dataProxyChanged(QSurfaceDataProxy *proxy); + +protected: + explicit QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent = 0); + QSurface3DSeriesPrivate *dptr(); + const QSurface3DSeriesPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QSurface3DSeries) + + friend class Surface3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qsurface3dseries_p.h b/src/datavisualization/data/qsurface3dseries_p.h new file mode 100644 index 00000000..6e5d9337 --- /dev/null +++ b/src/datavisualization/data/qsurface3dseries_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSURFACE3DSERIES_P_H +#define QSURFACE3DSERIES_P_H + +#include "qsurface3dseries.h" +#include "qabstract3dseries_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurface3DSeriesPrivate : public QAbstract3DSeriesPrivate +{ + Q_OBJECT +public: + QSurface3DSeriesPrivate(QSurface3DSeries *q); + virtual ~QSurface3DSeriesPrivate(); + + virtual void setDataProxy(QAbstractDataProxy *proxy); + virtual void connectControllerAndProxy(Abstract3DController *newController); +private: + QSurface3DSeries *qptr(); + +private: + friend class QSurface3DSeries; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index 7fe44464..e3c2714c 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -18,6 +18,7 @@ #include "qsurfacedataproxy.h" #include "qsurfacedataproxy_p.h" +#include "qsurface3dseries_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -94,6 +95,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE */ /*! + * \qmlproperty Surface3DSeries SurfaceDataProxy::series + * + * The series this proxy is attached to. + */ + +/*! * Constructs QSurfaceDataProxy with the given \a parent. */ QSurfaceDataProxy::QSurfaceDataProxy(QObject *parent) : @@ -117,6 +124,16 @@ QSurfaceDataProxy::~QSurfaceDataProxy() } /*! + * \property QSurfaceDataProxy::series + * + * The series this proxy is attached to. + */ +QSurface3DSeries *QSurfaceDataProxy::series() +{ + return static_cast<QSurface3DSeries *>(d_ptr->series()); +} + +/*! * Takes ownership of the \a newArray. Clears the existing array if the \a newArray is * different from the existing array. If it's the same array, this just triggers arrayReset() * signal. @@ -203,7 +220,6 @@ QSurfaceDataProxyPrivate::QSurfaceDataProxyPrivate(QSurfaceDataProxy *q) : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeSurface), m_dataArray(new QSurfaceDataArray) { - m_itemLabelFormat = QStringLiteral("@yLabel (@xLabel, @zLabel)"); } QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate() @@ -227,7 +243,7 @@ QSurfaceDataProxy *QSurfaceDataProxyPrivate::qptr() return static_cast<QSurfaceDataProxy *>(q_ptr); } -void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) +void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) const { qreal min = 0.0; qreal max = 0.0; @@ -286,4 +302,11 @@ void QSurfaceDataProxyPrivate::clearArray() delete m_dataArray; } +void QSurfaceDataProxyPrivate::setSeries(QAbstract3DSeries *series) +{ + QAbstractDataProxyPrivate::setSeries(series); + QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series); + emit qptr()->seriesChanged(surfaceSeries); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qsurfacedataproxy.h b/src/datavisualization/data/qsurfacedataproxy.h index 460fa437..ed594963 100644 --- a/src/datavisualization/data/qsurfacedataproxy.h +++ b/src/datavisualization/data/qsurfacedataproxy.h @@ -28,6 +28,7 @@ typedef QVector<QSurfaceDataItem> QSurfaceDataRow; typedef QList<QSurfaceDataRow *> QSurfaceDataArray; class QSurfaceDataProxyPrivate; +class QSurface3DSeries; class QT_DATAVISUALIZATION_EXPORT QSurfaceDataProxy : public QAbstractDataProxy { @@ -35,11 +36,13 @@ class QT_DATAVISUALIZATION_EXPORT QSurfaceDataProxy : public QAbstractDataProxy Q_PROPERTY(int rowCount READ rowCount) Q_PROPERTY(int columnCount READ columnCount) + Q_PROPERTY(QSurface3DSeries *series READ series NOTIFY seriesChanged) public: explicit QSurfaceDataProxy(QObject *parent = 0); virtual ~QSurfaceDataProxy(); + QSurface3DSeries *series(); int rowCount() const; int columnCount() const; const QSurfaceDataArray *array() const; @@ -49,6 +52,7 @@ public: signals: void arrayReset(); + void seriesChanged(QSurface3DSeries *series); protected: explicit QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent = 0); diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h index 4c8c2820..066df629 100644 --- a/src/datavisualization/data/qsurfacedataproxy_p.h +++ b/src/datavisualization/data/qsurfacedataproxy_p.h @@ -45,7 +45,9 @@ public: void resetArray(QSurfaceDataArray *newArray); - void limitValues(QVector3D &minValues, QVector3D &maxValues); + void limitValues(QVector3D &minValues, QVector3D &maxValues) const; + + virtual void setSeries(QAbstract3DSeries *series); protected: QSurfaceDataArray *m_dataArray; diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc index 59331bf9..989bcc9b 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc @@ -70,8 +70,3 @@ \qmlproperty bool AbstractGraph3D::backgroundVisible Background visibility. If false, background is not drawn. */ - -/*! - \qmlproperty string AbstractGraph3D::itemLabelFormat - Label format of single item labels, e.g. a selected datapoint. - */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc index c81e5aac..45324b8a 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc @@ -36,7 +36,7 @@ * * See \l{Qt Quick 2 Bars Example} for more thorough usage example. * - * \sa ItemModelBarDataProxy, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} + * \sa Bar3DSeries, ItemModelBarData, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} */ /*! @@ -53,14 +53,6 @@ */ /*! - * \qmlproperty BarDataProxy Bars3D::dataProxy - * The active data proxy. - * - * If a proxy is not given, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another proxy is explicitly set active via this property. - */ - -/*! * \qmlproperty CategoryAxis3D Bars3D::rowAxis * A user-defined row axis. * @@ -134,3 +126,20 @@ * Position of the selected bar in data window. Only one bar can be selected at a time. * To clear selection, specify an illegal position, e.g. Qt.point(-1.0, -1.0). */ + +/*! + * \qmlproperty list<QBar3DSeries> seriesList + * This property holds the series of the graph. + * By default, this property contains an empty list. + * To set the series, either use the addSeries() function or define them as children of the graph. + */ + +/*! + * \qmlmethod void addSeries(QBar3DSeries *series) + * Add the \a series to the graph. + */ + +/*! + * \qmlmethod void removeSeries(QBar3DSeries *series) + * Remove the \a series from the graph. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc index e9661b60..7ad9d470 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc @@ -36,7 +36,7 @@ See \l{Qt Quick 2 Scatter Example} for more thorough usage example. - \sa ItemModelScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes} + \sa Scatter3DSeries, ScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes} */ /*! @@ -53,14 +53,6 @@ */ /*! - \qmlproperty ScatterDataProxy Scatter3D::dataProxy - The active data proxy. - - If a proxy is not given, a temporary default proxy is created and activated. - This temporary proxy is destroyed if another proxy is explicitly set active via this property. - */ - -/*! \qmlproperty ValueAxis3D Scatter3D::axisX A user-defined X axis. @@ -109,3 +101,20 @@ Selects an item in the \a index. Only one item can be selected at a time. To clear selection, specify an illegal \a index, e.g. -1. */ + +/*! + * \qmlproperty list<QScatter3DSeries> seriesList + * This property holds the series of the graph. + * By default, this property contains an empty list. + * To set the series, either use the addSeries() function or define them as children of the graph. + */ + +/*! + * \qmlmethod void addSeries(QScatter3DSeries *series) + * Add the \a series to the graph. + */ + +/*! + * \qmlmethod void removeSeries(QScatter3DSeries *series) + * Remove the \a series from the graph. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc index 55a0d1d1..d1422b10 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc @@ -36,15 +36,7 @@ See \l{Qt Quick 2 Surface Example} for more thorough usage example. - \sa ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes} - */ - -/*! - \qmlproperty SurfaceDataProxy Surface3D::dataProxy - The active data proxy. - - If a proxy is not given, a temporary default proxy is created and activated. - This temporary proxy is destroyed if another proxy is explicitly set active via this property. + \sa Surface3DSeries, ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes} */ /*! @@ -99,7 +91,25 @@ \qmlproperty point Surface3D::selectedPoint Selects a surface grid point in a \a position. The position is the (row, column) position in - the data array of the active data proxy. + the data array of the series. Only one point can be selected at a time. To clear selection, specify an illegal \a position, e.g. (-1, -1). */ + +/*! + * \qmlproperty list<QSurface3DSeries> seriesList + * This property holds the series of the graph. + * By default, this property contains an empty list. + * To set the series, either use the addSeries() function or define them as children of the graph. + * \note The surface graph currently supports only a single series at a time. + */ + +/*! + * \qmlmethod void addSeries(QSurface3DSeries *series) + * Add the \a series to the graph. + */ + +/*! + * \qmlmethod void removeSeries(QSurface3DSeries *series) + * Remove the \a series from the graph. + */ diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index ab2d0ac2..c1f3a4b7 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -27,6 +27,7 @@ #include "qabstractdataproxy_p.h" #include "qabstract3dinputhandler_p.h" #include "qtouch3dinputhandler.h" +#include "qabstract3dseries_p.h" #include <QThread> @@ -50,7 +51,6 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : m_axisZ(0), m_renderer(0), m_isDataDirty(true), - m_data(0), m_renderPending(false) { // Set initial theme @@ -82,11 +82,39 @@ Abstract3DController::~Abstract3DController() delete m_scene; } +/** + * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards. + * @param renderer Renderer to be used. + */ void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) { m_renderer = renderer; } +void Abstract3DController::addSeries(QAbstract3DSeries *series) +{ + if (series && !m_seriesList.contains(series)) { + m_seriesList.append(series); + series->d_ptr->setController(this); + } +} + +void Abstract3DController::removeSeries(QAbstract3DSeries *series) +{ + if (series && series->d_ptr->m_controller == this) { + m_seriesList.removeAll(series); + series->d_ptr->setController(0); + } +} + +QList<QAbstract3DSeries *> Abstract3DController::seriesList() +{ + return m_seriesList; +} + +/** + * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering. + */ void Abstract3DController::synchDataToRenderer() { // If we don't have a renderer, don't do anything @@ -334,6 +362,12 @@ void Abstract3DController::synchDataToRenderer() valueAxisZ->labelFormat()); } } + + // TODO: Another (per-series?) flag about series visuals being dirty? + if (m_isDataDirty) { + m_renderer->updateSeriesData(m_seriesList); + m_isDataDirty = false; + } } void Abstract3DController::render(const GLuint defaultFboHandle) @@ -582,64 +616,6 @@ QList<Q3DAbstractAxis *> Abstract3DController::axes() const return m_axes; } -QAbstractDataProxy *Abstract3DController::activeDataProxy() const -{ - return m_data; -} - -void Abstract3DController::addDataProxy(QAbstractDataProxy *proxy) -{ - Q_ASSERT(proxy); - Abstract3DController *owner = qobject_cast<Abstract3DController *>(proxy->parent()); - if (owner != this) { - Q_ASSERT_X(!owner, "addDataProxy", "Proxy already attached to a graph."); - proxy->setParent(this); - } - if (!m_dataProxies.contains(proxy)) - m_dataProxies.append(proxy); -} - -void Abstract3DController::releaseDataProxy(QAbstractDataProxy *proxy) -{ - if (proxy && m_dataProxies.contains(proxy)) { - // Clear the default status from released default proxies - if (proxy->d_ptr->isDefaultProxy()) - proxy->d_ptr->setDefaultProxy(false); - - // If the proxy is in use, replace it with a temporary one - if (m_data == proxy) - setActiveDataProxy(0); - - m_dataProxies.removeAll(proxy); - proxy->setParent(0); - } -} - -QList<QAbstractDataProxy *> Abstract3DController::dataProxies() const -{ - return m_dataProxies; -} - -void Abstract3DController::setActiveDataProxy(QAbstractDataProxy *proxy) -{ - // If existing proxy is the default proxy, delete it - if (m_data) { - if (m_data->d_ptr->isDefaultProxy()) { - m_dataProxies.removeAll(m_data); - delete m_data; - } else { - // Disconnect the old proxy from use - QObject::disconnect(m_data, 0, this, 0); - } - } - - // Assume ownership and activate - addDataProxy(proxy); - m_data = proxy; - m_isDataDirty = true; - emitNeedRender(); -} - void Abstract3DController::addInputHandler(QAbstract3DInputHandler *inputHandler) { Q_ASSERT(inputHandler); @@ -1113,6 +1089,13 @@ void Abstract3DController::handleInputPositionChanged(const QPoint &position) emitNeedRender(); } +void Abstract3DController::handleSeriesVisibilityChanged(bool visible) +{ + Q_UNUSED(visible) + + handleSeriesVisibilityChangedBySender(sender()); +} + void Abstract3DController::handleRequestShadowQuality(QDataVis::ShadowQuality quality) { setShadowQuality(quality); @@ -1136,6 +1119,14 @@ void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender) emitNeedRender(); } +void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender) +{ + Q_UNUSED(sender) + + m_isDataDirty = true; + emitNeedRender(); +} + void Abstract3DController::setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis, Q3DAbstractAxis **axisPtr) { diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index d68d33e2..39e0abe6 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -47,6 +47,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class CameraHelper; class Abstract3DRenderer; +class QAbstract3DSeries; struct Abstract3DChangeBitField { bool positionChanged : 1; @@ -195,32 +196,24 @@ protected: QList<Q3DAbstractAxis *> m_axes; // List of all added axes Abstract3DRenderer *m_renderer; bool m_isDataDirty; - - QAbstractDataProxy *m_data; - QList<QAbstractDataProxy *> m_dataProxies; - bool m_renderPending; + QList<QAbstract3DSeries *> m_seriesList; + explicit Abstract3DController(QRect boundRect, QObject *parent = 0); virtual ~Abstract3DController(); public: inline bool isInitialized() { return (m_renderer != 0); } - - /** - * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering. - */ virtual void synchDataToRenderer(); - virtual void render(const GLuint defaultFboHandle = 0); - - /** - * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards. - * @param renderer Renderer to be used. - */ void setRenderer(Abstract3DRenderer *renderer); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + QList<QAbstract3DSeries *> seriesList(); + // Size virtual void setSize(const int width, const int height); virtual const QSize size(); @@ -256,11 +249,6 @@ public: virtual void setActiveInputHandler(QAbstract3DInputHandler *inputHandler); virtual QAbstract3DInputHandler *activeInputHandler(); - virtual QAbstractDataProxy *activeDataProxy() const; - virtual void addDataProxy(QAbstractDataProxy *proxy); - virtual void releaseDataProxy(QAbstractDataProxy *proxy); - virtual QList<QAbstractDataProxy *> dataProxies() const; - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); virtual void updateDevicePixelRatio(qreal ratio); virtual int zoomLevel(); @@ -324,6 +312,9 @@ public: Q3DScene *scene(); + inline void setDataDirty() { m_isDataDirty = true; } + void emitNeedRender(); + virtual void mouseDoubleClickEvent(QMouseEvent *event); virtual void touchEvent(QTouchEvent *event); virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); @@ -339,6 +330,7 @@ public: virtual void handleAxisAutoAdjustRangeChangedInOrientation( Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0; virtual void handleAxisLabelFormatChangedBySender(QObject *sender); + virtual void handleSeriesVisibilityChangedBySender(QObject *sender); public slots: void handleAxisTitleChanged(const QString &title); @@ -350,6 +342,7 @@ public slots: void handleAxisLabelFormatChanged(const QString &format); void handleInputStateChanged(QDataVis::InputState state); void handleInputPositionChanged(const QPoint &position); + void handleSeriesVisibilityChanged(bool visible); // Renderer callback handlers void handleRequestShadowQuality(QDataVis::ShadowQuality quality); @@ -377,7 +370,6 @@ protected: virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation); Q3DValueAxis *createDefaultValueAxis(); Q3DCategoryAxis *createDefaultCategoryAxis(); - void emitNeedRender(); private: void setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis, diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index 1b1143fa..f639c6e3 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -23,6 +23,7 @@ #include "q3dscene_p.h" #include "q3dcamera_p.h" #include "q3dlight_p.h" +#include "qabstract3dseries_p.h" Q_DECLARE_METATYPE(QtDataVisualization::QDataVis::ShadowQuality) @@ -142,11 +143,6 @@ QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal valu return Utils::formatLabel(valueFormatArray, valueParamType, value); } -void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy) -{ - m_cachedItemLabelFormat = dataProxy->itemLabelFormat(); -} - QString Abstract3DRenderer::itemLabelFormat() const { return m_cachedItemLabelFormat; @@ -378,6 +374,13 @@ void Abstract3DRenderer::updateMultiHighlightGradient(const QLinearGradient &gra fixGradient(&m_cachedMultiHighlightGradient, &m_multiHighlightGradientTexture); } +void Abstract3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) +{ + // TODO: To series visuals update - just use first series format for now + if (seriesList.size()) + m_cachedItemLabelFormat = seriesList.at(0)->itemLabelFormat(); +} + AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation) { switch (orientation) { diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 838eb181..3c833956 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -99,7 +99,7 @@ protected: public: virtual ~Abstract3DRenderer(); - void updateDataModel(QAbstractDataProxy *dataProxy); + virtual void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); virtual void render(GLuint defaultFboHandle); diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 6d1ebbae..019a96be 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -23,6 +23,7 @@ #include "q3dvalueaxis_p.h" #include "q3dcategoryaxis_p.h" #include "qbardataproxy_p.h" +#include "qbar3dseries_p.h" #include <QMatrix4x4> #include <qmath.h> @@ -40,8 +41,6 @@ Bars3DController::Bars3DController(QRect boundRect) // Default bar type; specific to bars setBarType(QDataVis::MeshStyleBevelBars, false); - setActiveDataProxy(0); - // Setting a null axis creates a new default axis according to orientation and graph type. // Note: these cannot be set in the Abstract3DController constructor, as they will call virtual // functions implemented by subclasses. @@ -83,57 +82,11 @@ void Bars3DController::synchDataToRenderer() m_changeTracker.barSpecsChanged = false; } + // Needs to be done after data is set, as it needs to know the visual array. if (m_changeTracker.selectedBarChanged) { m_renderer->updateSelectedBar(m_selectedBar); m_changeTracker.selectedBarChanged = false; } - - if (m_isDataDirty) { - m_renderer->updateDataModel(static_cast<QBarDataProxy *>(m_data)); - m_isDataDirty = false; - } -} - -void Bars3DController::setActiveDataProxy(QAbstractDataProxy *proxy) -{ - // Setting null proxy indicates default proxy - if (!proxy) { - proxy = new QBarDataProxy; - proxy->d_ptr->setDefaultProxy(true); - } - - Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar); - - Abstract3DController::setActiveDataProxy(proxy); - - QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_data); - - QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, this, - &Bars3DController::handleArrayReset); - QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, this, - &Bars3DController::handleRowsAdded); - QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, this, - &Bars3DController::handleRowsChanged); - QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, this, - &Bars3DController::handleRowsRemoved); - QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, this, - &Bars3DController::handleRowsInserted); - QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, this, - &Bars3DController::handleItemChanged); - QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, this, - &Bars3DController::handleDataRowLabelsChanged); - QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, this, - &Bars3DController::handleDataColumnLabelsChanged); - - adjustAxisRanges(); - - // Always clear selection on proxy change - setSelectedBar(noSelectionPoint()); - - handleDataRowLabelsChanged(); - handleDataColumnLabelsChanged(); - m_isDataDirty = true; - emitNeedRender(); } void Bars3DController::handleArrayReset() @@ -196,22 +149,29 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) void Bars3DController::handleDataRowLabelsChanged() { - if (m_axisX && m_data) { + QBar3DSeries *firstSeries = 0; + if (m_seriesList.size()) + firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0)); + if (m_axisX && firstSeries && firstSeries->dataProxy()) { // Grab a sublist equal to data window (no need to have more labels in axis) int min = int(m_axisX->min()); int count = int(m_axisX->max()) - min + 1; - QStringList subList = static_cast<QBarDataProxy *>(m_data)->rowLabels().mid(min, count); + QStringList subList = firstSeries->dataProxy()->rowLabels().mid(min, count); static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList); } } void Bars3DController::handleDataColumnLabelsChanged() { - if (m_axisZ && m_data) { + QBar3DSeries *firstSeries = 0; + if (m_seriesList.size()) + firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0)); + if (m_axisZ && firstSeries && firstSeries->dataProxy()) { // Grab a sublist equal to data window (no need to have more labels in axis) int min = int(m_axisZ->min()); int count = int(m_axisZ->max()) - min + 1; - QStringList subList = static_cast<QBarDataProxy *>(m_data)->columnLabels().mid(min, count); + QStringList subList = static_cast<QBarDataProxy *>(firstSeries->dataProxy()) + ->columnLabels().mid(min, count); static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList); } } @@ -249,6 +209,55 @@ void Bars3DController::setAxisZ(Q3DAbstractAxis *axis) handleDataColumnLabelsChanged(); } +void Bars3DController::addSeries(QAbstract3DSeries *series) +{ + Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeBar); + + bool firstAdded = !m_seriesList.size(); + + Abstract3DController::addSeries(series); + + if (firstAdded) { + adjustAxisRanges(); + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); + + // TODO: Temp until selection by series is properly implemented + setSelectedBar(noSelectionPoint()); + } +} + +void Bars3DController::removeSeries(QAbstract3DSeries *series) +{ + bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series); + + Abstract3DController::removeSeries(series); + + if (firstRemoved) { + adjustAxisRanges(); + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); + + // TODO: Temp until selection by series is properly implemented + setSelectedBar(noSelectionPoint()); + } +} + +QList<QBar3DSeries *> Bars3DController::barSeriesList() +{ + QList<QAbstract3DSeries *> abstractSeriesList = seriesList(); + QList<QBar3DSeries *> barSeriesList; + foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) { + QBar3DSeries *barSeries = qobject_cast<QBar3DSeries *>(abstractSeries); + if (barSeries) + barSeriesList.append(barSeries); + } + + return barSeriesList; +} + void Bars3DController::handleAxisRangeChangedBySender(QObject *sender) { // Data window changed @@ -334,8 +343,14 @@ void Bars3DController::setSelectedBar(const QPoint &position) // If the selection targets non-existent bar, clear selection instead. QPoint pos = position; + // TODO: Selection needs to be refactored to be handled by series + const QBarDataProxy *proxy = 0; + if (m_seriesList.size()) + proxy = static_cast<QBar3DSeries *>(m_seriesList.at(0))->dataProxy(); + else + return; + if (pos != noSelectionPoint()) { - const QBarDataProxy *proxy = static_cast<const QBarDataProxy *>(m_data); int maxRow = proxy->rowCount() - 1; int maxCol = (pos.x() <= maxRow && pos.x() >= 0 && proxy->rowAt(pos.x())) ? proxy->rowAt(pos.x())->size() - 1 : -1; @@ -370,43 +385,45 @@ QPoint Bars3DController::selectedBar() const void Bars3DController::adjustAxisRanges() { - const QBarDataProxy *proxy = static_cast<QBarDataProxy *>(m_data); - const QBarDataArray *array = proxy->array(); - - Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX); - if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) { - int rowCount = proxy->rowCount(); - if (rowCount) - rowCount--; - categoryAxisX->dptr()->setRange(0.0, qreal(rowCount)); - } + if (m_seriesList.size()) { + const QBarDataProxy *proxy = static_cast<QBar3DSeries *>(m_seriesList.at(0))->dataProxy(); + const QBarDataArray *array = proxy->array(); + + Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX); + if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) { + int rowCount = proxy->rowCount(); + if (rowCount) + rowCount--; + categoryAxisX->dptr()->setRange(0.0, qreal(rowCount)); + } - Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ); - if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) { - int columnCount = 0; - for (int i = 0; i < array->size(); i++) { - if (columnCount < array->at(i)->size()) - columnCount = array->at(i)->size(); + Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ); + if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) { + int columnCount = 0; + for (int i = 0; i < array->size(); i++) { + if (columnCount < array->at(i)->size()) + columnCount = array->at(i)->size(); + } + if (columnCount) + columnCount--; + categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount)); } - if (columnCount) - columnCount--; - categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount)); - } - Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY); - if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) { - QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(), - categoryAxisX->max(), - categoryAxisZ->min(), - categoryAxisZ->max()); - if (limits.first < 0) { - // Call private implementation to avoid unsetting auto adjust flag - valueAxis->dptr()->setRange(limits.first, limits.second); - } else if (limits.second == 0.0) { - // Only zero value values in data set, set range to something. - valueAxis->dptr()->setRange(0.0, 1.0); - } else { - valueAxis->dptr()->setRange(0.0, limits.second); + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY); + if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) { + QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(), + categoryAxisX->max(), + categoryAxisZ->min(), + categoryAxisZ->max()); + if (limits.first < 0) { + // Call private implementation to avoid unsetting auto adjust flag + valueAxis->dptr()->setRange(limits.first, limits.second); + } else if (limits.second == 0.0) { + // Only zero value values in data set, set range to something. + valueAxis->dptr()->setRange(0.0, 1.0); + } else { + valueAxis->dptr()->setRange(0.0, limits.second); + } } } } diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 652aeb48..f1eda225 100644 --- a/src/datavisualization/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -37,7 +37,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Bars3DRenderer; -class QBarDataProxy; +class QBar3DSeries; struct Bars3DChangeBitField { bool slicingActiveChanged : 1; @@ -92,8 +92,6 @@ public: void setSelectedBar(const QPoint &position); QPoint selectedBar() const; - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); static QPoint noSelectionPoint(); @@ -101,6 +99,10 @@ public: virtual void setAxisX(Q3DAbstractAxis *axis); virtual void setAxisZ(Q3DAbstractAxis *axis); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + virtual QList<QBar3DSeries *> barSeriesList(); + virtual void handleAxisRangeChangedBySender(QObject *sender); public slots: diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index be844a43..c7dac4f9 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -27,6 +27,7 @@ #include "drawer_p.h" #include "qbardataitem.h" #include "q3dlight.h" +#include "qbar3dseries_p.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -46,12 +47,6 @@ const int smallerVPSize = 5; const bool sliceGridLabels = true; // TODO: Make this user controllable (QTRD-2546) -// TODO: These will be based on sets (QTRD-2548) -const int seriesCount = 1; -const float seriesScale = 1.0f / float(seriesCount); -const float seriesStep = 1.0f / float(seriesCount); -const float seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * seriesStep; - Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) : Abstract3DRenderer(controller), m_cachedIsSlicingActivated(false), @@ -95,7 +90,11 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_clickedBarColor(invalidColorVector), m_hasHeightAdjustmentChanged(true), m_selectedBarPos(Bars3DController::noSelectionPoint()), - m_noZeroInRange(false) + m_noZeroInRange(false), + m_seriesCount(0), + m_seriesScale(0.0f), + m_seriesStep(0.0f), + m_seriesStart(0.0f) { initializeOpenGLFunctions(); initializeOpenGL(); @@ -153,8 +152,15 @@ void Bars3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) +void Bars3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) { + QList<QBar3DSeries *> visibleSeries; + foreach (QAbstract3DSeries *current, seriesList) { + if (current->isVisible()) + visibleSeries.append(static_cast<QBar3DSeries *>(current)); + } + + int seriesCount = visibleSeries.size(); int minRow = m_axisCacheX.min(); int maxRow = m_axisCacheX.max(); int minCol = m_axisCacheZ.min(); @@ -163,38 +169,43 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) int newColumns = maxCol - minCol + 1; int updateSize = 0; int dataRowCount = 0; - // TODO: Dummy series, replace with actual after QTRD-2548 - // TODO: Check if resize is needed - m_renderingArrays.clear(); - m_renderingArrays.resize(seriesCount); - for (int series = 0; series < seriesCount; series++) { + + if (m_seriesCount != seriesCount) { + m_seriesCount = seriesCount; + m_renderingArrays.resize(m_seriesCount); + m_seriesScale = 1.0f / float(m_seriesCount); + m_seriesStep = 1.0f / float(m_seriesCount); + m_seriesStart = -((float(m_seriesCount) - 1.0f) / 2.0f) * m_seriesStep; + } + + if (m_cachedRowCount != newRows || m_cachedColumnCount != newColumns) { + // Force update for selection related items + m_sliceCache = 0; + m_sliceTitleItem = 0; + if (m_sliceSelection) + m_sliceSelection->clear(); + + m_cachedColumnCount = newColumns; + m_cachedRowCount = newRows; + // Calculate max scene size + GLfloat sceneRatio = qMin(GLfloat(newColumns) / GLfloat(newRows), + GLfloat(newRows) / GLfloat(newColumns)); + m_maxSceneSize = 2.0f * qSqrt(sceneRatio * newColumns * newRows); + // Calculate here and at setting bar specs + calculateSceneScalingFactors(); + } + + for (int series = 0; series < m_seriesCount; series++) { if (newRows != m_renderingArrays.at(series).size() || newColumns != m_renderingArrays.at(series).at(0).size()) { // Destroy old render items and reallocate new array - m_renderingArrays[series].clear(); m_renderingArrays[series].resize(newRows); for (int i = 0; i < newRows; i++) m_renderingArrays[series][i].resize(newColumns); - - if (series == 0) { - // Force update for selection related items - m_sliceCache = 0; - m_sliceTitleItem = 0; - if (m_sliceSelection) - m_sliceSelection->clear(); - - m_cachedColumnCount = newColumns; - m_cachedRowCount = newRows; - // Calculate max scene size - GLfloat sceneRatio = qMin(GLfloat(newColumns) / GLfloat(newRows), - GLfloat(newRows) / GLfloat(newColumns)); - m_maxSceneSize = 2.0f * qSqrt(sceneRatio * newColumns * newRows); - // Calculate here and at setting bar specs - calculateSceneScalingFactors(); - } } // Update cached data window + QBarDataProxy *dataProxy = visibleSeries.at(series)->dataProxy(); dataRowCount = dataProxy->rowCount(); int dataRowIndex = minRow; GLfloat heightValue = 0.0f; @@ -222,9 +233,8 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) heightValue = 0.0f; } } - // TODO: Dummy values for replicated series, replace with actual after QTRD-2548 - m_renderingArrays[series][i][j].setValue(value * ((series + 1.0f) / float(seriesCount))); - m_renderingArrays[series][i][j].setHeight((heightValue / m_heightNormalizer) * ((series + 1.0f) / float(seriesCount))); + m_renderingArrays[series][i][j].setValue(value); + m_renderingArrays[series][i][j].setHeight(heightValue / m_heightNormalizer); dataColIndex++; } } @@ -238,12 +248,15 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) } m_renderColumns = updateSize; - m_renderRows = qMin((dataRowCount - minRow), m_renderingArrays[0].size()); + if (m_renderingArrays.size()) + m_renderRows = qMin((dataRowCount - minRow), newRows); + else + m_renderRows = 0; // Reset selected bar to update selection updateSelectedBar(m_selectedBarPos); - Abstract3DRenderer::updateDataModel(dataProxy); + Abstract3DRenderer::updateSeriesData(seriesList); } void Bars3DRenderer::updateScene(Q3DScene *scene) @@ -459,9 +472,9 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel, GLuint gradientTexture = 0; QVector3D modelMatrixScaler(m_scaleX, 0.0f, m_scaleZ); if (rowMode) - modelMatrixScaler.setX(m_scaleX * seriesScale); + modelMatrixScaler.setX(m_scaleX * m_seriesScale); else - modelMatrixScaler.setZ(m_scaleZ * seriesScale); + modelMatrixScaler.setZ(m_scaleZ * m_seriesScale); // Set common bar shader bindings m_barShader->setUniformValue(m_barShader->lightP(), lightPos); @@ -596,7 +609,7 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel, int labelCount = m_sliceCache->labelItems().size(); for (int labelNo = 0; labelNo < labelCount; labelNo++) { // Get labels from first series only - BarRenderItem *item = m_sliceSelection->at(labelNo * seriesCount); + BarRenderItem *item = m_sliceSelection->at(labelNo * m_seriesCount); // TODO: Make user controllable (QTRD-2546) // Draw labels int labelIndex = flipped ? m_sliceCache->labelItems().size() - 1 - labelNo : labelNo; @@ -760,12 +773,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix; // Draw bars to depth buffer - QVector3D shadowScaler(m_scaleX * seriesScale * 0.9f, 0.0f, m_scaleZ * 0.9f); + QVector3D shadowScaler(m_scaleX * m_seriesScale * 0.9f, 0.0f, m_scaleZ * 0.9f); for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { GLfloat shadowOffset = 0.0f; - float seriesPos = seriesStart; - for (int series = 0; series < seriesCount; series++) { + float seriesPos = m_seriesStart; + for (int series = 0; series < m_seriesCount; series++) { const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar); if (!item.value()) continue; @@ -818,7 +831,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableVertexAttribArray(m_depthShader->posAtt()); - seriesPos += seriesStep; + seriesPos += m_seriesStep; } } } @@ -867,8 +880,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { - float seriesPos = seriesStart; - for (int series = 0; series < seriesCount; series++) { + float seriesPos = m_seriesStart; + for (int series = 0; series < m_seriesCount; series++) { const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar); if (!item.value()) continue; @@ -887,7 +900,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, item.height(), (m_columnDepth - rowPos) / m_scaleFactor); - modelMatrix.scale(QVector3D(m_scaleX * seriesScale, + modelMatrix.scale(QVector3D(m_scaleX * m_seriesScale, item.height(), m_scaleZ)); @@ -925,7 +938,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glDisableVertexAttribArray(m_selectionShader->posAtt()); - seriesPos += seriesStep; + seriesPos += m_seriesStep; } } } @@ -1008,12 +1021,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) bool barSelectionFound = false; BarRenderItem *selectedBar(0); - QVector3D modelScaler(m_scaleX * seriesScale, 0.0f, m_scaleZ); + QVector3D modelScaler(m_scaleX * m_seriesScale, 0.0f, m_scaleZ); bool somethingSelected = (m_visualSelectedBarPos != Bars3DController::noSelectionPoint()); for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { - float seriesPos = seriesStart; - for (int series = 0; series < seriesCount; series++) { + float seriesPos = m_seriesStart; + for (int series = 0; series < m_seriesCount; series++) { BarRenderItem &item = m_renderingArrays[series][row][bar]; if (item.height() < 0) @@ -1072,7 +1085,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) if (m_selectionDirty && m_cachedIsSlicingActivated) { QVector3D translation = modelMatrix.column(3).toVector3D(); if (m_cachedSelectionMode & QDataVis::SelectionColumn - && seriesCount > 1) { + && m_seriesCount > 1) { translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos) * (m_cachedBarSpacing.height()))) / m_scaleFactor); @@ -1115,7 +1128,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) shadowLightStrength = adjustedHighlightStrength; if (m_cachedIsSlicingActivated) { QVector3D translation = modelMatrix.column(3).toVector3D(); - if (seriesCount > 1) { + if (m_seriesCount > 1) { translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos) * (m_cachedBarSpacing.height()))) / m_scaleFactor); @@ -1172,7 +1185,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_drawer->drawObject(m_barShader, m_barObj, gradientTexture); } } - seriesPos += seriesStep; + seriesPos += m_seriesStep; } } } diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 00b3510a..98fdf92e 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -105,12 +105,16 @@ private: BarRenderItem m_dummyBarRenderItem; QVector<BarRenderItemArray> m_renderingArrays; bool m_noZeroInRange; + int m_seriesCount; + float m_seriesScale; + float m_seriesStep; + float m_seriesStart; public: explicit Bars3DRenderer(Bars3DController *controller); ~Bars3DRenderer(); - void updateDataModel(QBarDataProxy *dataProxy); + void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp index 1eded43a..3baff904 100644 --- a/src/datavisualization/engine/q3dbars.cpp +++ b/src/datavisualization/engine/q3dbars.cpp @@ -21,8 +21,8 @@ #include "bars3dcontroller_p.h" #include "q3dvalueaxis.h" #include "q3dcategoryaxis.h" -#include "qbardataproxy.h" #include "q3dcamera.h" +#include "qbar3dseries_p.h" #include <QMouseEvent> @@ -46,11 +46,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * These default axes can be modified via axis accessors, but as soon any axis is set explicitly * for the orientation, the default axis for that orientation is destroyed. * - * Data proxies work similarly: If no data proxy is set explicitly, Q3DBars creates a default - * proxy. If any other proxy is set as active data proxy later, the default proxy and all data - * added to it is destroyed. + * Q3DBars supports more than one series visible at the same time, but all series added to the + * graph must have proxies with identical row and column counts for the graph to draw properly. + * Row and column labels are taken from the first added series, unless explicitly defined to + * row and column axes. * - * Methods are provided for changing bar types, themes, bar selection modes and so on. See the + * Methods are provided for changing themes, bar selection modes and so on. See the * methods for more detailed descriptions. * * \section1 How to construct a minimal Q3DBars graph @@ -61,7 +62,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * * After constructing Q3DBars, you can set the data window by changing the range on the row and * column axes. It is not mandatory, as data window will default to showing all of the data in - * the data proxy. If the amount of data is large, it is usually preferable to show just a + * the series. If the amount of data is large, it is usually preferable to show just a * portion of it. For the example, let's set the data window to show first five rows and columns: * * \snippet doc_src_q3dbars_construction.cpp 0 @@ -139,13 +140,41 @@ Q3DBars::Q3DBars() } /*! - * Destroys the 3D bar window. + * Destroys the 3D bar window. */ Q3DBars::~Q3DBars() { } /*! + * Adds the \a series to the graph. A graph can contain multiple series, but only one set of axes, + * so the rows and columns of all series must match for the visualized data to be meaningful. + * If the graph has multiple visible series, only the first one added will + * generate the row or column labels on the axes in cases where the labels are not explicitly set + * to the axes. + */ +void Q3DBars::addSeries(QBar3DSeries *series) +{ + d_ptr->m_shared->addSeries(series); +} + +/*! + * Removes the \a series from the graph. + */ +void Q3DBars::removeSeries(QBar3DSeries *series) +{ + d_ptr->m_shared->removeSeries(series); +} + +/*! + * \return list of series added to this graph. + */ +QList<QBar3DSeries *> Q3DBars::seriesList() +{ + return d_ptr->m_shared->barSeriesList(); +} + +/*! * \internal */ void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event) @@ -424,7 +453,7 @@ bool Q3DBars::isBackgroundVisible() const * \property Q3DBars::selectedBar * * Selects a bar in a \a position. The position is the (row, column) position in - * the data array of the active data proxy. + * the data array of the series. * Only one bar can be selected at a time. * To clear selection, specify an illegal \a position, e.g. (-1, -1). */ @@ -689,68 +718,6 @@ QList<Q3DAbstractAxis *> Q3DBars::axes() const return d_ptr->m_shared->axes(); } -/*! - * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of - * the \a proxy to this graph. - * - * If the \a proxy is null, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method. - * - * \sa addDataProxy(), releaseDataProxy() - */ -void Q3DBars::setActiveDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->setActiveDataProxy(proxy); -} - -/*! - * \return active data proxy. - */ -QBarDataProxy *Q3DBars::activeDataProxy() const -{ - return static_cast<QBarDataProxy *>(d_ptr->m_shared->activeDataProxy()); -} - -/*! - * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, - * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. - * The \a proxy must not be null or added to another graph. - * - * \sa releaseDataProxy(), setActiveDataProxy() - */ -void Q3DBars::addDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->addDataProxy(proxy); -} - -/*! - * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. - * If the released \a proxy is in use, a new empty default proxy is created and taken to use. - * - * If the default \a proxy is released and added back later, it behaves as any other proxy would. - * - * \sa addDataProxy(), setActiveDataProxy() - */ -void Q3DBars::releaseDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->releaseDataProxy(proxy); -} - -/*! - * \return list of all added data proxies. - * - * \sa addDataProxy() - */ -QList<QBarDataProxy *> Q3DBars::dataProxies() const -{ - QList<QBarDataProxy *> retList; - QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); - foreach (QAbstractDataProxy *proxy, abstractList) - retList.append(static_cast<QBarDataProxy *>(proxy)); - - return retList; -} - Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) : q_ptr(q), m_shared(new Bars3DController(rect)) diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h index 96fce909..cba54dce 100644 --- a/src/datavisualization/engine/q3dbars.h +++ b/src/datavisualization/engine/q3dbars.h @@ -30,8 +30,8 @@ class Q3DBarsPrivate; class Q3DAbstractAxis; class Q3DCategoryAxis; class Q3DValueAxis; -class QBarDataProxy; class Q3DScene; +class QBar3DSeries; class QT_DATAVISUALIZATION_EXPORT Q3DBars : public Q3DWindow { @@ -61,6 +61,10 @@ public: explicit Q3DBars(); ~Q3DBars(); + void addSeries(QBar3DSeries *series); + void removeSeries(QBar3DSeries *series); + QList<QBar3DSeries *> seriesList(); + // TODO: Move to dataset object once that is done QTRD-2121 void setBarType(QDataVis::MeshStyle style, bool smooth = false); @@ -132,13 +136,6 @@ public: void releaseAxis(Q3DAbstractAxis *axis); QList<Q3DAbstractAxis *> axes() const; - // TODO: Move to dataset object once that is done QTRD-2121 - void setActiveDataProxy(QBarDataProxy *proxy); - QBarDataProxy *activeDataProxy() const; - void addDataProxy(QBarDataProxy *proxy); - void releaseDataProxy(QBarDataProxy *proxy); - QList<QBarDataProxy *> dataProxies() const; - signals: void selectionModeChanged(QDataVis::SelectionFlags mode); void labelStyleChanged(QDataVis::LabelStyle style); diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp index 195660a9..7aaa0e6b 100644 --- a/src/datavisualization/engine/q3dscatter.cpp +++ b/src/datavisualization/engine/q3dscatter.cpp @@ -20,8 +20,8 @@ #include "q3dscatter_p.h" #include "scatter3dcontroller_p.h" #include "q3dvalueaxis.h" -#include "qscatterdataproxy.h" #include "q3dcamera.h" +#include "qscatter3dseries_p.h" #include <QMouseEvent> #include <QDebug> @@ -44,11 +44,9 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * These default axes can be modified via axis accessors, but as soon any axis is set explicitly * for the orientation, the default axis for that orientation is destroyed. * - * Data proxies work similarly: if no data proxy is set explicitly, Q3DScatter creates a default - * proxy. If any other proxy is set as active data proxy later, the default proxy and all data - * added to it is destroyed. + * Q3DScatter supports more than one series visible at the same time. * - * Methods are provided for changing item styles, themes, item selection modes and so on. See the + * Methods are provided for changing themes, item selection modes and so on. See the * methods for more detailed descriptions. * * \section1 How to construct a minimal Q3DScatter graph @@ -125,13 +123,38 @@ Q3DScatter::Q3DScatter() } /*! - * Destroys the 3D scatter window. + * Destroys the 3D scatter window. */ Q3DScatter::~Q3DScatter() { } /*! + * Adds the \a series to the graph. A graph can contain multiple series, but has only one set of + * axes. + */ +void Q3DScatter::addSeries(QScatter3DSeries *series) +{ + d_ptr->m_shared->addSeries(series); +} + +/*! + * Removes the \a series from the graph. + */ +void Q3DScatter::removeSeries(QScatter3DSeries *series) +{ + d_ptr->m_shared->removeSeries(series); +} + +/*! + * \return list of series added to this graph. + */ +QList<QScatter3DSeries *> Q3DScatter::seriesList() +{ + return d_ptr->m_shared->scatterSeriesList(); +} + +/*! * \internal */ void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event) @@ -620,68 +643,6 @@ QList<Q3DValueAxis *> Q3DScatter::axes() const } /*! - * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of - * the \a proxy to this graph. - * - * If the \a proxy is null, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method. - * - * \sa addDataProxy(), releaseDataProxy() - */ -void Q3DScatter::setActiveDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->setActiveDataProxy(proxy); -} - -/*! - * \return active data proxy. - */ -QScatterDataProxy *Q3DScatter::activeDataProxy() const -{ - return static_cast<QScatterDataProxy *>(d_ptr->m_shared->activeDataProxy()); -} - -/*! - * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, - * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. - * The \a proxy must not be null or added to another graph. - * - * \sa releaseDataProxy(), setActiveDataProxy() - */ -void Q3DScatter::addDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->addDataProxy(proxy); -} - -/*! - * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. - * If the released \a proxy is in use, a new empty default proxy is created and taken to use. - * - * If the default \a proxy is released and added back later, it behaves as any other proxy would. - * - * \sa addDataProxy(), setActiveDataProxy() - */ -void Q3DScatter::releaseDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->releaseDataProxy(proxy); -} - -/*! - * \return list of all added data proxies. - * - * \sa addDataProxy() - */ -QList<QScatterDataProxy *> Q3DScatter::dataProxies() const -{ - QList<QScatterDataProxy *> retList; - QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); - foreach (QAbstractDataProxy *proxy, abstractList) - retList.append(static_cast<QScatterDataProxy *>(proxy)); - - return retList; -} - -/*! * \fn void Q3DScatter::shadowQualityChanged(QDataVis::ShadowQuality quality) * * This signal is emitted when shadow \a quality changes. diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h index 49397a56..2f403ce1 100644 --- a/src/datavisualization/engine/q3dscatter.h +++ b/src/datavisualization/engine/q3dscatter.h @@ -31,7 +31,7 @@ class Q3DScatterPrivate; class LabelItem; class Q3DValueAxis; class Q3DCategoryAxis; -class QScatterDataProxy; +class QScatter3DSeries; class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public Q3DWindow { @@ -58,6 +58,10 @@ public: explicit Q3DScatter(); ~Q3DScatter(); + void addSeries(QScatter3DSeries *series); + void removeSeries(QScatter3DSeries *series); + QList<QScatter3DSeries *> seriesList(); + void setObjectType(QDataVis::MeshStyle style, bool smooth = false); void setTheme(QDataVis::Theme theme); @@ -118,12 +122,6 @@ public: void releaseAxis(Q3DValueAxis *axis); QList<Q3DValueAxis *> axes() const; - void setActiveDataProxy(QScatterDataProxy *proxy); - QScatterDataProxy *activeDataProxy() const; - void addDataProxy(QScatterDataProxy *proxy); - void releaseDataProxy(QScatterDataProxy *proxy); - QList<QScatterDataProxy *> dataProxies() const; - signals: void selectionModeChanged(QDataVis::SelectionFlags mode); void labelStyleChanged(QDataVis::LabelStyle style); diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp index ac451ad2..26f82611 100644 --- a/src/datavisualization/engine/q3dsurface.cpp +++ b/src/datavisualization/engine/q3dsurface.cpp @@ -21,6 +21,7 @@ #include "q3dvalueaxis.h" #include "qsurfacedataproxy.h" #include "q3dcamera.h" +#include "qsurface3dseries_p.h" #include <QMouseEvent> @@ -42,8 +43,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * a label which in default case shows the value of the data point and the coordinates of the point. * * The value range and the label format shown on the axis can be controlled through Q3DValueAxis. - * The Q3DSurface supports only a grid with fixed steps, so when setting ranges set a value that matches - * the grid step. To calculate the steps divide the whole data range with the number of segments. * * To rotate the graph, hold down the right mouse button and move the mouse. Zooming is done using mouse * wheel. Both assume the default input handler is in use. @@ -52,9 +51,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * These default axes can be modified via axis accessors, but as soon any axis is set explicitly * for the orientation, the default axis for that orientation is destroyed. * - * Data proxies work similarly: if no data proxy is set explicitly, Q3DSurface creates a default - * proxy. If any other proxy is set as active data proxy later, the default proxy and all data - * added to it is destroyed. + * Q3DSurface supports only single series at a time. * * \section1 How to construct a minimal Q3DSurface graph * @@ -135,6 +132,34 @@ Q3DSurface::~Q3DSurface() } /*! + * Adds the \a series to the graph. + * + * \note The surface graph currently supports only a single series at a time. + */ +void Q3DSurface::addSeries(QSurface3DSeries *series) +{ + d_ptr->m_shared->addSeries(series); +} + +/*! + * Removes the \a series from the graph. + */ +void Q3DSurface::removeSeries(QSurface3DSeries *series) +{ + d_ptr->m_shared->removeSeries(series); +} + +/*! + * \return list of series added to this graph. + * + * \note The surface graph currently supports only a single series at a time. + */ +QList<QSurface3DSeries *> Q3DSurface::seriesList() +{ + return d_ptr->m_shared->surfaceSeriesList(); +} + +/*! * \internal */ void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event) @@ -297,21 +322,6 @@ QDataVis::SelectionFlags Q3DSurface::selectionMode() const } /*! - * \property Q3DSurface::surfaceVisible - * - * Sets surface to \a visible. It is preset to \c true by default. - */ -void Q3DSurface::setSurfaceVisible(bool visible) -{ - d_ptr->m_shared->setSurfaceVisible(visible); -} - -bool Q3DSurface::isSurfaceVisible() const -{ - return d_ptr->m_shared->surfaceVisible(); -} - -/*! * \property Q3DSurface::surfaceGridEnabled * * Sets surface grid to \a enabled. It is preset to \c true by default. @@ -511,69 +521,6 @@ QList<Q3DValueAxis *> Q3DSurface::axes() const } /*! - * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of - * the \a proxy to this graph. - * - * If the \a proxy is null, a temporary default proxy is created and activated. - * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method. - * - * \sa addDataProxy(), releaseDataProxy() - */ -void Q3DSurface::setActiveDataProxy(QSurfaceDataProxy *proxy) -{ - d_ptr->m_shared->setActiveDataProxy(proxy); -} - -/*! - * \return active data proxy. - */ -QSurfaceDataProxy *Q3DSurface::activeDataProxy() const -{ - return static_cast<QSurfaceDataProxy *>(d_ptr->m_shared->activeDataProxy()); -} - -/*! - * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, - * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. - * The \a proxy must not be null or added to another graph. - * - * \sa releaseDataProxy(), setActiveDataProxy() - */ -void Q3DSurface::addDataProxy(QSurfaceDataProxy *proxy) -{ - d_ptr->m_shared->addDataProxy(proxy); -} - -/*! - * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. - * If the released \a proxy is in use, a new empty default proxy is created and taken to use. - * - * If the default \a proxy is released and added back later, it behaves as any other proxy would. - * - * \sa addDataProxy(), setActiveDataProxy() - */ -void Q3DSurface::releaseDataProxy(QSurfaceDataProxy *proxy) -{ - d_ptr->m_shared->releaseDataProxy(proxy); -} - -/*! - * \return list of all added data proxies. - * - * \sa addDataProxy() - */ -QList<QSurfaceDataProxy *> Q3DSurface::dataProxies() const -{ - QList<QSurfaceDataProxy *> retList; - QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); - foreach (QAbstractDataProxy *proxy, abstractList) - retList.append(static_cast<QSurfaceDataProxy *>(proxy)); - - return retList; -} - - -/*! * Modifies the current surface gradient. Sets gradient color to \a color at \a pos. */ void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h index 85b87589..29166362 100644 --- a/src/datavisualization/engine/q3dsurface.h +++ b/src/datavisualization/engine/q3dsurface.h @@ -29,7 +29,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DSurfacePrivate; class Q3DValueAxis; -class QSurfaceDataProxy; +class QSurface3DSeries; class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow { @@ -38,7 +38,6 @@ class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle NOTIFY labelStyleChanged) Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme NOTIFY themeChanged) Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) - Q_PROPERTY(bool surfaceVisible READ isSurfaceVisible WRITE setSurfaceVisible NOTIFY surfaceVisibleChanged) Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible NOTIFY gridVisibleChanged) Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible NOTIFY backgroundVisibleChanged) Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled NOTIFY smoothSurfaceEnabledChanged) @@ -53,8 +52,9 @@ public: explicit Q3DSurface(); ~Q3DSurface(); - void setSurfaceVisible(bool visible); - bool isSurfaceVisible() const; + void addSeries(QSurface3DSeries *series); + void removeSeries(QSurface3DSeries *series); + QList<QSurface3DSeries *> seriesList(); void setGridVisible(bool visible); bool isGridVisible() const; @@ -92,12 +92,6 @@ public: void releaseAxis(Q3DValueAxis *axis); QList<Q3DValueAxis *> axes() const; - void setActiveDataProxy(QSurfaceDataProxy *proxy); - QSurfaceDataProxy *activeDataProxy() const; - void addDataProxy(QSurfaceDataProxy *proxy); - void releaseDataProxy(QSurfaceDataProxy *proxy); - QList<QSurfaceDataProxy *> dataProxies() const; - void setFont(const QFont &font); QFont font() const; diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index a894101f..11a2d03f 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -22,6 +22,7 @@ #include "q3dabstractaxis_p.h" #include "q3dvalueaxis_p.h" #include "qscatterdataproxy_p.h" +#include "qscatter3dseries_p.h" #include <QMatrix4x4> #include <qmath.h> @@ -36,8 +37,6 @@ Scatter3DController::Scatter3DController(QRect boundRect) // Default object type; specific to scatter setObjectType(QDataVis::MeshStyleSpheres, false); - setActiveDataProxy(new QScatterDataProxy); - // Setting a null axis creates a new default axis according to orientation and graph type. // Note: These cannot be set in Abstract3DController constructor, as they will call virtual // functions implemented by subclasses. @@ -77,42 +76,47 @@ void Scatter3DController::synchDataToRenderer() m_renderer->updateSelectedItemIndex(m_selectedItemIndex); m_changeTracker.selectedItemIndexChanged = false; } - - if (m_isDataDirty) { - m_renderer->updateSeriesData(static_cast<QScatterDataProxy *>(m_data)); - m_isDataDirty = false; - } } -void Scatter3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +void Scatter3DController::addSeries(QAbstract3DSeries *series) { - // Setting null proxy indicates default proxy - if (!proxy) { - proxy = new QScatterDataProxy; - proxy->d_ptr->setDefaultProxy(true); + Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeScatter); + + bool firstAdded = !m_seriesList.size(); + + Abstract3DController::addSeries(series); + + if (firstAdded) { + adjustValueAxisRange(); + // TODO: Temp until selection by series is properly implemented + setSelectedItemIndex(noSelectionIndex()); } +} - Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter); +void Scatter3DController::removeSeries(QAbstract3DSeries *series) +{ + bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series); - Abstract3DController::setActiveDataProxy(proxy); + Abstract3DController::removeSeries(series); - QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_data); + if (firstRemoved) { + adjustValueAxisRange(); + // TODO: Temp until selection by series is properly implemented + setSelectedItemIndex(noSelectionIndex()); + } +} - QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset, - this, &Scatter3DController::handleArrayReset); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded, - this, &Scatter3DController::handleItemsAdded); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged, - this, &Scatter3DController::handleItemsChanged); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved, - this, &Scatter3DController::handleItemsRemoved); - QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted, - this, &Scatter3DController::handleItemsInserted); +QList<QScatter3DSeries *> Scatter3DController::scatterSeriesList() +{ + QList<QAbstract3DSeries *> abstractSeriesList = seriesList(); + QList<QScatter3DSeries *> scatterSeriesList; + foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) { + QScatter3DSeries *scatterSeries = qobject_cast<QScatter3DSeries *>(abstractSeries); + if (scatterSeries) + scatterSeriesList.append(scatterSeries); + } - adjustValueAxisRange(); - setSelectedItemIndex(noSelectionIndex()); - m_isDataDirty = true; - emitNeedRender(); + return scatterSeriesList; } void Scatter3DController::handleArrayReset() @@ -150,7 +154,8 @@ void Scatter3DController::handleItemsRemoved(int startIndex, int count) // TODO should dirty only affected values? adjustValueAxisRange(); m_isDataDirty = true; - if (startIndex >= static_cast<QScatterDataProxy *>(m_data)->itemCount()) + QScatterDataProxy *proxy = qobject_cast<QScatterDataProxy *>(sender()); + if (!proxy || startIndex >= proxy->itemCount()) setSelectedItemIndex(noSelectionIndex()); emitNeedRender(); } @@ -243,8 +248,9 @@ void Scatter3DController::adjustValueAxisRange() { QVector3D minLimits; QVector3D maxLimits; - if (m_data) { - static_cast<QScatterDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits); + if (m_seriesList.size()) { + const QScatterDataProxy *proxy = static_cast<QScatter3DSeries *>(m_seriesList.at(0))->dataProxy(); + proxy->dptrc()->limitValues(minLimits, maxLimits); Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX); if (valueAxis && valueAxis->isAutoAdjustRange()) { if (minLimits.x() != maxLimits.x()) diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h index d593d010..a75b61ac 100644 --- a/src/datavisualization/engine/scatter3dcontroller_p.h +++ b/src/datavisualization/engine/scatter3dcontroller_p.h @@ -38,6 +38,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Scatter3DRenderer; class QScatterDataProxy; +class QScatter3DSeries; struct Scatter3DChangeBitField { bool selectedItemIndexChanged : 1; @@ -75,10 +76,12 @@ public: int selectedItemIndex() const; static inline int noSelectionIndex() { return -1; } - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); - void synchDataToRenderer(); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + virtual QList<QScatter3DSeries *> scatterSeriesList(); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); virtual void handleAxisRangeChangedBySender(QObject *sender); diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 449809c8..e87c1435 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -25,6 +25,7 @@ #include "texturehelper_p.h" #include "utils_p.h" #include "q3dlight.h" +#include "qscatter3dseries_p.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -141,15 +142,14 @@ void Scatter3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -//void Scatter3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) -void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) +void Scatter3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) { - //QList<QScatter3DSeries *> visibleSeries; - //foreach (QAbstract3DSeries *current, seriesList) { - // if (current->isVisible()) - // visibleSeries.append(static_cast<QScatter3DSeries *>(current)); - //} - int seriesCount = 3;//visibleSeries.size(); // TODO: Use a number for testing until QTRD-2548 is done + QList<QScatter3DSeries *> visibleSeries; + foreach (QAbstract3DSeries *current, seriesList) { + if (current->isVisible()) + visibleSeries.append(static_cast<QScatter3DSeries *>(current)); + } + int seriesCount = visibleSeries.size(); calculateSceneScalingFactors(); float minX = float(m_axisCacheX.min()); float maxX = float(m_axisCacheX.max()); @@ -165,7 +165,7 @@ void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) } for (int series = 0; series < m_seriesCount; series++) { - //QScatterDataProxy *dataProxy = visibleSeries.at(series)->dataProxy(); + QScatterDataProxy *dataProxy = visibleSeries.at(series)->dataProxy(); const QScatterDataArray &dataArray = *dataProxy->array(); int dataSize = dataArray.size(); totalDataSize += dataSize; @@ -179,9 +179,7 @@ void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) if ((dotPos.x() >= minX && dotPos.x() <= maxX ) && (dotPos.y() >= minY && dotPos.y() <= maxY) && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) { - //m_renderingArrays[series][i].setPosition(dotPos); - // TODO: Hack different values for sets until QTRD-2548 - m_renderingArrays[series][i].setPosition(dotPos * (1.0f - (series * 0.25f))); + m_renderingArrays[series][i].setPosition(dotPos); m_renderingArrays[series][i].setVisible(true); calculateTranslation(m_renderingArrays[series][i]); } else { @@ -192,8 +190,7 @@ void Scatter3DRenderer::updateSeriesData(QScatterDataProxy *dataProxy) m_dotSizeScale = (GLfloat)qBound(0.01, (2.0 / qSqrt((qreal)totalDataSize)), 0.1); m_selectedItem = 0; - Abstract3DRenderer::updateDataModel(dataProxy); - //Abstract3DRenderer::updateSeriesData(seriesList); + Abstract3DRenderer::updateSeriesData(seriesList); } void Scatter3DRenderer::updateScene(Q3DScene *scene) @@ -514,7 +511,6 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) glEnable(GL_DITHER); // Read color under cursor - // TODO: Can't call back to controller here! (QTRD-2216) QVector3D clickedColor = Utils::getSelection(m_inputPosition, m_cachedBoundingRect.height()); if (m_clickedColor == invalidColorVector) { @@ -585,7 +581,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) int dotNo = 0; for (int series = 0; series < m_seriesCount; series++) { - // TODO: Color per series. Let's just hack it while testing with 2 series + // TODO: Color per series. Let's just hack it while testing with 2 series QTRD-2557 QVector3D baseColor = Utils::vectorFromColor(m_cachedObjectColor) * (series + 0.25f); QVector3D dotColor = baseColor; diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index c6a627d0..4050f89b 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -96,8 +96,7 @@ public: explicit Scatter3DRenderer(Scatter3DController *controller); ~Scatter3DRenderer(); - //void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); - void updateSeriesData(QScatterDataProxy *dataProxy); + void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); void updateScene(Q3DScene *scene); void updateInputState(QDataVis::InputState state); diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 9e82017a..060e688f 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -23,6 +23,7 @@ #include "q3dvalueaxis_p.h" #include "q3dcategoryaxis.h" #include "qsurfacedataproxy_p.h" +#include "qsurface3dseries_p.h" #include <QMatrix4x4> @@ -38,8 +39,6 @@ Surface3DController::Surface3DController(QRect rect) m_isSurfaceGridEnabled(true), m_selectedPoint(noSelectionPoint()) { - setActiveDataProxy(0); - // Setting a null axis creates a new default axis according to orientation and graph type. // Note: these cannot be set in the Abstract3DController constructor, as they will call virtual // functions implemented by subclasses. @@ -73,11 +72,16 @@ void Surface3DController::initializeOpenGL() void Surface3DController::synchDataToRenderer() { - Abstract3DController::synchDataToRenderer(); - if (!isInitialized()) return; + if (m_changeTracker.surfaceGridChanged) { + m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled); + m_changeTracker.surfaceGridChanged = false; + } + + Abstract3DController::synchDataToRenderer(); + // Notify changes to renderer if (m_changeTracker.gradientColorChanged) { m_renderer->updateSurfaceGradient(m_userDefinedGradient); @@ -92,25 +96,10 @@ void Surface3DController::synchDataToRenderer() emit smoothSurfaceEnabledChanged(m_isSmoothSurfaceEnabled); } - if (m_changeTracker.surfaceVisibilityChanged) { - m_renderer->updateSurfaceVisibilityStatus(m_isSurfaceEnabled); - m_changeTracker.surfaceVisibilityChanged = false; - } - - if (m_changeTracker.surfaceGridChanged) { - m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled); - m_changeTracker.surfaceGridChanged = false; - } - if (m_changeTracker.selectedPointChanged) { m_renderer->updateSelectedPoint(m_selectedPoint); m_changeTracker.selectedPointChanged = false; } - - if (m_isDataDirty) { - m_renderer->updateDataModel(static_cast<QSurfaceDataProxy *>(m_data)); - m_isDataDirty = false; - } } void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) @@ -135,34 +124,60 @@ QPoint Surface3DController::noSelectionPoint() return noSelectionPoint; } -void Surface3DController::setSmoothSurface(bool enable) +void Surface3DController::addSeries(QAbstract3DSeries *series) { - if (enable != m_isSmoothSurfaceEnabled) { - m_isSmoothSurfaceEnabled = enable; - m_changeTracker.smoothStatusChanged = true; - emit smoothSurfaceEnabledChanged(enable); - emitNeedRender(); + Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface); + + if (!m_seriesList.size()) { + Abstract3DController::addSeries(series); + + adjustValueAxisRange(); + + // TODO: Temp until selection by series is properly implemented + setSelectedPoint(noSelectionPoint()); + } else { + qWarning("Surface graph only supports a single series."); } } -bool Surface3DController::smoothSurface() +void Surface3DController::removeSeries(QAbstract3DSeries *series) { - return m_isSmoothSurfaceEnabled; + if (series && series->d_ptr->m_controller == this) { + Abstract3DController::removeSeries(series); + + adjustValueAxisRange(); + + // TODO: Temp until selection by series is properly implemented + setSelectedPoint(noSelectionPoint()); + } +} + +QList<QSurface3DSeries *> Surface3DController::surfaceSeriesList() +{ + QList<QAbstract3DSeries *> abstractSeriesList = seriesList(); + QList<QSurface3DSeries *> surfaceSeriesList; + foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) { + QSurface3DSeries *surfaceSeries = qobject_cast<QSurface3DSeries *>(abstractSeries); + if (surfaceSeries) + surfaceSeriesList.append(surfaceSeries); + } + + return surfaceSeriesList; } -void Surface3DController::setSurfaceVisible(bool visible) +void Surface3DController::setSmoothSurface(bool enable) { - if (visible != m_isSurfaceEnabled) { - m_isSurfaceEnabled = visible; - m_changeTracker.surfaceVisibilityChanged = true; - emit surfaceVisibleChanged(visible); + if (enable != m_isSmoothSurfaceEnabled) { + m_isSmoothSurfaceEnabled = enable; + m_changeTracker.smoothStatusChanged = true; + emit smoothSurfaceEnabledChanged(enable); emitNeedRender(); } } -bool Surface3DController::surfaceVisible() const +bool Surface3DController::smoothSurface() { - return m_isSurfaceEnabled; + return m_isSmoothSurfaceEnabled; } void Surface3DController::setSurfaceGrid(bool enable) @@ -172,6 +187,7 @@ void Surface3DController::setSurfaceGrid(bool enable) m_changeTracker.surfaceGridChanged = true; emit surfaceGridEnabledChanged(enable); emitNeedRender(); + m_isDataDirty = true; } } @@ -230,7 +246,15 @@ void Surface3DController::setSelectedPoint(const QPoint &position) // If the selection targets non-existent point, clear selection instead. QPoint pos = position; - const QSurfaceDataProxy *proxy = static_cast<const QSurfaceDataProxy *>(m_data); + // TODO: Selection needs to be refactored to be handled by series + const QSurfaceDataProxy *proxy = 0; + if (m_seriesList.size()) { + QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_seriesList.at(0)); + proxy = static_cast<QSurfaceDataProxy *>(series->dataProxy()); + } else { + return; + } + if (pos != noSelectionPoint()) { int maxRow = proxy->rowCount() - 1; int maxCol = proxy->columnCount() - 1; @@ -284,32 +308,6 @@ QPoint Surface3DController::selectedPoint() const return m_selectedPoint; } -void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy) -{ - // Setting null proxy indicates default proxy - if (!proxy) { - proxy = new QSurfaceDataProxy; - proxy->d_ptr->setDefaultProxy(true); - } - - Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface); - - Abstract3DController::setActiveDataProxy(proxy); - - QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_data); - - QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, - this, &Surface3DController::handleArrayReset); - - adjustValueAxisRange(); - - // Always clear selection on proxy change - setSelectedPoint(noSelectionPoint()); - - m_isDataDirty = true; - emitNeedRender(); -} - void Surface3DController::handleArrayReset() { adjustValueAxisRange(); @@ -334,10 +332,12 @@ void Surface3DController::handleRequestSmoothSurface(bool enable) void Surface3DController::adjustValueAxisRange() { - if (m_data) { + if (m_seriesList.size()) { QVector3D minLimits; QVector3D maxLimits; - static_cast<QSurfaceDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits); + QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_seriesList.at(0)); + static_cast<QSurfaceDataProxy *>(series->dataProxy())->dptrc()->limitValues(minLimits, + maxLimits); Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX); if (valueAxis && valueAxis->isAutoAdjustRange()) { if (minLimits.x() != maxLimits.x()) diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index f9617ad4..09c0ca5b 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -37,18 +37,17 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Surface3DRenderer; +class QSurface3DSeries; struct Surface3DChangeBitField { bool gradientColorChanged : 1; bool smoothStatusChanged : 1; - bool surfaceVisibilityChanged : 1; bool surfaceGridChanged : 1; bool selectedPointChanged : 1; Surface3DChangeBitField() : gradientColorChanged(true), smoothStatusChanged(true), - surfaceVisibilityChanged(true), surfaceGridChanged(true), selectedPointChanged(true) { @@ -75,9 +74,6 @@ public: void initializeOpenGL(); virtual void synchDataToRenderer(); - void setSurfaceVisible(bool visible); - bool surfaceVisible() const; - void setSmoothSurface(bool enable); bool smoothSurface(); @@ -94,13 +90,15 @@ public: void setSelectedPoint(const QPoint &position); QPoint selectedPoint() const; - virtual void setActiveDataProxy(QAbstractDataProxy *proxy); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); virtual void handleAxisRangeChangedBySender(QObject *sender); static QPoint noSelectionPoint(); + virtual void addSeries(QAbstract3DSeries *series); + virtual void removeSeries(QAbstract3DSeries *series); + virtual QList<QSurface3DSeries *> surfaceSeriesList(); + public slots: void handleArrayReset(); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 8bb16f86..3a6e3560 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -29,6 +29,7 @@ #include "utils_p.h" #include "drawer_p.h" #include "q3dlight.h" +#include "qsurface3dseries_p.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -101,7 +102,7 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_shadowQualityToShader(33.3f), m_cachedSmoothSurface(true), m_flatSupported(true), - m_cachedSurfaceOn(true), + m_cachedSurfaceVisible(true), m_cachedSurfaceGridOn(true), m_selectionPointer(0), m_selectionActive(false), @@ -196,15 +197,25 @@ void Surface3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) +void Surface3DRenderer::updateSeriesData(const QList<QAbstract3DSeries *> &seriesList) { - calculateSceneScalingFactors(); + // Surface only supports single series for now, so we are only interested in the first series + const QSurfaceDataArray *array = 0; + if (seriesList.size()) { + QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(seriesList.at(0)); + m_cachedSurfaceVisible = firstSeries->isVisible(); // TODO: To series visuals update? + if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) { + QSurfaceDataProxy *dataProxy = firstSeries->dataProxy(); + if (dataProxy) + array = dataProxy->array(); + } + } - const QSurfaceDataArray &array = *dataProxy->array(); + calculateSceneScalingFactors(); // Need minimum of 2x2 array to draw a surface - if (array.size() >= 2 && array.at(0)->size() >= 2) { - QRect sampleSpace = calculateSampleRect(array); + if (array && array->size() >= 2 && array->at(0)->size() >= 2) { + QRect sampleSpace = calculateSampleRect(*array); bool dimensionChanged = false; if (m_sampleSpace != sampleSpace) { @@ -225,7 +236,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) } for (int i = 0; i < sampleSpace.height(); i++) { for (int j = 0; j < sampleSpace.width(); j++) - (*(m_dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(j + sampleSpace.x()); + (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(j + sampleSpace.x()); } if (m_dataArray.size() > 0) { @@ -258,7 +269,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) m_selectionDirty = true; - Abstract3DRenderer::updateDataModel(dataProxy); + Abstract3DRenderer::updateSeriesData(seriesList); } void Surface3DRenderer::updateSliceDataModel(const QPoint &point) @@ -515,7 +526,7 @@ void Surface3DRenderer::drawSlicedScene() MVPMatrix = projectionViewMatrix * modelMatrix; - if (m_cachedSurfaceOn) { + if (m_cachedSurfaceVisible) { if (m_cachedSurfaceGridOn) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.5f, 1.0f); @@ -784,7 +795,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Draw depth buffer #if !defined(QT_OPENGL_ES_2) GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f; - if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj && m_cachedSurfaceOn) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj && m_cachedSurfaceVisible) { // Render scene into a depth texture for using with shadow mapping // Enable drawing to depth framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -899,7 +910,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Draw selection buffer if (!m_cachedIsSlicingActivated && m_surfaceObj && m_inputState == QDataVis::InputStateOnScene - && m_cachedSelectionMode > QDataVis::SelectionNone) { + && m_cachedSelectionMode > QDataVis::SelectionNone + && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn)) { m_selectionShader->bind(); glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used @@ -970,7 +982,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) MVPMatrix = projectionViewMatrix * modelMatrix; #endif - if (m_cachedSurfaceOn) { + if (m_cachedSurfaceVisible) { // Set shader bindings m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos); m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix); @@ -1063,7 +1075,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_cachedTheme.m_ambientStrength * 2.0f); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_cachedSurfaceOn) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_cachedSurfaceVisible) { // Set shadow shader bindings QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), @@ -1781,11 +1793,6 @@ void Surface3DRenderer::updateSelectedPoint(const QPoint &position) m_selectionDirty = true; } -void Surface3DRenderer::updateSurfaceVisibilityStatus(bool visible) -{ - m_cachedSurfaceOn = visible; -} - void Surface3DRenderer::updateSurfaceGridStatus(bool enable) { m_cachedSurfaceGridOn = enable; diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 0cff19cd..2c5f84fb 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -111,7 +111,7 @@ private: GLfloat m_shadowQualityToShader; bool m_cachedSmoothSurface; bool m_flatSupported; - bool m_cachedSurfaceOn; + bool m_cachedSurfaceVisible; bool m_cachedSurfaceGridOn; SelectionPointer *m_selectionPointer; bool m_selectionActive; @@ -132,11 +132,10 @@ public: explicit Surface3DRenderer(Surface3DController *controller); ~Surface3DRenderer(); - void updateDataModel(QSurfaceDataProxy *dataProxy); + void updateSeriesData(const QList<QAbstract3DSeries *> &seriesList); void updateScene(Q3DScene *scene); void updateInputState(QDataVis::InputState state); bool updateSmoothStatus(bool enable); - void updateSurfaceVisibilityStatus(bool visible); void updateSurfaceGridStatus(bool enable); void updateSurfaceGradient(const QLinearGradient &gradient); void updateSlicingActive(bool isSlicing); diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp index 6abc8684..80752019 100644 --- a/src/datavisualizationqml2/abstractdeclarative.cpp +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -107,16 +107,6 @@ QDataVis::ShadowQuality AbstractDeclarative::shadowQuality() const return m_controller->shadowQuality(); } -void AbstractDeclarative::setItemLabelFormat(const QString &format) -{ - m_controller->activeDataProxy()->setItemLabelFormat(format); -} - -QString AbstractDeclarative::itemLabelFormat() const -{ - return m_controller->activeDataProxy()->itemLabelFormat(); -} - void AbstractDeclarative::setSharedController(Abstract3DController *controller) { Q_ASSERT(controller); @@ -137,8 +127,6 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller) &AbstractDeclarative::backgroundVisibleChanged); QObject::connect(m_controller, &Abstract3DController::gridVisibleChanged, this, &AbstractDeclarative::gridVisibleChanged); - QObject::connect(m_controller->activeDataProxy(), &QAbstractDataProxy::itemLabelFormatChanged, this, - &AbstractDeclarative::itemLabelFormatChanged); } QAbstract3DInputHandler* AbstractDeclarative::inputHandler() const diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h index 646ed785..1740b816 100644 --- a/src/datavisualizationqml2/abstractdeclarative_p.h +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -51,7 +51,6 @@ class AbstractDeclarative : public QQuickItem Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible NOTIFY gridVisibleChanged) Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible NOTIFY backgroundVisibleChanged) - Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged) public: explicit AbstractDeclarative(QQuickItem *parent = 0); @@ -83,9 +82,6 @@ public: virtual void setShadowQuality(QDataVis::ShadowQuality quality); virtual QDataVis::ShadowQuality shadowQuality() const; - virtual void setItemLabelFormat(const QString &format); - virtual QString itemLabelFormat() const; - void setSharedController(Abstract3DController *controller); protected: diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp index be50982d..4e47ba53 100644 --- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp @@ -62,6 +62,10 @@ void Datavis3Dqml2Plugin::registerTypes(const char *uri) qmlRegisterType<QItemModelSurfaceDataProxy>(uri, 1, 0, "ItemModelSurfaceDataProxy"); qmlRegisterType<QHeightMapSurfaceDataProxy>(uri, 1, 0, "HeightMapSurfaceDataProxy"); + qmlRegisterType<QBar3DSeries>(uri, 1, 0, "Bar3DSeries"); + qmlRegisterType<QScatter3DSeries>(uri, 1, 0, "Scatter3DSeries"); + qmlRegisterType<QSurface3DSeries>(uri, 1, 0, "Surface3DSeries"); + qmlRegisterType<ColorGradientStop>(uri, 1, 0, "ColorGradientStop"); qmlRegisterType<ColorGradient>(uri, 1, 0, "ColorGradient"); } diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.h b/src/datavisualizationqml2/datavisualizationqml2_plugin.h index c0d7c4b8..d74def9d 100644 --- a/src/datavisualizationqml2/datavisualizationqml2_plugin.h +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.h @@ -35,6 +35,10 @@ #include "q3dobject.h" #include "q3dcamera.h" #include "q3dscene.h" +#include "qabstract3dseries.h" +#include "qbar3dseries.h" +#include "qscatter3dseries.h" +#include "qsurface3dseries.h" #include <QQmlExtensionPlugin> @@ -68,6 +72,11 @@ QML_DECLARE_TYPE(QSurfaceDataProxy) QML_DECLARE_TYPE(QItemModelSurfaceDataProxy) QML_DECLARE_TYPE(QHeightMapSurfaceDataProxy) +QML_DECLARE_TYPE(QAbstract3DSeries) +QML_DECLARE_TYPE(QBar3DSeries) +QML_DECLARE_TYPE(QScatter3DSeries) +QML_DECLARE_TYPE(QSurface3DSeries) + QML_DECLARE_TYPE(ColorGradientStop) QML_DECLARE_TYPE(ColorGradient) diff --git a/src/datavisualizationqml2/declarativebars.cpp b/src/datavisualizationqml2/declarativebars.cpp index 9f2af06b..cf74d444 100644 --- a/src/datavisualizationqml2/declarativebars.cpp +++ b/src/datavisualizationqml2/declarativebars.cpp @@ -45,9 +45,6 @@ DeclarativeBars::DeclarativeBars(QQuickItem *parent) &DeclarativeBars::selectedBarChanged); QObject::connect(m_shared, &Abstract3DController::meshFileNameChanged, this, &DeclarativeBars::meshFileNameChanged); - - QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy; - m_shared->setActiveDataProxy(proxy); } DeclarativeBars::~DeclarativeBars() @@ -83,16 +80,6 @@ void DeclarativeBars::setBarColor(const QColor &baseColor) m_shared->setObjectColor(baseColor); } -void DeclarativeBars::setDataProxy(QBarDataProxy *dataProxy) -{ - m_shared->setActiveDataProxy(dataProxy); -} - -QBarDataProxy *DeclarativeBars::dataProxy() const -{ - return static_cast<QBarDataProxy *>(m_shared->activeDataProxy()); -} - Q3DCategoryAxis *DeclarativeBars::rowAxis() const { return static_cast<Q3DCategoryAxis *>(m_shared->axisX()); @@ -221,4 +208,48 @@ QPointF DeclarativeBars::selectedBar() const return QPointF(m_shared->selectedBar()); } +QQmlListProperty<QBar3DSeries> DeclarativeBars::seriesList() +{ + return QQmlListProperty<QBar3DSeries>(this, this, + &DeclarativeBars::appendSeriesFunc, + &DeclarativeBars::countSeriesFunc, + &DeclarativeBars::atSeriesFunc, + &DeclarativeBars::clearSeriesFunc); +} + +void DeclarativeBars::appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series) +{ + reinterpret_cast<DeclarativeBars *>(list->data)->addSeries(series); +} + +int DeclarativeBars::countSeriesFunc(QQmlListProperty<QBar3DSeries> *list) +{ + return reinterpret_cast<DeclarativeBars *>(list->data)->m_shared->barSeriesList().size(); +} + +QBar3DSeries *DeclarativeBars::atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, int index) +{ + return reinterpret_cast<DeclarativeBars *>(list->data)->m_shared->barSeriesList().at(index); +} + +void DeclarativeBars::clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list) +{ + DeclarativeBars *declBars = reinterpret_cast<DeclarativeBars *>(list->data); + QList<QBar3DSeries *> realList = declBars->m_shared->barSeriesList(); + int count = realList.size(); + for (int i = 0; i < count; i++) + declBars->removeSeries(realList.at(i)); +} + +void DeclarativeBars::addSeries(QBar3DSeries *series) +{ + m_shared->addSeries(series); +} + +void DeclarativeBars::removeSeries(QBar3DSeries *series) +{ + m_shared->removeSeries(series); + series->setParent(this); // Reparent as removing will leave series parentless +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativebars_p.h b/src/datavisualizationqml2/declarativebars_p.h index f6d36632..c3808b7b 100644 --- a/src/datavisualizationqml2/declarativebars_p.h +++ b/src/datavisualizationqml2/declarativebars_p.h @@ -36,6 +36,7 @@ #include "q3dvalueaxis.h" #include "q3dcategoryaxis.h" #include "qbardataproxy.h" +#include "qbar3dseries.h" #include <QAbstractItemModel> #include <QQuickItem> @@ -47,7 +48,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class DeclarativeBars : public AbstractDeclarative { Q_OBJECT - Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy) Q_PROPERTY(Q3DCategoryAxis *rowAxis READ rowAxis WRITE setRowAxis) Q_PROPERTY(Q3DValueAxis *valueAxis READ valueAxis WRITE setValueAxis) Q_PROPERTY(Q3DCategoryAxis *columnAxis READ columnAxis WRITE setColumnAxis) @@ -58,6 +58,7 @@ class DeclarativeBars : public AbstractDeclarative Q_PROPERTY(bool barSmoothingEnabled READ isBarSmoothingEnabled WRITE setBarSmoothingEnabled NOTIFY meshFileNameChanged) Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName NOTIFY meshFileNameChanged) Q_PROPERTY(QPointF selectedBar READ selectedBar WRITE setSelectedBar NOTIFY selectedBarChanged) + Q_PROPERTY(QQmlListProperty<QBar3DSeries> seriesList READ seriesList) public: explicit DeclarativeBars(QQuickItem *parent = 0); @@ -65,9 +66,6 @@ public: Q_INVOKABLE void setBarColor(const QColor &baseColor); // TODO property (or more likely as part of data set) - QBarDataProxy *dataProxy() const; - void setDataProxy(QBarDataProxy *dataProxy); - Q3DCategoryAxis *rowAxis() const; void setRowAxis(Q3DCategoryAxis *axis); Q3DValueAxis *valueAxis() const; @@ -96,6 +94,14 @@ public: void setSelectedBar(const QPointF &position); QPointF selectedBar() const; + QQmlListProperty<QBar3DSeries> seriesList(); + static void appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series); + static int countSeriesFunc(QQmlListProperty<QBar3DSeries> *list); + static QBar3DSeries *atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, int index); + static void clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list); + Q_INVOKABLE void addSeries(QBar3DSeries *series); + Q_INVOKABLE void removeSeries(QBar3DSeries *series); + signals: void selectedBarChanged(const QPointF &position); void barThicknessChanged(qreal thicknessRatio); diff --git a/src/datavisualizationqml2/declarativescatter.cpp b/src/datavisualizationqml2/declarativescatter.cpp index 7c201301..1a05c425 100644 --- a/src/datavisualizationqml2/declarativescatter.cpp +++ b/src/datavisualizationqml2/declarativescatter.cpp @@ -40,7 +40,6 @@ DeclarativeScatter::DeclarativeScatter(QQuickItem *parent) // Create the shared component on the main GUI thread. m_shared = new Scatter3DController(boundingRect().toRect()); setSharedController(m_shared); - m_shared->setActiveDataProxy(new QItemModelScatterDataProxy); QObject::connect(m_shared, &Scatter3DController::selectedItemIndexChanged, this, &DeclarativeScatter::selectedItemIndexChanged); @@ -81,16 +80,6 @@ void DeclarativeScatter::setObjectColor(const QColor &baseColor) m_shared->setObjectColor(baseColor); } -QScatterDataProxy *DeclarativeScatter::dataProxy() const -{ - return static_cast<QScatterDataProxy *>(m_shared->activeDataProxy()); -} - -void DeclarativeScatter::setDataProxy(QScatterDataProxy *dataProxy) -{ - m_shared->setActiveDataProxy(dataProxy); -} - Q3DValueAxis *DeclarativeScatter::axisX() const { return static_cast<Q3DValueAxis *>(m_shared->axisX()); @@ -180,4 +169,48 @@ int DeclarativeScatter::selectedItemIndex() const return m_shared->selectedItemIndex(); } +QQmlListProperty<QScatter3DSeries> DeclarativeScatter::seriesList() +{ + return QQmlListProperty<QScatter3DSeries>(this, this, + &DeclarativeScatter::appendSeriesFunc, + &DeclarativeScatter::countSeriesFunc, + &DeclarativeScatter::atSeriesFunc, + &DeclarativeScatter::clearSeriesFunc); +} + +void DeclarativeScatter::appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series) +{ + reinterpret_cast<DeclarativeScatter *>(list->data)->addSeries(series); +} + +int DeclarativeScatter::countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list) +{ + return reinterpret_cast<DeclarativeScatter *>(list->data)->m_shared->scatterSeriesList().size(); +} + +QScatter3DSeries *DeclarativeScatter::atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, int index) +{ + return reinterpret_cast<DeclarativeScatter *>(list->data)->m_shared->scatterSeriesList().at(index); +} + +void DeclarativeScatter::clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list) +{ + DeclarativeScatter *declScatter = reinterpret_cast<DeclarativeScatter *>(list->data); + QList<QScatter3DSeries *> realList = declScatter->m_shared->scatterSeriesList(); + int count = realList.size(); + for (int i = 0; i < count; i++) + declScatter->removeSeries(realList.at(i)); +} + +void DeclarativeScatter::addSeries(QScatter3DSeries *series) +{ + m_shared->addSeries(series); +} + +void DeclarativeScatter::removeSeries(QScatter3DSeries *series) +{ + m_shared->removeSeries(series); + series->setParent(this); // Reparent as removing will leave series parentless +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativescatter_p.h b/src/datavisualizationqml2/declarativescatter_p.h index c066f42c..e229c0d5 100644 --- a/src/datavisualizationqml2/declarativescatter_p.h +++ b/src/datavisualizationqml2/declarativescatter_p.h @@ -35,6 +35,7 @@ #include "declarativescatter_p.h" #include "q3dvalueaxis.h" #include "qscatterdataproxy.h" +#include "qscatter3dseries.h" #include <QAbstractItemModel> #include <QQuickItem> @@ -45,7 +46,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class DeclarativeScatter : public AbstractDeclarative { Q_OBJECT - Q_PROPERTY(QScatterDataProxy *dataProxy READ dataProxy WRITE setDataProxy) Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX) Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY) Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ) @@ -53,6 +53,7 @@ class DeclarativeScatter : public AbstractDeclarative Q_PROPERTY(bool objectSmoothingEnabled READ isObjectSmoothingEnabled WRITE setObjectSmoothingEnabled NOTIFY meshFileNameChanged) Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName NOTIFY meshFileNameChanged) Q_PROPERTY(int selectedItemIndex READ selectedItemIndex WRITE setSelectedItemIndex NOTIFY selectedItemIndexChanged) + Q_PROPERTY(QQmlListProperty<QScatter3DSeries> seriesList READ seriesList) public: explicit DeclarativeScatter(QQuickItem *parent = 0); @@ -60,9 +61,6 @@ public: Q_INVOKABLE void setObjectColor(const QColor &baseColor); // TODO property (or more likely as part of data set) - QScatterDataProxy *dataProxy() const; - void setDataProxy(QScatterDataProxy *dataProxy); - Q3DValueAxis *axisX() const; void setAxisX(Q3DValueAxis *axis); Q3DValueAxis *axisY() const; @@ -82,6 +80,14 @@ public: void setSelectedItemIndex(int index); int selectedItemIndex() const; + QQmlListProperty<QScatter3DSeries> seriesList(); + static void appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series); + static int countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list); + static QScatter3DSeries *atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, int index); + static void clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list); + Q_INVOKABLE void addSeries(QScatter3DSeries *series); + Q_INVOKABLE void removeSeries(QScatter3DSeries *series); + signals: void selectedItemIndexChanged(int index); void meshFileNameChanged(QString filename); diff --git a/src/datavisualizationqml2/declarativesurface.cpp b/src/datavisualizationqml2/declarativesurface.cpp index 853d0d59..25f27f16 100644 --- a/src/datavisualizationqml2/declarativesurface.cpp +++ b/src/datavisualizationqml2/declarativesurface.cpp @@ -41,9 +41,6 @@ DeclarativeSurface::DeclarativeSurface(QQuickItem *parent) m_shared = new Surface3DController(boundingRect().toRect()); setSharedController(m_shared); - QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy; - m_shared->setActiveDataProxy(proxy); - QObject::connect(m_shared, &Surface3DController::smoothSurfaceEnabledChanged, this, &DeclarativeSurface::smoothSurfaceEnabledChanged); QObject::connect(m_shared, &Surface3DController::selectedPointChanged, this, @@ -88,16 +85,6 @@ QSGNode *DeclarativeSurface::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa return node; } -void DeclarativeSurface::setDataProxy(QSurfaceDataProxy *dataProxy) -{ - m_shared->setActiveDataProxy(dataProxy); -} - -QSurfaceDataProxy *DeclarativeSurface::dataProxy() const -{ - return static_cast<QSurfaceDataProxy *>(m_shared->activeDataProxy()); -} - Q3DValueAxis *DeclarativeSurface::axisX() const { return static_cast<Q3DValueAxis *>(m_shared->axisX()); @@ -138,16 +125,6 @@ bool DeclarativeSurface::isSmoothSurfaceEnabled() const return m_shared->smoothSurface(); } -void DeclarativeSurface::setSurfaceVisible(bool visible) -{ - m_shared->setSurfaceVisible(visible); -} - -bool DeclarativeSurface::isSurfaceVisible() const -{ - return m_shared->surfaceVisible(); -} - void DeclarativeSurface::setSurfaceGridEnabled(bool enabled) { m_shared->setSurfaceGrid(enabled); @@ -211,4 +188,48 @@ void DeclarativeSurface::setControllerGradient(const ColorGradient &gradient) m_shared->setGradient(newGradient); } +QQmlListProperty<QSurface3DSeries> DeclarativeSurface::seriesList() +{ + return QQmlListProperty<QSurface3DSeries>(this, this, + &DeclarativeSurface::appendSeriesFunc, + &DeclarativeSurface::countSeriesFunc, + &DeclarativeSurface::atSeriesFunc, + &DeclarativeSurface::clearSeriesFunc); +} + +void DeclarativeSurface::appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, QSurface3DSeries *series) +{ + reinterpret_cast<DeclarativeSurface *>(list->data)->addSeries(series); +} + +int DeclarativeSurface::countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list) +{ + return reinterpret_cast<DeclarativeSurface *>(list->data)->m_shared->surfaceSeriesList().size(); +} + +QSurface3DSeries *DeclarativeSurface::atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, int index) +{ + return reinterpret_cast<DeclarativeSurface *>(list->data)->m_shared->surfaceSeriesList().at(index); +} + +void DeclarativeSurface::clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list) +{ + DeclarativeSurface *declSurface = reinterpret_cast<DeclarativeSurface *>(list->data); + QList<QSurface3DSeries *> realList = declSurface->m_shared->surfaceSeriesList(); + int count = realList.size(); + for (int i = 0; i < count; i++) + declSurface->removeSeries(realList.at(i)); +} + +void DeclarativeSurface::addSeries(QSurface3DSeries *series) +{ + m_shared->addSeries(series); +} + +void DeclarativeSurface::removeSeries(QSurface3DSeries *series) +{ + m_shared->removeSeries(series); + series->setParent(this); // Reparent as removing will leave series parentless +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativesurface_p.h b/src/datavisualizationqml2/declarativesurface_p.h index df3a280c..c6284a9b 100644 --- a/src/datavisualizationqml2/declarativesurface_p.h +++ b/src/datavisualizationqml2/declarativesurface_p.h @@ -36,6 +36,7 @@ #include "q3dvalueaxis.h" #include "qsurfacedataproxy.h" #include "colorgradient_p.h" +#include "qsurface3dseries.h" #include <QAbstractItemModel> #include <QQuickItem> @@ -47,23 +48,19 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class DeclarativeSurface : public AbstractDeclarative { Q_OBJECT - Q_PROPERTY(QSurfaceDataProxy *dataProxy READ dataProxy WRITE setDataProxy) Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX) Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY) Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ) - Q_PROPERTY(bool surfaceVisible READ isSurfaceVisible WRITE setSurfaceVisible NOTIFY surfaceVisibleChanged) Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled NOTIFY smoothSurfaceEnabledChanged) Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled NOTIFY surfaceGridEnabledChanged) Q_PROPERTY(ColorGradient *gradient READ gradient WRITE setGradient) Q_PROPERTY(QPointF selectedPoint READ selectedPoint WRITE setSelectedPoint NOTIFY selectedPointChanged) + Q_PROPERTY(QQmlListProperty<QSurface3DSeries> seriesList READ seriesList) public: explicit DeclarativeSurface(QQuickItem *parent = 0); ~DeclarativeSurface(); - QSurfaceDataProxy *dataProxy() const; - void setDataProxy(QSurfaceDataProxy *dataProxy); - Q3DValueAxis *axisX() const; void setAxisX(Q3DValueAxis *axis); Q3DValueAxis *axisY() const; @@ -71,9 +68,6 @@ public: Q3DValueAxis *axisZ() const; void setAxisZ(Q3DValueAxis *axis); - void setSurfaceVisible(bool visible); - bool isSurfaceVisible() const; - void setSmoothSurfaceEnabled(bool enabled); bool isSmoothSurfaceEnabled() const; @@ -86,6 +80,14 @@ public: void setSelectedPoint(const QPointF &position); QPointF selectedPoint() const; + QQmlListProperty<QSurface3DSeries> seriesList(); + static void appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, QSurface3DSeries *series); + static int countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list); + static QSurface3DSeries *atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, int index); + static void clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list); + Q_INVOKABLE void addSeries(QSurface3DSeries *series); + Q_INVOKABLE void removeSeries(QSurface3DSeries *series); + signals: void surfaceVisibleChanged(bool visible); void smoothSurfaceEnabledChanged(bool enabled); diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index 268c8faa..496a454d 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -50,8 +50,9 @@ GraphModifier::GraphModifier(Q3DBars *barchart) m_monthAxis(new Q3DCategoryAxis), m_genericRowAxis(new Q3DCategoryAxis), m_genericColumnAxis(new Q3DCategoryAxis), - m_temperatureData(new QBarDataProxy), - m_genericData(new QBarDataProxy), + m_temperatureData(new QBar3DSeries), + m_temperatureData2(new QBar3DSeries), + m_genericData(new QBar3DSeries), m_currentAxis(m_fixedRangeAxis), m_negativeValuesOn(false), m_useNullInputHandler(false), @@ -112,11 +113,9 @@ GraphModifier::GraphModifier(Q3DBars *barchart) m_chart->setShadowQuality(QDataVis::ShadowQualitySoftMedium); m_temperatureData->setItemLabelFormat(QStringLiteral("@valueTitle for @colLabel @rowLabel: @valueLabel")); + m_temperatureData2->setItemLabelFormat(QStringLiteral("** @valueTitle for @colLabel @rowLabel: @valueLabel **")); m_genericData->setItemLabelFormat(QStringLiteral("@valueTitle for (@rowIdx, @colIdx): @valueLabel")); - m_genericData->setColumnLabels(genericColumnLabels); - - m_chart->addDataProxy(m_temperatureData); - m_chart->addDataProxy(m_genericData); + m_genericData->dataProxy()->setColumnLabels(genericColumnLabels); m_chart->setFont(QFont("Times Roman", 20)); @@ -144,7 +143,9 @@ void GraphModifier::restart(bool dynamicData) m_static = !dynamicData; if (m_static) { - m_chart->setActiveDataProxy(m_temperatureData); + m_chart->addSeries(m_temperatureData); + m_chart->addSeries(m_temperatureData2); + m_chart->removeSeries(m_genericData); m_chart->setTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)")); @@ -154,7 +155,9 @@ void GraphModifier::restart(bool dynamicData) m_chart->setSelectionMode(QDataVis::SelectionRow | QDataVis::SelectionSlice); } else { - m_chart->setActiveDataProxy(m_genericData); + m_chart->removeSeries(m_temperatureData); + m_chart->removeSeries(m_temperatureData2); + m_chart->addSeries(m_genericData); m_chart->setTitle(QStringLiteral("Generic data")); @@ -213,10 +216,11 @@ void GraphModifier::releaseAxes() void GraphModifier::releaseProxies() { - // Releases all proxies - results in default proxy. - // Proxies will get readded back when graph is switched as setDataProxy call is made. - m_chart->releaseDataProxy(m_temperatureData); - m_chart->releaseDataProxy(m_genericData); + // Releases all series + // Correct series will get readded back when graph is switched + m_chart->removeSeries(m_temperatureData); + m_chart->removeSeries(m_temperatureData2); + m_chart->removeSeries(m_genericData); } void GraphModifier::flipViews() @@ -260,7 +264,7 @@ void GraphModifier::createMassiveArray() dataArray->append(dataRow); } - m_chart->activeDataProxy()->resetArray(dataArray, genericRowLabels, genericColumnLabels); + m_chart->seriesList().at(0)->dataProxy()->resetArray(dataArray, genericRowLabels, genericColumnLabels); qDebug() << "Created Massive Array (" << arrayDimension << "), time:" << timer.elapsed(); } @@ -295,9 +299,23 @@ void GraphModifier::resetTemperatureData() dataSet->append(dataRow); } + QBarDataArray *dataSet2 = new QBarDataArray; + + dataSet2->reserve(m_years.size()); + for (int year = m_years.size() - 1; year >= 0; year--) { + dataRow = new QBarDataRow(m_months.size()); + // Create data items + for (int month = m_months.size() - 1; month >= 0 ; month--) { + // Add data to rows + (*dataRow)[month].setValue(temp[year][month]); + } + // Add row to set + dataSet2->append(dataRow); + } // Add data to chart (chart assumes ownership) - m_temperatureData->resetArray(dataSet, m_years, m_months); + m_temperatureData->dataProxy()->resetArray(dataSet, m_years, m_months); + m_temperatureData2->dataProxy()->resetArray(dataSet2, m_years, m_months); } @@ -318,7 +336,7 @@ void GraphModifier::addRow() // TODO Needs to be changed to account for data window offset once it is implemented. QString label = QStringLiteral("Add %1").arg(addCounter++); - m_chart->activeDataProxy()->addRow(dataRow, label); + m_chart->seriesList().at(0)->dataProxy()->addRow(dataRow, label); } void GraphModifier::addRows() @@ -328,13 +346,13 @@ void GraphModifier::addRows() for (int i = 0; i < m_rowCount; i++) { QBarDataRow *dataRow = new QBarDataRow(m_columnCount); for (int j = 0; j < m_columnCount; j++) - (*dataRow)[j].setValue(qreal(j + i + m_chart->activeDataProxy()->rowCount()) + m_minval); + (*dataRow)[j].setValue(qreal(j + i + m_chart->seriesList().at(0)->dataProxy()->rowCount()) + m_minval); dataArray.append(dataRow); labels.append(QStringLiteral("Add %1").arg(addCounter++)); } // TODO Needs to be changed to account for data window offset once it is implemented. - m_chart->activeDataProxy()->addRows(dataArray, labels); + m_chart->seriesList().at(0)->dataProxy()->addRows(dataArray, labels); } void GraphModifier::insertRow() @@ -347,7 +365,7 @@ void GraphModifier::insertRow() // TODO Needs to be changed to account for data window offset once it is implemented. int row = qMax(m_selectedBar.x(), 0); QString label = QStringLiteral("Insert %1").arg(insertCounter++); - m_chart->activeDataProxy()->insertRow(row, dataRow, label); + m_chart->seriesList().at(0)->dataProxy()->insertRow(row, dataRow, label); } void GraphModifier::insertRows() @@ -359,14 +377,14 @@ void GraphModifier::insertRows() for (int i = 0; i < m_rowCount; i++) { QBarDataRow *dataRow = new QBarDataRow(m_columnCount); for (int j = 0; j < m_columnCount; j++) - (*dataRow)[j].setValue(qreal(j + i + m_chart->activeDataProxy()->rowCount()) + m_minval); + (*dataRow)[j].setValue(qreal(j + i + m_chart->seriesList().at(0)->dataProxy()->rowCount()) + m_minval); dataArray.append(dataRow); labels.append(QStringLiteral("Insert %1").arg(insertCounter++)); } // TODO Needs to be changed to account for data window offset once it is implemented. int row = qMax(m_selectedBar.x(), 0); - m_chart->activeDataProxy()->insertRows(row, dataArray, labels); + m_chart->seriesList().at(0)->dataProxy()->insertRows(row, dataArray, labels); qDebug() << "Inserted" << m_rowCount << "rows, time:" << timer.elapsed(); } @@ -377,7 +395,7 @@ void GraphModifier::changeItem() int column = m_selectedBar.y(); if (row >= 0 && column >= 0) { QBarDataItem item(qreal(rand() % 100)); - m_chart->activeDataProxy()->setItem(row, column, item); + m_chart->seriesList().at(0)->dataProxy()->setItem(row, column, item); } } @@ -386,11 +404,11 @@ void GraphModifier::changeRow() // TODO Needs to be changed to account for data window offset once it is implemented. int row = m_selectedBar.x(); if (row >= 0) { - QBarDataRow *newRow = new QBarDataRow(m_chart->activeDataProxy()->rowAt(row)->size()); + QBarDataRow *newRow = new QBarDataRow(m_chart->seriesList().at(0)->dataProxy()->rowAt(row)->size()); for (int i = 0; i < newRow->size(); i++) (*newRow)[i].setValue(qreal(rand() % int(m_maxval)) + m_minval); QString label = QStringLiteral("Change %1").arg(changeCounter++); - m_chart->activeDataProxy()->setRow(row, newRow, label); + m_chart->seriesList().at(0)->dataProxy()->setRow(row, newRow, label); } } @@ -403,13 +421,13 @@ void GraphModifier::changeRows() QBarDataArray newArray; QStringList labels; for (int i = startRow; i <= row; i++ ) { - QBarDataRow *newRow = new QBarDataRow(m_chart->activeDataProxy()->rowAt(i)->size()); + QBarDataRow *newRow = new QBarDataRow(m_chart->seriesList().at(0)->dataProxy()->rowAt(i)->size()); for (int j = 0; j < newRow->size(); j++) (*newRow)[j].setValue(qreal(rand() % int(m_maxval)) + m_minval); newArray.append(newRow); labels.append(QStringLiteral("Change %1").arg(changeCounter++)); } - m_chart->activeDataProxy()->setRows(startRow, newArray, labels); + m_chart->seriesList().at(0)->dataProxy()->setRows(startRow, newArray, labels); } } @@ -418,7 +436,7 @@ void GraphModifier::removeRow() // TODO Needs to be changed to account for data window offset once it is implemented. int row = m_selectedBar.x(); if (row >= 0) - m_chart->activeDataProxy()->removeRows(row, 1); + m_chart->seriesList().at(0)->dataProxy()->removeRows(row, 1); } void GraphModifier::removeRows() @@ -427,7 +445,7 @@ void GraphModifier::removeRows() int row = m_selectedBar.x(); if (row >= 0) { int startRow = qMax(row - 2, 0); - m_chart->activeDataProxy()->removeRows(startRow, 3); + m_chart->seriesList().at(0)->dataProxy()->removeRows(startRow, 3); } } diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index 11af4949..a9d6119b 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -21,7 +21,7 @@ #include <QtDataVisualization/q3dbars.h> #include <QtDataVisualization/qabstract3dinputhandler.h> - +#include <QtDataVisualization/qbar3dseries.h> #include <QFont> #include <QDebug> #include <QStringList> @@ -110,8 +110,9 @@ private: Q3DCategoryAxis *m_monthAxis; Q3DCategoryAxis *m_genericRowAxis; Q3DCategoryAxis *m_genericColumnAxis; - QBarDataProxy *m_temperatureData; - QBarDataProxy *m_genericData; + QBar3DSeries *m_temperatureData; + QBar3DSeries *m_temperatureData2; + QBar3DSeries *m_genericData; Q3DValueAxis *m_currentAxis; bool m_negativeValuesOn; bool m_useNullInputHandler; diff --git a/tests/multigraphs/data.cpp b/tests/multigraphs/data.cpp index 31bc5391..a488a276 100644 --- a/tests/multigraphs/data.cpp +++ b/tests/multigraphs/data.cpp @@ -21,6 +21,9 @@ #include "data.h" #include <QtDataVisualization/Q3DValueAxis> #include <QtDataVisualization/Q3DCamera> +#include <QtDataVisualization/QBar3DSeries> +#include <QtDataVisualization/QScatter3DSeries> +#include <QtDataVisualization/QSurface3DSeries> #include <QScrollBar> #include <QSize> #include <QImage> @@ -53,8 +56,8 @@ Data::Data(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars, m_surface->setSurfaceGridEnabled(false); m_surface->setBackgroundVisible(false); m_surface->setSmoothSurfaceEnabled(false); - m_surface->setActiveDataProxy(new QHeightMapSurfaceDataProxy()); m_surface->scene()->activeCamera()->setCameraPosition(0.0, 90.0, 150); + m_surface->addSeries(new QSurface3DSeries(new QHeightMapSurfaceDataProxy())); // Initialize scatter m_scatter->setTheme(QDataVis::ThemeStoneMoss); @@ -63,6 +66,7 @@ Data::Data(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars, m_scatter->setObjectType(QDataVis::MeshStylePoints); m_scatter->setShadowQuality(QDataVis::ShadowQualitySoftLow); m_scatter->scene()->activeCamera()->setCameraPosition(0.0, 85.0, 150); + m_scatter->addSeries(new QScatter3DSeries); // Initialize bars m_bars->setTheme(QDataVis::ThemeQt); @@ -72,6 +76,7 @@ Data::Data(Q3DSurface *surface, Q3DScatter *scatter, Q3DBars *bars, m_bars->setShadowQuality(QDataVis::ShadowQualityLow); m_bars->setBarSpacing(QSizeF(0.0, 0.0)); m_bars->scene()->activeCamera()->setCameraPosition(0.0, 75.0, 150); + m_bars->addSeries(new QBar3DSeries); // Hide scroll bar m_statusArea->verticalScrollBar()->setVisible(false); @@ -108,15 +113,15 @@ void Data::updateData() if (m_mode != Surface) setData(depthMap); else - static_cast<QHeightMapSurfaceDataProxy *>(m_surface->activeDataProxy())->setHeightMap( + static_cast<QHeightMapSurfaceDataProxy *>(m_surface->seriesList().at(0)->dataProxy())->setHeightMap( depthMap); } void Data::clearData() { - m_bars->activeDataProxy()->resetArray(0); - m_scatter->activeDataProxy()->resetArray(0); - m_surface->activeDataProxy()->resetArray(0); + m_bars->seriesList().at(0)->dataProxy()->resetArray(0); + m_scatter->seriesList().at(0)->dataProxy()->resetArray(0); + m_surface->seriesList().at(0)->dataProxy()->resetArray(0); } void Data::setResolution(int selection) @@ -226,7 +231,7 @@ void Data::setData(const QImage &image) } QScatterDataArray *dataArray = new QScatterDataArray(m_scatterDataArray->mid(0, count)); - m_scatter->activeDataProxy()->resetArray(dataArray); + m_scatter->seriesList().at(0)->dataProxy()->resetArray(dataArray); } else { QBarDataArray *dataArray = m_barDataArray; for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) { @@ -235,7 +240,7 @@ void Data::setData(const QImage &image) newRow[j] = qreal(bits[bitCount + (j * 4)]); } - m_bars->activeDataProxy()->resetArray(dataArray); + m_bars->seriesList().at(0)->dataProxy()->resetArray(dataArray); } } diff --git a/tests/qmlcamera/qml/qmlcamera/Data.qml b/tests/qmlcamera/qml/qmlcamera/Data.qml index 8b7057d5..2072aaed 100644 --- a/tests/qmlcamera/qml/qmlcamera/Data.qml +++ b/tests/qmlcamera/qml/qmlcamera/Data.qml @@ -23,6 +23,7 @@ Item { property alias mapping: valueMapping property alias model: dataModel property alias proxy: modelProxy + property alias series: barSeries BarDataMapping { id: valueMapping @@ -37,6 +38,12 @@ Item { itemModel: dataModel } + Bar3DSeries { + id: barSeries + dataProxy: modelProxy + itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel" + } + ListModel { id: dataModel ListElement{ year: "2006"; month: "Jan"; expenses: "4"; income: "5" } diff --git a/tests/qmlcamera/qml/qmlcamera/main.qml b/tests/qmlcamera/qml/qmlcamera/main.qml index 4fff55e7..1f87d5eb 100644 --- a/tests/qmlcamera/qml/qmlcamera/main.qml +++ b/tests/qmlcamera/qml/qmlcamera/main.qml @@ -50,14 +50,13 @@ Item { font.pointSize: 35 theme: Bars3D.ThemeRetro labelStyle: Bars3D.LabelStyleFromTheme - dataProxy: chartData.proxy + seriesList: [chartData.series] barThickness: 0.5 barSpacing: Qt.size(0.5, 0.5) barSpacingRelative: false columnAxis: chartAxes.column valueAxis: chartAxes.expenses - itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel" onSelectedBarChanged: { // Set camControlArea current row to selected bar diff --git a/tests/scattertest/main.cpp b/tests/scattertest/main.cpp index 8da3898c..2e8792ad 100644 --- a/tests/scattertest/main.cpp +++ b/tests/scattertest/main.cpp @@ -133,7 +133,7 @@ int main(int argc, char **argv) shadowQuality->addItem(QStringLiteral("Low Soft")); shadowQuality->addItem(QStringLiteral("Medium Soft")); shadowQuality->addItem(QStringLiteral("High Soft")); - shadowQuality->setCurrentIndex(3); + shadowQuality->setCurrentIndex(0); QFontComboBox *fontList = new QFontComboBox(widget); diff --git a/tests/scattertest/scatterchart.cpp b/tests/scattertest/scatterchart.cpp index ed188e68..fa59c204 100644 --- a/tests/scattertest/scatterchart.cpp +++ b/tests/scattertest/scatterchart.cpp @@ -18,6 +18,7 @@ #include "scatterchart.h" #include <QtDataVisualization/qscatterdataproxy.h> +#include <QtDataVisualization/qscatter3dseries.h> #include <QtDataVisualization/q3dvalueaxis.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> @@ -38,15 +39,18 @@ ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter) m_chart->setFont(font); m_chart->setObjectType(QDataVis::MeshStyleSpheres, true); m_chart->setTheme(QDataVis::ThemeStoneMoss); - m_chart->setShadowQuality(QDataVis::ShadowQualityHigh); + m_chart->setShadowQuality(QDataVis::ShadowQualityNone); m_chart->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetFront); m_chart->setAxisX(new Q3DValueAxis); m_chart->setAxisY(new Q3DValueAxis); m_chart->setAxisZ(new Q3DValueAxis); + QScatter3DSeries *series = new QScatter3DSeries; + QScatter3DSeries *series2 = new QScatter3DSeries; - QScatterDataProxy *proxy = new QScatterDataProxy; - proxy->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel"); - m_chart->setActiveDataProxy(proxy); + m_chart->addSeries(series); + m_chart->addSeries(series2); + series->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel"); + series->setItemLabelFormat("** @xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel **"); m_chart->setSelectionMode(QDataVis::SelectionItem); @@ -70,17 +74,22 @@ void ScatterDataModifier::addData() m_chart->axisY()->setTitle("Y"); m_chart->axisZ()->setTitle("Z"); m_chart->axisX()->setRange(-50.0, 50.0); - m_chart->axisY()->setRange(-1.0, 1.0); + m_chart->axisY()->setRange(-1.0, 1.2); m_chart->axisZ()->setRange(-50.0, 50.0); QScatterDataArray *dataArray = new QScatterDataArray; dataArray->resize(numberOfItems); QScatterDataItem *ptrToDataArray = &dataArray->first(); + QScatterDataArray *dataArray2 = new QScatterDataArray; + dataArray2->resize(numberOfItems); + QScatterDataItem *ptrToDataArray2 = &dataArray2->first(); #ifdef RANDOM_SCATTER for (int i = 0; i < numberOfItems; i++) { ptrToDataArray->setPosition(randVector()); ptrToDataArray++; + ptrToDataArray2->setPosition(randVector()); + ptrToDataArray2++; } #else float limit = qSqrt(numberOfItems) / 2.0f; @@ -88,11 +97,14 @@ void ScatterDataModifier::addData() for (float j = -limit; j < limit; j++) { ptrToDataArray->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 7.5)), j)); ptrToDataArray++; + ptrToDataArray2->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 7.5)) + 0.2, j)); + ptrToDataArray2++; } } #endif - static_cast<QScatterDataProxy *>(m_chart->activeDataProxy())->resetArray(dataArray); + m_chart->seriesList().at(0)->dataProxy()->resetArray(dataArray); + m_chart->seriesList().at(1)->dataProxy()->resetArray(dataArray2); } void ScatterDataModifier::changeStyle() @@ -174,7 +186,7 @@ void ScatterDataModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality s void ScatterDataModifier::clear() { - m_chart->activeDataProxy()->resetArray(0); + m_chart->seriesList().at(0)->dataProxy()->resetArray(0); qDebug() << m_loopCounter << "Cleared array"; } @@ -198,8 +210,8 @@ void ScatterDataModifier::resetAxes() void ScatterDataModifier::addOne() { QScatterDataItem item(randVector()); - int addIndex = m_chart->activeDataProxy()->addItem(item); - qDebug() << m_loopCounter << "added one to index:" << addIndex << "array size:" << m_chart->activeDataProxy()->array()->size(); + int addIndex = m_chart->seriesList().at(0)->dataProxy()->addItem(item); + qDebug() << m_loopCounter << "added one to index:" << addIndex << "array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } void ScatterDataModifier::addBunch() @@ -207,15 +219,15 @@ void ScatterDataModifier::addBunch() QScatterDataArray items(100); for (int i = 0; i < items.size(); i++) items[i].setPosition(randVector()); - int addIndex = m_chart->activeDataProxy()->addItems(items); - qDebug() << m_loopCounter << "added bunch to index:" << addIndex << "array size:" << m_chart->activeDataProxy()->array()->size(); + int addIndex = m_chart->seriesList().at(0)->dataProxy()->addItems(items); + qDebug() << m_loopCounter << "added bunch to index:" << addIndex << "array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } void ScatterDataModifier::insertOne() { QScatterDataItem item(randVector()); - m_chart->activeDataProxy()->insertItem(0, item); - qDebug() << m_loopCounter << "Inserted one, array size:" << m_chart->activeDataProxy()->array()->size(); + m_chart->seriesList().at(0)->dataProxy()->insertItem(0, item); + qDebug() << m_loopCounter << "Inserted one, array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } void ScatterDataModifier::insertBunch() @@ -223,43 +235,43 @@ void ScatterDataModifier::insertBunch() QScatterDataArray items(100); for (int i = 0; i < items.size(); i++) items[i].setPosition(randVector()); - m_chart->activeDataProxy()->insertItems(0, items); - qDebug() << m_loopCounter << "Inserted bunch, array size:" << m_chart->activeDataProxy()->array()->size(); + m_chart->seriesList().at(0)->dataProxy()->insertItems(0, items); + qDebug() << m_loopCounter << "Inserted bunch, array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } void ScatterDataModifier::changeOne() { - if (m_selectedItem >= 0 && m_chart->activeDataProxy()->array()->size()) { + if (m_selectedItem >= 0 && m_chart->seriesList().at(0)->dataProxy()->array()->size()) { QScatterDataItem item(randVector()); - m_chart->activeDataProxy()->setItem(m_selectedItem, item); - qDebug() << m_loopCounter << "Changed one, array size:" << m_chart->activeDataProxy()->array()->size(); + m_chart->seriesList().at(0)->dataProxy()->setItem(m_selectedItem, item); + qDebug() << m_loopCounter << "Changed one, array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } } void ScatterDataModifier::changeBunch() { - if (m_chart->activeDataProxy()->array()->size()) { - int amount = qMin(m_chart->activeDataProxy()->array()->size(), 100); + if (m_chart->seriesList().at(0)->dataProxy()->array()->size()) { + int amount = qMin(m_chart->seriesList().at(0)->dataProxy()->array()->size(), 100); QScatterDataArray items(amount); for (int i = 0; i < items.size(); i++) items[i].setPosition(randVector()); - m_chart->activeDataProxy()->setItems(0, items); - qDebug() << m_loopCounter << "Changed bunch, array size:" << m_chart->activeDataProxy()->array()->size(); + m_chart->seriesList().at(0)->dataProxy()->setItems(0, items); + qDebug() << m_loopCounter << "Changed bunch, array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } } void ScatterDataModifier::removeOne() { if (m_selectedItem >= 0) { - m_chart->activeDataProxy()->removeItems(m_selectedItem, 1); - qDebug() << m_loopCounter << "Removed one, array size:" << m_chart->activeDataProxy()->array()->size(); + m_chart->seriesList().at(0)->dataProxy()->removeItems(m_selectedItem, 1); + qDebug() << m_loopCounter << "Removed one, array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } } void ScatterDataModifier::removeBunch() { - m_chart->activeDataProxy()->removeItems(0, 100); - qDebug() << m_loopCounter << "Removed bunch, array size:" << m_chart->activeDataProxy()->array()->size(); + m_chart->seriesList().at(0)->dataProxy()->removeItems(0, 100); + qDebug() << m_loopCounter << "Removed bunch, array size:" << m_chart->seriesList().at(0)->dataProxy()->array()->size(); } void ScatterDataModifier::timeout() diff --git a/tests/spectrum/spectrumapp/main.cpp b/tests/spectrum/spectrumapp/main.cpp index 5c756753..e9913706 100644 --- a/tests/spectrum/spectrumapp/main.cpp +++ b/tests/spectrum/spectrumapp/main.cpp @@ -25,6 +25,7 @@ #include <QtDataVisualization/q3dcategoryaxis.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> #include <QGuiApplication> #include <QAudio> @@ -106,7 +107,7 @@ MainApp::MainApp(Q3DBars *window) QObject::connect(m_restartTimer, &QTimer::timeout, this, &MainApp::restart); QBarDataProxy *proxy = new QBarDataProxy; - m_chart->setActiveDataProxy(proxy); + m_chart->addSeries(new QBar3DSeries(proxy)); } MainApp::~MainApp() @@ -143,7 +144,7 @@ void MainApp::spectrumChanged(qint64 position, qint64 length, const FrequencySpe (*data)[barIndex(e.frequency)].setValue(qMax(data->at(barIndex(e.frequency)).value(), qreal(e.amplitude))); } } - static_cast<QBarDataProxy *>(m_chart->activeDataProxy())->insertRow(0, data); + m_chart->seriesList().at(0)->dataProxy()->insertRow(0, data); } void MainApp::stateChanged(QAudio::Mode mode, QAudio::State state) diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp index f5c39f98..4365e055 100644 --- a/tests/surfacetest/graphmodifier.cpp +++ b/tests/surfacetest/graphmodifier.cpp @@ -19,6 +19,7 @@ #include "graphmodifier.h" #include <QtDataVisualization/Q3DValueAxis> #include <QtDataVisualization/QSurfaceDataProxy> +#include <QtDataVisualization/QSurface3DSeries> #include <qmath.h> #include <QLinearGradient> @@ -46,13 +47,15 @@ GraphModifier::GraphModifier(Q3DSurface *graph) m_rangeZ(16.0), m_minX(-8.0), m_minZ(-8.0), - m_planeArray(0) + m_planeArray(0), + m_theSeries(new QSurface3DSeries) { m_graph->setAxisX(new Q3DValueAxis); m_graph->setAxisY(new Q3DValueAxis); m_graph->setAxisZ(new Q3DValueAxis); m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX); m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ); + m_graph->addSeries(m_theSeries); changeStyle(); connect(&m_timer, &QTimer::timeout, this, &GraphModifier::timeout); @@ -79,7 +82,7 @@ void GraphModifier::toggleSurfaceGrid(bool enable) void GraphModifier::toggleSurface(bool enable) { qDebug() << "GraphModifier::toggleSurface" << enable; - m_graph->setSurfaceVisible(enable); + m_theSeries->setVisible(enable); } void GraphModifier::toggleSqrtSin(bool enable) @@ -316,8 +319,9 @@ void GraphModifier::changeStyle() void GraphModifier::selectButtonClicked() { - int row = rand() % m_graph->activeDataProxy()->rowCount(); - int col = rand() % m_graph->activeDataProxy()->columnCount(); + QSurfaceDataProxy *proxy = m_theSeries->dataProxy(); + int row = rand() % proxy->rowCount(); + int col = rand() % proxy->columnCount(); m_graph->setSelectedPoint(QPoint(row, col)); } @@ -357,7 +361,7 @@ void GraphModifier::timeout() } // Reset same array to make it redraw - m_graph->activeDataProxy()->resetArray(m_planeArray); + m_theSeries->dataProxy()->resetArray(m_planeArray); } void GraphModifier::resetArrayAndSliders(QSurfaceDataArray *array, qreal minZ, qreal maxZ, qreal minX, qreal maxX) @@ -367,7 +371,7 @@ void GraphModifier::resetArrayAndSliders(QSurfaceDataArray *array, qreal minZ, q m_axisRangeSliderX->setValue(maxX - minX); m_axisRangeSliderZ->setValue(maxZ - minZ); - m_graph->activeDataProxy()->resetArray(array); + m_theSeries->dataProxy()->resetArray(array); } void GraphModifier::changeShadowQuality(int quality) diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h index 853c698a..b0f9b3da 100644 --- a/tests/surfacetest/graphmodifier.h +++ b/tests/surfacetest/graphmodifier.h @@ -21,6 +21,7 @@ #include <QtDataVisualization/Q3DSurface> #include <QtDataVisualization/QSurfaceDataProxy> +#include <QtDataVisualization/QSurface3DSeries> #include <QSlider> #include <QTimer> #include <QLabel> @@ -97,6 +98,7 @@ private: QTimer m_timer; QSurfaceDataArray *m_planeArray; QLabel *m_selectionInfoLabel; + QSurface3DSeries *m_theSeries; }; #endif |