Surface Graph Gallery
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick.Controls
import QtGraphs
import SurfaceGallery
Item {
id: oscilloscopeView
property int sampleColumns: sampleSlider.value
property int sampleRows: sampleColumns / 2
property int sampleCache: 24
required property bool portraitMode
property real controlWidth: oscilloscopeView.portraitMode ? oscilloscopeView.width - 10
: oscilloscopeView.width / 4 - 6.66
property real buttonWidth: oscilloscopeView.portraitMode ? oscilloscopeView.width - 10
: oscilloscopeView.width / 3 - 7.5
onSampleRowsChanged: {
surfaceSeries.selectedPoint = surfaceSeries.invalidSelectionPosition
generateData()
}
DataSource {
id: dataSource
}
Item {
id: dataView
anchors.bottom: parent.bottom
width: parent.width
height: parent.height - controlArea.height
Surface3D {
id: surfaceGraph
anchors.fill: parent
Surface3DSeries {
id: surfaceSeries
drawMode: Surface3DSeries.DrawSurfaceAndWireframe
itemLabelFormat: "@xLabel, @zLabel: @yLabel"
itemLabelVisible: false
onItemLabelChanged: {
if (surfaceSeries.selectedPoint == surfaceSeries.invalidSelectionPosition)
selectionText.text = "No selection";
else
selectionText.text = surfaceSeries.itemLabel;
}
}
shadowQuality: AbstractGraph3D.ShadowQualityNone
selectionMode: AbstractGraph3D.SelectionSlice | AbstractGraph3D.SelectionItemAndColumn
theme: Theme3D {
type: Theme3D.ThemeIsabelle
backgroundEnabled: false
}
scene.activeCamera.cameraPreset: Camera3D.CameraPresetFrontHigh
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
measureFps: true
renderingMode: AbstractGraph3D.RenderDirectToBackground
onCurrentFpsChanged: (currentFps)=> {
fpsText.text = "FPS: " + currentFps;
}
Component.onCompleted: oscilloscopeView.generateData();
}
}
Timer {
id: refreshTimer
interval: 1000 / frequencySlider.value
running: true
repeat: true
onTriggered: dataSource.update(surfaceSeries);
}
Rectangle {
id: controlArea
height: oscilloscopeView.portraitMode ? flatShadingToggle.implicitHeight * 7
: flatShadingToggle.implicitHeight * 2
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
color: surfaceGraph.theme.backgroundColor
// Samples
Rectangle {
id: samples
width: oscilloscopeView.controlWidth
height: flatShadingToggle.implicitHeight
anchors.left: parent.left
anchors.top: parent.top
anchors.margins: 5
color: surfaceGraph.theme.windowColor
border.color: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 4
Row {
anchors.centerIn: parent
spacing: 10
padding: 5
Slider {
id: sampleSlider
from: oscilloscopeView.sampleCache * 2
to: from * 10
stepSize: oscilloscopeView.sampleCache
background: Rectangle {
x: sampleSlider.leftPadding
y: sampleSlider.topPadding + sampleSlider.availableHeight / 2
- height / 2
implicitWidth: 200
implicitHeight: 4
width: sampleSlider.availableWidth
height: implicitHeight
radius: 2
color: surfaceGraph.theme.gridLineColor
Rectangle {
width: sampleSlider.visualPosition * parent.width
height: parent.height
color: surfaceGraph.theme.labelTextColor
radius: 2
}
}
handle: Rectangle {
x: sampleSlider.leftPadding + sampleSlider.visualPosition
* (sampleSlider.availableWidth - width)
y: sampleSlider.topPadding + sampleSlider.availableHeight / 2
- height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: sampleSlider.pressed ? surfaceGraph.theme.gridLineColor
: surfaceGraph.theme.windowColor
border.color: sampleSlider.pressed ? surfaceGraph.theme.labelTextColor
: surfaceGraph.theme.gridLineColor
}
Component.onCompleted: value = from;
}
Text {
id: samplesText
text: "Samples: " + (oscilloscopeView.sampleRows * oscilloscopeView.sampleColumns)
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: surfaceGraph.theme.labelTextColor
}
}
}
// Frequency
Rectangle {
id: frequency
width: oscilloscopeView.controlWidth
height: flatShadingToggle.implicitHeight
anchors.left: oscilloscopeView.portraitMode ? parent.left : samples.right
anchors.top: oscilloscopeView.portraitMode ? samples.bottom : parent.top
anchors.margins: 5
color: surfaceGraph.theme.windowColor
border.color: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 4
Row {
anchors.centerIn: parent
spacing: 10
padding: 5
Slider {
id: frequencySlider
from: 2
to: 60
stepSize: 2
value: 30
background: Rectangle {
x: frequencySlider.leftPadding
y: frequencySlider.topPadding + frequencySlider.availableHeight / 2
- height / 2
implicitWidth: 200
implicitHeight: 4
width: frequencySlider.availableWidth
height: implicitHeight
radius: 2
color: surfaceGraph.theme.gridLineColor
Rectangle {
width: frequencySlider.visualPosition * parent.width
height: parent.height
color: surfaceGraph.theme.labelTextColor
radius: 2
}
}
handle: Rectangle {
x: frequencySlider.leftPadding + frequencySlider.visualPosition
* (frequencySlider.availableWidth - width)
y: frequencySlider.topPadding + frequencySlider.availableHeight / 2
- height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: frequencySlider.pressed ? surfaceGraph.theme.gridLineColor
: surfaceGraph.theme.windowColor
border.color: frequencySlider.pressed ? surfaceGraph.theme.labelTextColor
: surfaceGraph.theme.gridLineColor
}
}
Text {
id: frequencyText
text: "Freq: " + frequencySlider.value + " Hz"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: surfaceGraph.theme.labelTextColor
}
}
}
// FPS
Rectangle {
id: fpsindicator
width: oscilloscopeView.controlWidth
height: flatShadingToggle.implicitHeight
anchors.left: oscilloscopeView.portraitMode ? parent.left : frequency.right
anchors.top: oscilloscopeView.portraitMode ? frequency.bottom : parent.top
anchors.margins: 5
color: surfaceGraph.theme.windowColor
border.color: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 4
Text {
id: fpsText
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: surfaceGraph.theme.labelTextColor
}
}
// Selection
Rectangle {
id: selection
width: oscilloscopeView.controlWidth
height: flatShadingToggle.implicitHeight
anchors.left: oscilloscopeView.portraitMode ? parent.left : fpsindicator.right
anchors.top: oscilloscopeView.portraitMode ? fpsindicator.bottom : parent.top
anchors.margins: 5
color: surfaceGraph.theme.windowColor
border.color: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 4
Text {
id: selectionText
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: "No selection"
color: surfaceGraph.theme.labelTextColor
}
}
// Flat shading
Button {
id: flatShadingToggle
width: oscilloscopeView.buttonWidth
anchors.left: parent.left
anchors.top: selection.bottom
anchors.margins: 5
text: surfaceSeries.flatShadingSupported ? "Show\nSmooth" : "Flat\nnot supported"
enabled: surfaceSeries.flatShadingSupported
onClicked: {
if (surfaceSeries.flatShadingEnabled) {
surfaceSeries.flatShadingEnabled = false;
text = "Show\nFlat"
} else {
surfaceSeries.flatShadingEnabled = true;
text = "Show\nSmooth"
}
}
contentItem: Text {
text: flatShadingToggle.text
opacity: flatShadingToggle.enabled ? 1.0 : 0.3
color: surfaceGraph.theme.labelTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
opacity: flatShadingToggle.enabled ? 1 : 0.3
color: flatShadingToggle.down ? surfaceGraph.theme.gridLineColor
: surfaceGraph.theme.windowColor
border.color: flatShadingToggle.down ? surfaceGraph.theme.labelTextColor
: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 2
}
}
// Surface grid
Button {
id: surfaceGridToggle
width: oscilloscopeView.buttonWidth
anchors.left: oscilloscopeView.portraitMode ? parent.left : flatShadingToggle.right
anchors.top: oscilloscopeView.portraitMode ? flatShadingToggle.bottom : selection.bottom
anchors.margins: 5
text: "Hide\nSurface Grid"
onClicked: {
if (surfaceSeries.drawMode & Surface3DSeries.DrawWireframe) {
surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe;
text = "Show\nSurface Grid";
} else {
surfaceSeries.drawMode |= Surface3DSeries.DrawWireframe;
text = "Hide\nSurface Grid";
}
}
contentItem: Text {
text: surfaceGridToggle.text
color: surfaceGraph.theme.labelTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
color: surfaceGridToggle.down ? surfaceGraph.theme.gridLineColor
: surfaceGraph.theme.windowColor
border.color: surfaceGridToggle.down ? surfaceGraph.theme.labelTextColor
: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 2
}
}
// Exit
Button {
id: exitButton
width: oscilloscopeView.buttonWidth
height: surfaceGridToggle.height
anchors.left: oscilloscopeView.portraitMode ? parent.left : surfaceGridToggle.right
anchors.top: oscilloscopeView.portraitMode ? surfaceGridToggle.bottom : selection.bottom
anchors.margins: 5
text: "Quit"
onClicked: Qt.quit();
contentItem: Text {
text: exitButton.text
color: surfaceGraph.theme.labelTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
color: exitButton.down ? surfaceGraph.theme.gridLineColor
: surfaceGraph.theme.windowColor
border.color: exitButton.down ? surfaceGraph.theme.labelTextColor
: surfaceGraph.theme.gridLineColor
border.width: 1
radius: 2
}
}
}
function generateData() {
dataSource.generateData(oscilloscopeView.sampleCache, oscilloscopeView.sampleRows,
oscilloscopeView.sampleColumns,
surfaceGraph.axisX.min, surfaceGraph.axisX.max,
surfaceGraph.axisY.min, surfaceGraph.axisY.max,
surfaceGraph.axisZ.min, surfaceGraph.axisZ.max);
}
}