summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/examples.pro3
-rw-r--r--examples/qmlbars/qmlbars.pro2
-rw-r--r--examples/qmlcustominput/qmlcustominput.pro2
-rw-r--r--examples/qmllegend/qmllegend.pro2
-rw-r--r--examples/qmlmultigraph/qmlmultigraph.pro2
-rw-r--r--examples/qmloscilloscope/datasource.cpp155
-rw-r--r--examples/qmloscilloscope/datasource.h55
-rw-r--r--examples/qmloscilloscope/doc/src/qmloscilloscope.qdoc102
-rw-r--r--examples/qmloscilloscope/main.cpp56
-rw-r--r--examples/qmloscilloscope/qml/qmloscilloscope/NewButton.qml52
-rw-r--r--examples/qmloscilloscope/qml/qmloscilloscope/main.qml290
-rw-r--r--examples/qmloscilloscope/qmloscilloscope.desktop11
-rw-r--r--examples/qmloscilloscope/qmloscilloscope.pro27
-rw-r--r--examples/qmloscilloscope/qmloscilloscope.qrc6
-rw-r--r--examples/qmloscilloscope/qmloscilloscope64.pngbin0 -> 3400 bytes
-rw-r--r--examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.cpp81
-rw-r--r--examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.h33
-rw-r--r--examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.pri180
-rw-r--r--examples/qmlscatter/qmlscatter.pro2
-rw-r--r--examples/qmlsurface/qmlsurface.pro2
-rw-r--r--src/datavisualization/data/qbardataproxy.cpp10
-rw-r--r--src/datavisualization/data/qbardataproxy.h1
-rw-r--r--src/datavisualization/data/qsurface3dseries.cpp2
-rw-r--r--src/datavisualization/data/qsurfacedataproxy.cpp32
-rw-r--r--src/datavisualization/data/qsurfacedataproxy.h3
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp6
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp30
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h2
-rw-r--r--tests/qmldynamicdata/qmldynamicdata.pro2
29 files changed, 1107 insertions, 44 deletions
diff --git a/examples/examples.pro b/examples/examples.pro
index e6bb0aab..9c3b5704 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -4,7 +4,8 @@ SUBDIRS += qmlbars \
qmlsurface \
qmlcustominput \
qmllegend \
- qmlmultigraph
+ qmlmultigraph \
+ qmloscilloscope
!android:!ios {
SUBDIRS += bars \
diff --git a/examples/qmlbars/qmlbars.pro b/examples/qmlbars/qmlbars.pro
index 758e7b76..7d0460f0 100644
--- a/examples/qmlbars/qmlbars.pro
+++ b/examples/qmlbars/qmlbars.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the examples.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmlbars
folder_01.target = qml
diff --git a/examples/qmlcustominput/qmlcustominput.pro b/examples/qmlcustominput/qmlcustominput.pro
index c58eff49..40cd3f24 100644
--- a/examples/qmlcustominput/qmlcustominput.pro
+++ b/examples/qmlcustominput/qmlcustominput.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the examples.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmlcustominput
folder_01.target = qml
diff --git a/examples/qmllegend/qmllegend.pro b/examples/qmllegend/qmllegend.pro
index d896e7ac..4bf520b2 100644
--- a/examples/qmllegend/qmllegend.pro
+++ b/examples/qmllegend/qmllegend.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the examples.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmllegend
folder_01.target = qml
diff --git a/examples/qmlmultigraph/qmlmultigraph.pro b/examples/qmlmultigraph/qmlmultigraph.pro
index af4e0d90..42955632 100644
--- a/examples/qmlmultigraph/qmlmultigraph.pro
+++ b/examples/qmlmultigraph/qmlmultigraph.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the examples.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmlmultigraph
folder_01.target = qml
diff --git a/examples/qmloscilloscope/datasource.cpp b/examples/qmloscilloscope/datasource.cpp
new file mode 100644
index 00000000..3d2f908d
--- /dev/null
+++ b/examples/qmloscilloscope/datasource.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "datasource.h"
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
+#include <QDebug>
+#include <qmath.h>
+
+using namespace QtDataVisualization;
+
+Q_DECLARE_METATYPE(QSurface3DSeries *)
+
+DataSource::DataSource(QQuickView *appViewer, QObject *parent) :
+ QObject(parent),
+ m_appViewer(appViewer),
+ m_index(-1),
+ m_resetArray(0)
+{
+ qRegisterMetaType<QSurface3DSeries *>();
+}
+
+DataSource::~DataSource()
+{
+ clearData();
+}
+
+//! [0]
+void DataSource::generateData(int cacheCount, int rowCount, int columnCount,
+ float xMin, float xMax, float yMin, float yMax,
+ float zMin, float zMax)
+{
+ clearData();
+
+ // Re-create the cache array
+ m_data.resize(cacheCount);
+ for (int i(0); i < cacheCount; i++) {
+ QSurfaceDataArray &array = m_data[i];
+ array.reserve(rowCount);
+ for (int j(0); j < rowCount; j++)
+ array.append(new QSurfaceDataRow(columnCount));
+ }
+
+ float xRange = xMax - xMin;
+ float yRange = yMax - yMin;
+ float zRange = zMax - zMin;
+
+ // Populate caches
+ for (int i(0); i < cacheCount; i++) {
+ QSurfaceDataArray &cache = m_data[i];
+ for (int j(0); j < rowCount; j++) {
+ QSurfaceDataRow &row = *(cache[j]);
+ for (int k(0); k < columnCount; k++) {
+ float colMod = (float(k)) / float(columnCount - 1.0f);
+ float rowMod = (float(j)) / float(rowCount - 1.0f);
+ float xRangeMod = xRange * colMod;
+ float yRangeMod = yRange * rowMod;
+ float zRangeMod = zRange * rowMod;
+ float x = xRangeMod + xMin;
+ float y = (((float(qSin(M_PI * rowMod / 2.0) + 1.0)))
+ + ((float(qSin(M_PI * rowMod * colMod * 5.0) + 1.0))))
+ * yRangeMod * 0.2f +
+ + (0.15f * float(rand()) / float(RAND_MAX)) * yRangeMod;
+ float z = zRangeMod + zMin;
+ row[k] = QVector3D(x, y, z);
+ }
+ }
+ }
+}
+//! [0]
+
+//! [1]
+void DataSource::update(QSurface3DSeries *series)
+{
+ if (series) {
+ // Each iteration uses data from a different cached array
+ m_index++;
+ if (m_index > m_data.count() - 1)
+ m_index = 0;
+
+ QSurfaceDataArray array = m_data.at(m_index);
+ int newRowCount = array.size();
+ int newColumnCount = array.at(0)->size();
+
+ // If the first time or the dimensions of the cache array have changed,
+ // reconstruct the reset array
+ if (m_resetArray || series->dataProxy()->rowCount() != newRowCount
+ || series->dataProxy()->columnCount() != newColumnCount) {
+ m_resetArray = new QSurfaceDataArray();
+ m_resetArray->reserve(newRowCount);
+ for (int i(0); i < newRowCount; i++)
+ m_resetArray->append(new QSurfaceDataRow(newColumnCount));
+ }
+
+ // Copy items from our cache to the reset array
+ for (int i(0); i < newRowCount; i++) {
+ const QSurfaceDataRow &sourceRow = *(array.at(i));
+ QSurfaceDataRow &row = *(*m_resetArray)[i];
+ for (int j(0); j < newColumnCount; j++)
+ row[j].setPosition(sourceRow.at(j).position());
+ }
+
+ // Notify the proxy that data has changed
+ series->dataProxy()->resetArray(m_resetArray);
+ }
+}
+//! [1]
+
+//! [2]
+QString DataSource::selectionLabel(QSurface3DSeries *series, QValue3DAxis *axisX,
+ QValue3DAxis *axisY, QValue3DAxis *axisZ)
+{
+ QString label;
+
+ if (series && series->selectedPoint() != QSurface3DSeries::invalidSelectionPosition()) {
+ const QSurfaceDataItem *item = series->dataProxy()->itemAt(series->selectedPoint());
+ QString x;
+ QString y;
+ QString z;
+ x.sprintf(axisX->labelFormat().toUtf8().constData(), int(item->x()));
+ y.sprintf(axisY->labelFormat().toUtf8().constData(), int(item->y()));
+ z.sprintf(axisZ->labelFormat().toUtf8().constData(), int(item->z()));
+ label = QStringLiteral("%1, %3: %2").arg(x).arg(y).arg(z);
+ } else {
+ label = QStringLiteral("No selection");
+ }
+
+ return label;
+}
+//! [2]
+
+void DataSource::clearData()
+{
+ for (int i(0); i < m_data.size(); i++) {
+ QSurfaceDataArray &array = m_data[i];
+ for (int j(0); j < array.size(); j++)
+ delete array[j];
+ array.clear();
+ }
+}
diff --git a/examples/qmloscilloscope/datasource.h b/examples/qmloscilloscope/datasource.h
new file mode 100644
index 00000000..6ef0cacb
--- /dev/null
+++ b/examples/qmloscilloscope/datasource.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 DATASOURCE_H
+#define DATASOURCE_H
+
+#include <QtDataVisualization>
+#include <QObject>
+
+class QQuickView;
+
+using namespace QtDataVisualization;
+
+class DataSource : public QObject
+{
+ Q_OBJECT
+public:
+ explicit DataSource(QQuickView *appViewer, QObject *parent = 0);
+ virtual ~DataSource();
+
+ //! [0]
+public slots:
+ void generateData(int cacheCount, int rowCount, int columnCount,
+ float xMin, float xMax, float yMin, float yMax, float zMin, float zMax);
+
+ void update(QSurface3DSeries *series);
+
+ QString selectionLabel(QSurface3DSeries *series, QValue3DAxis *axisX,
+ QValue3DAxis *axisY, QValue3DAxis *axisZ);
+ //! [0]
+private:
+ void clearData();
+
+ QQuickView *m_appViewer;
+ QVector<QSurfaceDataArray> m_data;
+ int m_index;
+ QSurfaceDataArray *m_resetArray;
+};
+
+#endif
diff --git a/examples/qmloscilloscope/doc/src/qmloscilloscope.qdoc b/examples/qmloscilloscope/doc/src/qmloscilloscope.qdoc
new file mode 100644
index 00000000..9fdcd8d2
--- /dev/null
+++ b/examples/qmloscilloscope/doc/src/qmloscilloscope.qdoc
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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
+**
+****************************************************************************/
+
+/*!
+ \example qmloscilloscope
+ \title Qt Quick 2 Oscilloscope Example
+ \ingroup qtdatavisualization_examples
+ \brief Example of a hybrid C++ and QML application.
+
+ The Qt Quick 2 oscilloscope example shows how to combine C++ and QML in an application,
+ as well as showing data that changes realtime.
+
+ \image qmloscilloscope-example.png
+
+ The interesting thing about this example is combining C++ and QML, so we'll concentrate on
+ that and skip explaining the basic functionality - for
+ more detailed QML example documentation, see \l{Qt Quick 2 Scatter Example}.
+
+ \section1 Data source in C++
+
+ The item model based proxies are good for simple and/or static graphs, but to achieve
+ best performance when displaying data changing in realtime, the basic proxies should be used.
+ Those are not supported in QML, as the data items they store are not \l{QObject}s and
+ cannot therefore be directly manipulated from QML code.
+ To overcome this limitation, we implement a simple \c DataSource class in C++ to populate the
+ data proxy of the series.
+
+ The \c DataSource class provides three methods that can be called from QML:
+
+ \snippet ../examples/qmloscilloscope/datasource.h 0
+
+ The first method, \c generateData(), creates a cache of simulated oscilloscope data for us
+ to display. The data is cached in a format accepted by QSurfaceDataProxy:
+
+ \snippet ../examples/qmloscilloscope/datasource.cpp 0
+
+ The secod method, \c update(), copies one set of the cached data into another array, which we
+ set to the data proxy of the series by calling QSurfaceDataProxy::resetArray().
+ We reuse the same array if the array dimensions have not changed to minimize overhead:
+
+ \snippet ../examples/qmloscilloscope/datasource.cpp 1
+
+ \note Even though we are operating on the array pointer we have previously set to the proxy
+ we still need to call QSurfaceDataProxy::resetArray() after changing the data in it to prompt
+ the graph to render the data.
+
+ The final method, \c selectionLabel(), is used to generate a label string we can show on the
+ QML ui. This method utilizes the axis formats to format the label:
+
+ \snippet ../examples/qmloscilloscope/datasource.cpp 2
+
+ To be able to access the \c DataSource methods from QML, we need to expose it. We do this by
+ defining a context property in application main:
+
+ \snippet ../examples/qmloscilloscope/main.cpp 0
+
+ \section1 QML
+
+ In the QML codes, we define a Surface3D graph normally and give it a Surface3DSeries:
+
+ \snippet ../examples/qmloscilloscope/qml/qmloscilloscope/main.qml 0
+
+ One interesting detail is that we don't specify a proxy for the Surface3DSeries we attach
+ to the graph. This makes the series to utilize the default QSurfaceDataProxy.
+
+ We also specify an empty string for \l{Abstract3DSeries::itemLabelFormat}{itemLabelFormat}, since we want to display
+ the selected item information in a \c Text element instead of a label above the selection pointer.
+ This is done because the selection pointer moves around a lot as the data changes, which makes
+ the regular selection label difficult to read.
+ When selection point changes, we update the label text using a helper function
+ \c updateSelectionLabel(), which calls one of the methods we defined for our \c DataSource class
+ to obtain the label:
+
+ \snippet ../examples/qmloscilloscope/qml/qmloscilloscope/main.qml 1
+
+ We initialize the \c DataSource cache when the graph is complete by calling a helper function
+ \c generateData(), which calls the method with the same name on the \c DataSource:
+
+ \snippet ../examples/qmloscilloscope/qml/qmloscilloscope/main.qml 2
+ \dots 4
+ \snippet ../examples/qmloscilloscope/qml/qmloscilloscope/main.qml 4
+
+ To trigger the updates in data, we define a \c Timer item which calls the \c update() method on the \c
+ DataSource at requested intervals. The label update is also triggered on each cycle:
+
+ \snippet ../examples/qmloscilloscope/qml/qmloscilloscope/main.qml 3
+*/
diff --git a/examples/qmloscilloscope/main.cpp b/examples/qmloscilloscope/main.cpp
new file mode 100644
index 00000000..c4e2430a
--- /dev/null
+++ b/examples/qmloscilloscope/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "datasource.h"
+#include <QtDataVisualization/qutils.h>
+#include <QtGui/QGuiApplication>
+#include "qtquick2applicationviewer.h"
+#ifdef Q_OS_ANDROID
+#include <QtCore/QDir>
+#include <QtQml/QQmlEngine>
+#endif
+#include <QtCore/QDebug>
+#include <QtQml/QQmlContext>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QtQuick2ApplicationViewer viewer;
+
+ // Enable antialiasing
+ viewer.setFormat(QtDataVisualization::qDefaultSurfaceFormat());
+
+#ifdef Q_OS_ANDROID
+ viewer.addImportPath(QString::fromLatin1("assets:/qml"));
+ viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(),
+ QString::fromLatin1("lib")));
+#endif
+ viewer.setTitle(QStringLiteral("Oscilloscope example"));
+
+ //! [0]
+ DataSource dataSource(&viewer);
+ viewer.rootContext()->setContextProperty("dataSource", &dataSource);
+ //! [0]
+
+ viewer.setSource(QUrl("qrc:/qml/qmloscilloscope/main.qml"));
+ viewer.setResizeMode(QQuickView::SizeRootObjectToView);
+ viewer.show();
+
+ return app.exec();
+}
diff --git a/examples/qmloscilloscope/qml/qmloscilloscope/NewButton.qml b/examples/qmloscilloscope/qml/qmloscilloscope/NewButton.qml
new file mode 100644
index 00000000..e4fb99d2
--- /dev/null
+++ b/examples/qmloscilloscope/qml/qmloscilloscope/NewButton.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Styles 1.0
+
+Item {
+ id: newbutton
+
+ property alias text: buttonText.text
+
+ signal clicked
+
+ implicitWidth: buttonText.implicitWidth + 5
+ implicitHeight: buttonText.implicitHeight + 10
+
+ Button {
+ id: buttonText
+ width: parent.width
+ height: parent.height
+
+ style: ButtonStyle {
+ label: Component {
+ Text {
+ text: buttonText.text
+ clip: true
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.fill: parent
+ }
+ }
+ }
+ onClicked: newbutton.clicked()
+ }
+}
diff --git a/examples/qmloscilloscope/qml/qmloscilloscope/main.qml b/examples/qmloscilloscope/qml/qmloscilloscope/main.qml
new file mode 100644
index 00000000..4d330b60
--- /dev/null
+++ b/examples/qmloscilloscope/qml/qmloscilloscope/main.qml
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+import QtQuick.Controls 1.0
+import QtDataVisualization 1.0
+import "."
+
+Item {
+ id: mainView
+ width: 1280
+ height: 1024
+
+ property int sampleCache: 5
+ property int sampleColumns: sampleSlider.value
+ property int sampleRows: sampleColumns / 2
+
+ Item {
+ id: dataView
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: parent.height - buttonLayout.height
+
+ Surface3D {
+ id: surfaceGraph
+
+ width: dataView.width
+ height: dataView.height
+ shadowQuality: AbstractGraph3D.ShadowQualityNone
+ selectionMode: AbstractGraph3D.SelectionSlice | AbstractGraph3D.SelectionItemAndRow
+
+ axisX.labelFormat: "%d ms"
+ axisY.labelFormat: "%d W"
+ axisZ.labelFormat: "%d mV"
+ axisX.min: 0
+ axisY.min: 0
+ axisZ.min: 0
+ axisX.max: 1000
+ axisY.max: 100
+ axisZ.max: 800
+ axisX.segmentCount: 4
+ axisY.segmentCount: 4
+ axisZ.segmentCount: 4
+
+ //! [0]
+ Surface3DSeries {
+ id: surfaceSeries
+ drawMode: Surface3DSeries.DrawSurface;
+ flatShadingEnabled: false;
+ meshSmooth: true
+ itemLabelFormat: ""
+
+ onSelectedPointChanged: mainView.updateSelectionLabel()
+ }
+ //! [0]
+
+ //! [2]
+ Component.onCompleted: mainView.generateData()
+ //! [2]
+ }
+ }
+
+ //! [3]
+ Timer {
+ id: refreshTimer
+ interval: 1000 / frequencySlider.value
+ running: true
+ repeat: true
+ onTriggered: {
+ dataSource.update(surfaceSeries)
+ mainView.updateSelectionLabel()
+ }
+ }
+ //! [3]
+
+ Rectangle {
+ width: parent.width
+ height: flatShadingToggle.height
+ anchors.left: parent.left
+ anchors.top: parent.top
+ color: surfaceGraph.theme.backgroundColor
+
+ RowLayout {
+ id: buttonLayout
+ Layout.minimumHeight: flatShadingToggle.height
+ anchors.fill: parent
+ spacing: 0
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.minimumWidth: samplesText.implicitWidth + 120
+ Layout.maximumWidth: samplesText.implicitWidth + 120
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ border.color: "gray"
+ border.width: 1
+ radius: 4
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.margins: parent.border.width + 1
+
+ Slider {
+ id: sampleSlider
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ Layout.minimumWidth: 100
+ minimumValue: 10
+ maximumValue: 400
+ stepSize: 5
+ updateValueWhileDragging: true
+ value: 50
+
+ onValueChanged: {
+ refreshTimer
+ surfaceSeries.selectedPoint = surfaceSeries.invalidSelectionPosition
+ mainView.generateData()
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.minimumWidth: samplesText.implicitWidth + 10
+ Layout.maximumWidth: samplesText.implicitWidth + 10
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ Text {
+ id: samplesText
+ text: "Samples: " + (mainView.sampleRows * mainView.sampleColumns)
+ anchors.fill: parent
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.minimumWidth: frequencyText.implicitWidth + 120
+ Layout.maximumWidth: frequencyText.implicitWidth + 120
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ border.color: "gray"
+ border.width: 1
+ radius: 4
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.margins: parent.border.width + 1
+
+ Slider {
+ id: frequencySlider
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ Layout.minimumWidth: 100
+ minimumValue: 2
+ maximumValue: 60
+ stepSize: 2
+ updateValueWhileDragging: true
+ value: 30
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.minimumWidth: frequencyText.implicitWidth + 10
+ Layout.maximumWidth: frequencyText.implicitWidth + 10
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ Text {
+ id: frequencyText
+ text: "Target freq: " + frequencySlider.value + " Hz"
+ anchors.fill: parent
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.minimumWidth: selectionText.implicitWidth + 10
+ Layout.maximumWidth: selectionText.implicitWidth + 10
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ border.color: "gray"
+ border.width: 1
+ radius: 4
+
+ Text {
+ id: selectionText
+ text: "No selection"
+ anchors.fill: parent
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+
+ NewButton {
+ id: flatShadingToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ text: "Show Flat"
+ enabled: surfaceSeries.flatShadingSupported
+
+ onClicked: {
+ if (surfaceSeries.flatShadingEnabled === true) {
+ surfaceSeries.flatShadingEnabled = false;
+ text = "Show Flat"
+ } else {
+ surfaceSeries.flatShadingEnabled = true;
+ text = "Show Smooth"
+ }
+ }
+ }
+
+ NewButton {
+ id: surfaceGridToggle
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ text: "Show Surface Grid"
+
+ onClicked: {
+ if (surfaceSeries.drawMode & Surface3DSeries.DrawWireframe) {
+ surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe;
+ text = "Show Surface Grid"
+ } else {
+ surfaceSeries.drawMode |= Surface3DSeries.DrawWireframe;
+ text = "Hide Surface Grid"
+ }
+ }
+ }
+
+ NewButton {
+ id: exitButton
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ text: "Quit"
+
+ onClicked: Qt.quit(0);
+ }
+ }
+ }
+
+ //! [1]
+ function updateSelectionLabel() {
+ selectionText.text = dataSource.selectionLabel(surfaceSeries,
+ surfaceGraph.axisX,
+ surfaceGraph.axisY,
+ surfaceGraph.axisZ)
+ }
+ //! [1]
+
+ //! [4]
+ function generateData() {
+ dataSource.generateData(mainView.sampleCache, mainView.sampleRows,
+ mainView.sampleColumns, surfaceGraph.axisX.min,
+ surfaceGraph.axisX.max, surfaceGraph.axisY.min,
+ surfaceGraph.axisY.max, surfaceGraph.axisZ.min,
+ surfaceGraph.axisZ.max)
+ }
+ //! [4]
+}
diff --git a/examples/qmloscilloscope/qmloscilloscope.desktop b/examples/qmloscilloscope/qmloscilloscope.desktop
new file mode 100644
index 00000000..bd8e8325
--- /dev/null
+++ b/examples/qmloscilloscope/qmloscilloscope.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Terminal=false
+Name=qmloscilloscope
+Exec=/opt/qmloscilloscope/bin/qmloscilloscope
+Icon=qmloscilloscope64
+X-Window-Icon=
+X-HildonDesk-ShowInToolbar=true
+X-Osso-Type=application/x-executable
diff --git a/examples/qmloscilloscope/qmloscilloscope.pro b/examples/qmloscilloscope/qmloscilloscope.pro
new file mode 100644
index 00000000..5e1a3ddd
--- /dev/null
+++ b/examples/qmloscilloscope/qmloscilloscope.pro
@@ -0,0 +1,27 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += datavisualization
+
+# Add more folders to ship with the application, here
+folder_01.source = qml/qmloscilloscope
+folder_01.target = qml
+DEPLOYMENTFOLDERS = folder_01
+
+# Additional import path used to resolve QML modules in Creator's code model
+QML_IMPORT_PATH =
+
+# The .cpp file which was generated for your project. Feel free to hack it.
+SOURCES += main.cpp \
+ datasource.cpp
+HEADERS += datasource.h
+
+# Please do not modify the following two lines. Required for deployment.
+include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
+qtcAddDeployment()
+
+RESOURCES += qmloscilloscope.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
diff --git a/examples/qmloscilloscope/qmloscilloscope.qrc b/examples/qmloscilloscope/qmloscilloscope.qrc
new file mode 100644
index 00000000..a2358789
--- /dev/null
+++ b/examples/qmloscilloscope/qmloscilloscope.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/qmloscilloscope/main.qml</file>
+ <file>qml/qmloscilloscope/NewButton.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/qmloscilloscope/qmloscilloscope64.png b/examples/qmloscilloscope/qmloscilloscope64.png
new file mode 100644
index 00000000..707d5c4e
--- /dev/null
+++ b/examples/qmloscilloscope/qmloscilloscope64.png
Binary files differ
diff --git a/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.cpp b/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.cpp
new file mode 100644
index 00000000..10709d7a
--- /dev/null
+++ b/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.cpp
@@ -0,0 +1,81 @@
+// checksum 0x4f6f version 0x90005
+/*
+ This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+ QtQuick2ApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#include "qtquick2applicationviewer.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtQml/QQmlEngine>
+
+class QtQuick2ApplicationViewerPrivate
+{
+ QString mainQmlFile;
+ friend class QtQuick2ApplicationViewer;
+ static QString adjustPath(const QString &path);
+};
+
+QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path)
+{
+#if defined(Q_OS_MAC)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("%1/../Resources/%2")
+ .arg(QCoreApplication::applicationDirPath(), path);
+#elif defined(Q_OS_BLACKBERRY)
+ if (!QDir::isAbsolutePath(path))
+ return QString::fromLatin1("app/native/%1").arg(path);
+#elif !defined(Q_OS_ANDROID)
+ QString pathInInstallDir =
+ QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+ pathInInstallDir =
+ QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path);
+ if (QFileInfo(pathInInstallDir).exists())
+ return pathInInstallDir;
+#endif
+ return path;
+}
+
+QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
+ : QQuickView(parent)
+ , d(new QtQuick2ApplicationViewerPrivate())
+{
+ connect(engine(), SIGNAL(quit()), SLOT(close()));
+ setResizeMode(QQuickView::SizeRootObjectToView);
+}
+
+QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer()
+{
+ delete d;
+}
+
+void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
+{
+ d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
+#ifdef Q_OS_ANDROID
+ setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile));
+#else
+ setSource(QUrl::fromLocalFile(d->mainQmlFile));
+#endif
+}
+
+void QtQuick2ApplicationViewer::addImportPath(const QString &path)
+{
+ engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path));
+}
+
+void QtQuick2ApplicationViewer::showExpanded()
+{
+#if defined(Q_WS_SIMULATOR) || defined(Q_OS_QNX)
+ showFullScreen();
+#else
+ show();
+#endif
+}
diff --git a/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.h b/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.h
new file mode 100644
index 00000000..cf66f140
--- /dev/null
+++ b/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.h
@@ -0,0 +1,33 @@
+// checksum 0xfde6 version 0x90005
+/*
+ This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+ QtQuick2ApplicationViewer is a convenience class containing mobile device specific
+ code such as screen orientation handling. Also QML paths and debugging are
+ handled here.
+ It is recommended not to modify this file, since newer versions of Qt Creator
+ may offer an updated version of it.
+*/
+
+#ifndef QTQUICK2APPLICATIONVIEWER_H
+#define QTQUICK2APPLICATIONVIEWER_H
+
+#include <QtQuick/QQuickView>
+
+class QtQuick2ApplicationViewer : public QQuickView
+{
+ Q_OBJECT
+
+public:
+ explicit QtQuick2ApplicationViewer(QWindow *parent = 0);
+ virtual ~QtQuick2ApplicationViewer();
+
+ void setMainQmlFile(const QString &file);
+ void addImportPath(const QString &path);
+
+ void showExpanded();
+
+private:
+ class QtQuick2ApplicationViewerPrivate *d;
+};
+
+#endif // QTQUICK2APPLICATIONVIEWER_H
diff --git a/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.pri
new file mode 100644
index 00000000..e5f7990f
--- /dev/null
+++ b/examples/qmloscilloscope/qtquick2applicationviewer/qtquick2applicationviewer.pri
@@ -0,0 +1,180 @@
+# checksum 0x7b0d version 0x90005
+# This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+# The code below adds the QtQuick2ApplicationViewer to the project and handles
+# the activation of QML debugging.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+QT += qml quick
+
+SOURCES += $$PWD/qtquick2applicationviewer.cpp
+HEADERS += $$PWD/qtquick2applicationviewer.h
+INCLUDEPATH += $$PWD
+# This file was generated by an application wizard of Qt Creator.
+# The code below handles deployment to Android and Maemo, aswell as copying
+# of the application data to shadow build directories on desktop.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+defineTest(qtcAddDeployment) {
+for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ greaterThan(QT_MAJOR_VERSION, 4) {
+ itemsources = $${item}.files
+ } else {
+ itemsources = $${item}.sources
+ }
+ $$itemsources = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath= $$eval($${deploymentfolder}.target)
+ export($$itemsources)
+ export($$itempath)
+ DEPLOYMENT += $$item
+}
+
+MAINPROFILEPWD = $$PWD
+
+android-no-sdk {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ target.path = /data/user/qt
+
+ export(target.path)
+ INSTALLS += target
+} else:android {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /assets/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
+ INSTALLS += target
+} else:win32 {
+ copyCommand =
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+ source = $$replace(source, /, \\)
+ sourcePathSegments = $$split(source, \\)
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments)
+ target = $$replace(target, /, \\)
+ target ~= s,\\\\\\.?\\\\,\\,
+ !isEqual(source,$$target) {
+ !isEmpty(copyCommand):copyCommand += &&
+ isEqual(QMAKE_DIR_SEP, \\) {
+ copyCommand += $(COPY_DIR) \"$$source\" \"$$target\"
+ } else {
+ source = $$replace(source, \\\\, /)
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+ target = $$replace(target, \\\\, /)
+ copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\"
+ }
+ }
+ }
+ !isEmpty(copyCommand) {
+ copyCommand = @echo Copying application data... && $$copyCommand
+ copydeploymentfolders.commands = $$copyCommand
+ first.depends = $(first) copydeploymentfolders
+ export(first.depends)
+ export(copydeploymentfolders.commands)
+ QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+ }
+} else:unix {
+ maemo5 {
+ desktopfile.files = $${TARGET}.desktop
+ desktopfile.path = /usr/share/applications/hildon
+ icon.files = $${TARGET}64.png
+ icon.path = /usr/share/icons/hicolor/64x64/apps
+ } else:!isEmpty(MEEGO_VERSION_MAJOR) {
+ desktopfile.files = $${TARGET}_harmattan.desktop
+ desktopfile.path = /usr/share/applications
+ icon.files = $${TARGET}80.png
+ icon.path = /usr/share/icons/hicolor/80x80/apps
+ } else { # Assumed to be a Desktop Unix
+ copyCommand =
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+ source = $$replace(source, \\\\, /)
+ macx {
+ target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target)
+ } else {
+ target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+ }
+ target = $$replace(target, \\\\, /)
+ sourcePathSegments = $$split(source, /)
+ targetFullPath = $$target/$$last(sourcePathSegments)
+ targetFullPath ~= s,/\\.?/,/,
+ !isEqual(source,$$targetFullPath) {
+ !isEmpty(copyCommand):copyCommand += &&
+ copyCommand += $(MKDIR) \"$$target\"
+ copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\"
+ }
+ }
+ !isEmpty(copyCommand) {
+ copyCommand = @echo Copying application data... && $$copyCommand
+ copydeploymentfolders.commands = $$copyCommand
+ first.depends = $(first) copydeploymentfolders
+ export(first.depends)
+ export(copydeploymentfolders.commands)
+ QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+ }
+ }
+ !isEmpty(target.path) {
+ installPrefix = $${target.path}
+ } else {
+ installPrefix = /opt/$${TARGET}
+ }
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ !isEmpty(desktopfile.path) {
+ export(icon.files)
+ export(icon.path)
+ export(desktopfile.files)
+ export(desktopfile.path)
+ INSTALLS += icon desktopfile
+ }
+
+ isEmpty(target.path) {
+ target.path = $${installPrefix}/bin
+ export(target.path)
+ }
+ INSTALLS += target
+}
+
+export (ICON)
+export (INSTALLS)
+export (DEPLOYMENT)
+export (LIBS)
+export (QMAKE_EXTRA_TARGETS)
+}
diff --git a/examples/qmlscatter/qmlscatter.pro b/examples/qmlscatter/qmlscatter.pro
index 0c66c5ae..9d12334a 100644
--- a/examples/qmlscatter/qmlscatter.pro
+++ b/examples/qmlscatter/qmlscatter.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the examples.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmlscatter
folder_01.target = qml
diff --git a/examples/qmlsurface/qmlsurface.pro b/examples/qmlsurface/qmlsurface.pro
index 64c72cf7..560a1e23 100644
--- a/examples/qmlsurface/qmlsurface.pro
+++ b/examples/qmlsurface/qmlsurface.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the examples.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmlsurface
folder_01.target = qml
diff --git a/src/datavisualization/data/qbardataproxy.cpp b/src/datavisualization/data/qbardataproxy.cpp
index a26e446e..4247e963 100644
--- a/src/datavisualization/data/qbardataproxy.cpp
+++ b/src/datavisualization/data/qbardataproxy.cpp
@@ -427,6 +427,16 @@ const QBarDataItem *QBarDataProxy::itemAt(int rowIndex, int columnIndex) const
}
/*!
+ * \return pointer to the item at \a position. The X-value of \a position indicates the row
+ * and the Y-value indicates the column. The item is guaranteed to be valid only
+ * until the next call that modifies data.
+ */
+const QBarDataItem *QBarDataProxy::itemAt(const QPoint &position) const
+{
+ return itemAt(position.x(), position.y());
+}
+
+/*!
* \internal
*/
QBarDataProxyPrivate *QBarDataProxy::dptr()
diff --git a/src/datavisualization/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h
index 0ad71365..780897e8 100644
--- a/src/datavisualization/data/qbardataproxy.h
+++ b/src/datavisualization/data/qbardataproxy.h
@@ -58,6 +58,7 @@ public:
const QBarDataArray *array() const;
const QBarDataRow *rowAt(int rowIndex) const;
const QBarDataItem *itemAt(int rowIndex, int columnIndex) const;
+ const QBarDataItem *itemAt(const QPoint &position) const;
void resetArray();
void resetArray(QBarDataArray *newArray);
diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp
index e5f06cc6..b7e15014 100644
--- a/src/datavisualization/data/qsurface3dseries.cpp
+++ b/src/datavisualization/data/qsurface3dseries.cpp
@@ -221,7 +221,7 @@ void QSurface3DSeries::setSelectedPoint(const QPoint &position)
{
// Don't do this in private to avoid loops, as that is used for callback from controller.
if (d_ptr->m_controller)
- static_cast<Surface3DController *>(d_ptr->m_controller)->setSelectedPoint(position, this);
+ static_cast<Surface3DController *>(d_ptr->m_controller)->setSelectedPoint(position, this, true);
else
dptr()->setSelectedPoint(position);
}
diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp
index 43ce40eb..b19f1f0a 100644
--- a/src/datavisualization/data/qsurfacedataproxy.cpp
+++ b/src/datavisualization/data/qsurfacedataproxy.cpp
@@ -259,6 +259,29 @@ const QSurfaceDataArray *QSurfaceDataProxy::array() const
}
/*!
+ * \return pointer to the item at \a rowIndex, \a columnIndex. It is guaranteed to be valid only
+ * until the next call that modifies data.
+ */
+const QSurfaceDataItem *QSurfaceDataProxy::itemAt(int rowIndex, int columnIndex) const
+{
+ const QSurfaceDataArray &dataArray = *dptrc()->m_dataArray;
+ Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size());
+ const QSurfaceDataRow &dataRow = *dataArray[rowIndex];
+ Q_ASSERT(columnIndex >= 0 && columnIndex < dataRow.size());
+ return &dataRow.at(columnIndex);
+}
+
+/*!
+ * \return pointer to the item at \a position. The X-value of \a position indicates the row
+ * and the Y-value indicates the column. The item is guaranteed to be valid only
+ * until the next call that modifies data.
+ */
+const QSurfaceDataItem *QSurfaceDataProxy::itemAt(const QPoint &position) const
+{
+ return itemAt(position.x(), position.y());
+}
+
+/*!
* \property QSurfaceDataProxy::rowCount
*
* \return number of rows in the data.
@@ -282,15 +305,6 @@ int QSurfaceDataProxy::columnCount() const
}
/*!
- * \return pointer to the item at \a index. It is guaranteed to be valid only until the next call that
- * modifies data.
- */
-const QSurfaceDataItem *QSurfaceDataProxy::itemAt(int index) const
-{
- return &dptrc()->m_dataArray->at(index)->at(2);
-}
-
-/*!
* \internal
*/
QSurfaceDataProxyPrivate *QSurfaceDataProxy::dptr()
diff --git a/src/datavisualization/data/qsurfacedataproxy.h b/src/datavisualization/data/qsurfacedataproxy.h
index 0933faf6..9cfe3b77 100644
--- a/src/datavisualization/data/qsurfacedataproxy.h
+++ b/src/datavisualization/data/qsurfacedataproxy.h
@@ -49,7 +49,8 @@ public:
int rowCount() const;
int columnCount() const;
const QSurfaceDataArray *array() const;
- const QSurfaceDataItem *itemAt(int index) const;
+ const QSurfaceDataItem *itemAt(int rowIndex, int columnIndex) const;
+ const QSurfaceDataItem *itemAt(const QPoint &position) const;
void resetArray(QSurfaceDataArray *newArray);
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index d8146149..adb34458 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -85,6 +85,12 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
automatically. If you wish to control the slice view yourself via Q3DScene, do not set this
flag. When setting this mode flag, either \c SelectionRow or \c SelectionColumn must also
be set, but not both. Slicing is supported by Q3DBars and Q3DSurface only.
+ When this flag is set, slice mode is entered in the following situations:
+ \list
+ \li When selection is changed explicitly via series API to a visible item
+ \li When selection is changed by clicking on the graph
+ \li When the selection mode changes and the selected item is visible
+ \endlist
\value SelectionMultiSeries
Setting this mode means that items for all series at same position are highlighted, instead
of just the selected item. The actual selection in the other series doesn't change.
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 0eb66d0e..5aeecb20 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -103,7 +103,7 @@ void Surface3DController::handleAxisRangeChangedBySender(QObject *sender)
Abstract3DController::handleAxisRangeChangedBySender(sender);
// Update selected point - may be moved offscreen
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
}
void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
@@ -111,10 +111,6 @@ void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
adjustValueAxisRange();
-
- // Visibility changes may require disabling/enabling slicing,
- // so just reset selection to ensure everything is still valid.
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
}
void Surface3DController::handlePendingClick()
@@ -123,7 +119,7 @@ void Surface3DController::handlePendingClick()
QPoint position = m_renderer->clickedPosition();
QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_renderer->clickedSeries());
- setSelectedPoint(position, series);
+ setSelectedPoint(position, series, true);
m_renderer->resetClickedStatus();
}
@@ -154,7 +150,7 @@ void Surface3DController::addSeries(QAbstract3DSeries *series)
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
- setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries);
+ setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries, false);
}
void Surface3DController::removeSeries(QAbstract3DSeries *series)
@@ -164,7 +160,7 @@ void Surface3DController::removeSeries(QAbstract3DSeries *series)
Abstract3DController::removeSeries(series);
if (m_selectedSeries == series)
- setSelectedPoint(invalidSelectionPosition(), 0);
+ setSelectedPoint(invalidSelectionPosition(), 0, false);
if (wasVisible)
adjustValueAxisRange();
@@ -203,7 +199,7 @@ void Surface3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode
if (mode != oldMode) {
// Refresh selection upon mode change to ensure slicing is correctly updated
// according to series the visibility.
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, true);
// Special case: Always deactivate slicing when changing away from slice
// automanagement, as this can't be handled in setSelectedBar.
@@ -215,7 +211,7 @@ void Surface3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode
}
}
-void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series)
+void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series, bool enterSlice)
{
// If the selection targets non-existent point, clear selection instead.
QPoint pos = position;
@@ -253,7 +249,7 @@ void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSer
if (item.x() < axisMinX || item.x() > axisMaxX
|| item.z() < axisMinZ || item.z() > axisMaxZ) {
scene()->setSlicingActive(false);
- } else {
+ } else if (enterSlice) {
scene()->setSlicingActive(true);
}
}
@@ -280,7 +276,7 @@ void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSer
void Surface3DController::clearSelection()
{
- setSelectedPoint(invalidSelectionPosition(), 0);
+ setSelectedPoint(invalidSelectionPosition(), 0, false);
}
void Surface3DController::handleArrayReset()
@@ -291,7 +287,7 @@ void Surface3DController::handleArrayReset()
m_isDataDirty = true;
}
// Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
@@ -335,7 +331,7 @@ void Surface3DController::handleRowsChanged(int startIndex, int count)
adjustValueAxisRange();
// Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
}
@@ -361,7 +357,7 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
adjustValueAxisRange();
// Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
}
@@ -389,7 +385,7 @@ void Surface3DController::handleRowsInserted(int startIndex, int count)
int selectedRow = m_selectedPoint.x();
if (startIndex <= selectedRow) {
selectedRow += count;
- setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries);
+ setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries, false);
}
}
@@ -415,7 +411,7 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count)
else
selectedRow -= count; // Move selected row down by amount of rows removed
- setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries);
+ setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries, false);
}
}
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 624bea47..4ca9c8e2 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -76,7 +76,7 @@ public:
virtual void synchDataToRenderer();
void setSelectionMode(QAbstract3DGraph::SelectionFlags mode);
- void setSelectedPoint(const QPoint &position, QSurface3DSeries *series);
+ void setSelectedPoint(const QPoint &position, QSurface3DSeries *series, bool enterSlice);
virtual void clearSelection();
virtual void handleAxisAutoAdjustRangeChangedInOrientation(
diff --git a/tests/qmldynamicdata/qmldynamicdata.pro b/tests/qmldynamicdata/qmldynamicdata.pro
index b95f1577..12bf7c10 100644
--- a/tests/qmldynamicdata/qmldynamicdata.pro
+++ b/tests/qmldynamicdata/qmldynamicdata.pro
@@ -2,8 +2,6 @@
error( "Couldn't find the tests.pri file!" )
}
-QT += widgets
-
# Add more folders to ship with the application, here
folder_01.source = qml/qmldynamicdata
folder_01.target = qml