summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorTomi Korpipaa <tomi.korpipaa@qt.io>2023-01-30 13:10:05 +0200
committerTomi Korpipaa <tomi.korpipaa@qt.io>2023-02-02 12:05:14 +0200
commit6ae51a12ccd15575197e5aeff4de3273a615c1a9 (patch)
treeed52a789b499c02d36d861eb87cc694fd805f23f /examples
parentb20a41dfb410ef0e99d73bc35dfffade48cf55cb (diff)
Combine 2 examples into one
Combine qmlaxisdrag and qmlaxisformatter examples into one Pick-to: 6.5 Fixes: QTBUG-110699 Change-Id: I5043089ad47370165543b7c09409ba08d5f4690d Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/datavisualization/CMakeLists.txt3
-rw-r--r--examples/datavisualization/datavisualization.pro3
-rw-r--r--examples/datavisualization/qmlaxisdrag/CMakeLists.txt55
-rw-r--r--examples/datavisualization/qmlaxisdrag/doc/images/qmlaxisdrag-example.pngbin89048 -> 0 bytes
-rw-r--r--examples/datavisualization/qmlaxisdrag/doc/src/qmlaxisdrag.qdoc99
-rw-r--r--examples/datavisualization/qmlaxisdrag/main.cpp34
-rw-r--r--examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cubetexture.pngbin10429 -> 0 bytes
-rw-r--r--examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/main.qml308
-rw-r--r--examples/datavisualization/qmlaxisdrag/qmlaxisdrag.pro11
-rw-r--r--examples/datavisualization/qmlaxisdrag/qmlaxisdrag.qrc11
-rw-r--r--examples/datavisualization/qmlaxisformatter/doc/images/qmlaxisformatter-example.pngbin132952 -> 0 bytes
-rw-r--r--examples/datavisualization/qmlaxisformatter/doc/src/qmlaxisformatter.qdoc101
-rw-r--r--examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/main.qml168
-rw-r--r--examples/datavisualization/qmlaxisformatter/qmlaxisformatter.pro16
-rw-r--r--examples/datavisualization/qmlaxisformatter/qmlaxisformatter.qrc6
-rw-r--r--examples/datavisualization/qmlaxishandling/CMakeLists.txt (renamed from examples/datavisualization/qmlaxisformatter/CMakeLists.txt)23
-rw-r--r--examples/datavisualization/qmlaxishandling/customformatter.cpp (renamed from examples/datavisualization/qmlaxisformatter/customformatter.cpp)7
-rw-r--r--examples/datavisualization/qmlaxishandling/customformatter.h (renamed from examples/datavisualization/qmlaxisformatter/customformatter.h)6
-rw-r--r--examples/datavisualization/qmlaxishandling/doc/images/qmlaxishandling-example.pngbin0 -> 132862 bytes
-rw-r--r--examples/datavisualization/qmlaxishandling/doc/src/qmlaxishandling.qdoc189
-rw-r--r--examples/datavisualization/qmlaxishandling/main.cpp (renamed from examples/datavisualization/qmlaxisformatter/main.cpp)20
-rw-r--r--examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml298
-rw-r--r--examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml156
-rw-r--r--examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/Data.qml (renamed from examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/Data.qml)2
-rw-r--r--examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cube.obj (renamed from examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cube.obj)0
-rw-r--r--examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cubetexture.pngbin0 -> 3386 bytes
-rw-r--r--examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/main.qml47
-rw-r--r--examples/datavisualization/qmlaxishandling/qmlaxishandling.pro16
-rw-r--r--examples/datavisualization/qmlaxishandling/qmlaxishandling.qrc12
-rw-r--r--examples/datavisualization/qmlaxishandling/qmldir2
30 files changed, 758 insertions, 835 deletions
diff --git a/examples/datavisualization/CMakeLists.txt b/examples/datavisualization/CMakeLists.txt
index 6081fe25..b6c45906 100644
--- a/examples/datavisualization/CMakeLists.txt
+++ b/examples/datavisualization/CMakeLists.txt
@@ -6,8 +6,7 @@ if(TARGET Qt::Quick)
qt_internal_add_example(qmlscatter)
qt_internal_add_example(qmlsurface)
qt_internal_add_example(qml3doscilloscope)
- qt_internal_add_example(qmlaxisformatter)
- qt_internal_add_example(qmlaxisdrag)
+ qt_internal_add_example(qmlaxishandling)
qt_internal_add_example(qmlspectrogram)
endif()
if(NOT ANDROID AND NOT IOS AND NOT WINRT)
diff --git a/examples/datavisualization/datavisualization.pro b/examples/datavisualization/datavisualization.pro
index 3d108577..ef536c49 100644
--- a/examples/datavisualization/datavisualization.pro
+++ b/examples/datavisualization/datavisualization.pro
@@ -4,8 +4,7 @@ qtHaveModule(quick) {
qmlscatter \
qmlsurface \
qml3doscilloscope \
- qmlaxisformatter \
- qmlaxisdrag \
+ qmlaxishandling \
qmlspectrogram
}
diff --git a/examples/datavisualization/qmlaxisdrag/CMakeLists.txt b/examples/datavisualization/qmlaxisdrag/CMakeLists.txt
deleted file mode 100644
index e7e70916..00000000
--- a/examples/datavisualization/qmlaxisdrag/CMakeLists.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-cmake_minimum_required(VERSION 3.16)
-project(qmlaxisdrag LANGUAGES CXX)
-
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-set(CMAKE_AUTOUIC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}")
-
-find_package(Qt6 COMPONENTS Core)
-find_package(Qt6 COMPONENTS Gui)
-find_package(Qt6 COMPONENTS Qml)
-find_package(Qt6 COMPONENTS Quick)
-find_package(Qt6 COMPONENTS DataVisualization)
-
-qt_add_executable(qmlaxisdrag
- main.cpp
-)
-set_target_properties(qmlaxisdrag PROPERTIES
- WIN32_EXECUTABLE TRUE
- MACOSX_BUNDLE TRUE
-)
-target_link_libraries(qmlaxisdrag PUBLIC
- Qt::Core
- Qt::Gui
- Qt::Qml
- Qt::Quick
- Qt::DataVisualization
-)
-
-qt6_add_qml_module(qmlaxisdrag
- URI AxisDrag
- VERSION 1.0
- NO_RESOURCE_TARGET_PATH
- QML_FILES
- qml/qmlaxisdrag/main.qml
- RESOURCES
- qml/qmlaxisdrag/cube.obj
- qml/qmlaxisdrag/cubetexture.png
-)
-
-install(TARGETS qmlaxisdrag
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
-)
diff --git a/examples/datavisualization/qmlaxisdrag/doc/images/qmlaxisdrag-example.png b/examples/datavisualization/qmlaxisdrag/doc/images/qmlaxisdrag-example.png
deleted file mode 100644
index de33ba66..00000000
--- a/examples/datavisualization/qmlaxisdrag/doc/images/qmlaxisdrag-example.png
+++ /dev/null
Binary files differ
diff --git a/examples/datavisualization/qmlaxisdrag/doc/src/qmlaxisdrag.qdoc b/examples/datavisualization/qmlaxisdrag/doc/src/qmlaxisdrag.qdoc
deleted file mode 100644
index 70eaa9ca..00000000
--- a/examples/datavisualization/qmlaxisdrag/doc/src/qmlaxisdrag.qdoc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example qmlaxisdrag
- \meta tags {DataVisualization, Scatter3D, Custom Input Handler, Dynamic Data, Scatter Graph}
- \meta category {Graphics}
- \title Axis Dragging
- \ingroup qtdatavisualization_qmlexamples
- \brief Implementing axis dragging with a custom input handler in QML.
- \since QtDataVisualization 1.1
-
- The axis dragging example concentrates on showing how to implement axis range
- changing by dragging axis labels in QML. It also gives a quick peek to two other new features
- in Qt Data Visualization 1.1: orthographic projection and dynamic custom item handling.
-
- \image qmlaxisdrag-example.png
-
- \include examples-run.qdocinc
-
- \section1 Overriding Default Input Handling
-
- First we deactivate the default input handling mechanism by setting the active input handler
- of Scatter3D graph to \c{null}:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 0
- \dots
-
- Then we add a MouseArea and set it to fill the parent, which is the same \c Item our
- \c scatterGraph is contained in. We also set it to accept only left mouse button presses,
- as in this example we are not interested in other buttons:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 1
- \dots
-
- Then we need to listen to mouse presses, and when caught, send a selection query to the graph:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 2
-
- Current mouse position, that will be needed for move distance calculation, is caught in
- \c{onPositionChanged}:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 3
- \dots
-
- At the end of \c{onPositionChanged}, we'll save the previous mouse position for move distance
- calculation that will be introduced later:
-
- \dots 0
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 4
-
- \section1 Translating Mouse Movement to Axis Range Change
-
- in \c scatterGraph we will need to listen to \c onSelectedElementChanged signal. The signal
- is emitted after the selection query has been made in the \c{onPressed} of \c{inputArea}. We
- set the element type into a property we defined (\c{property int selectedAxisLabel: -1}) in our
- main component, since it is of a type we are interested in:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 5
-
- Then, back in the \c onPositionChanged of \c{inputArea}, we check if a mouse button is pressed
- and if we have a current axis label selection. If the conditions are met, we'll call the
- function that does the conversion from mouse movement to axis range update:
-
- \dots 0
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 6
- \dots 0
-
- The conversion is easy in this case, as we have a fixed camera rotation. We can use some
- precalculated values, calculate mouse move distance, and apply the values to the
- selected axis range:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 7
-
- For a more sophisticated conversion from mouse movement to axis range update, see
- \l{Input Handling for Axes}.
-
- \section1 Other Features
-
- The example also demonstrates how to use orthographic projection and how to update properties
- of a custom item on the fly.
-
- Orthographic projection is very simple. You'll just need to change \c orthoProjection property
- of \c{scatterGraph}. In this example we have a button for toggling it on and off:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 8
-
- For custom items, first we'll add one in the \c customItemList of \c{scatterGraph}:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 9
-
- We have implemented a timer to add, remove, and rotate all the items in the graph,
- and we'll use the same timer for rotating the custom item:
-
- \snippet qmlaxisdrag/qml/qmlaxisdrag/main.qml 10
- \dots
-
- \section1 Example Contents
-*/
diff --git a/examples/datavisualization/qmlaxisdrag/main.cpp b/examples/datavisualization/qmlaxisdrag/main.cpp
deleted file mode 100644
index e910b8a2..00000000
--- a/examples/datavisualization/qmlaxisdrag/main.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#include <QtGui/QGuiApplication>
-#include <QtCore/QDir>
-#include <QtQuick/QQuickView>
-#include <QtQml/QQmlEngine>
-
-int main(int argc, char *argv[])
-{
- qputenv("QSG_RHI_BACKEND", "opengl");
- QGuiApplication app(argc, argv);
-
- QQuickView viewer;
-
- // The following are needed to make examples run without having to install the module
- // in desktop environments.
-#ifdef Q_OS_WIN
- QString extraImportPath(QStringLiteral("%1/../../../../%2"));
-#else
- QString extraImportPath(QStringLiteral("%1/../../../%2"));
-#endif
- viewer.engine()->addImportPath(extraImportPath.arg(QGuiApplication::applicationDirPath(),
- QString::fromLatin1("qml")));
- QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);
-
- viewer.setTitle(QStringLiteral("QML Draggable Axes"));
-
- viewer.setSource(QUrl("qrc:/qml/qmlaxisdrag/main.qml"));
- viewer.setResizeMode(QQuickView::SizeRootObjectToView);
- viewer.show();
-
- return app.exec();
-}
diff --git a/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cubetexture.png b/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cubetexture.png
deleted file mode 100644
index 3cea6863..00000000
--- a/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cubetexture.png
+++ /dev/null
Binary files differ
diff --git a/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/main.qml b/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/main.qml
deleted file mode 100644
index dc5f0802..00000000
--- a/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/main.qml
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-import QtQuick
-import QtDataVisualization
-import QtQuick.Controls
-
-Item {
- id: mainView
- width: 800
- height: 600
- visible: true
-
- property int selectedAxisLabel: -1
- property real dragSpeedModifier: 100.0
- property int currentMouseX: -1
- property int currentMouseY: -1
- property int previousMouseX: -1
- property int previousMouseY: -1
-
- property bool portraitMode: width < height
-
- ListModel {
- id: graphModel
- ListElement{ xPos: 0.0; yPos: 0.0; zPos: 0.0; rotation: "@0,0,0,0" }
- ListElement{ xPos: 1.0; yPos: 1.0; zPos: 1.0; rotation: "@45,1,1,1" }
- }
-
- Timer {
- id: dataTimer
- interval: 1
- running: true
- repeat: true
- property bool isIncreasing: true
- property real rotationAngle: 0
-
- function generateQuaternion() {
- return "@" + Math.random() * 360 + "," + Math.random() + ","
- + Math.random() + "," + Math.random()
- }
-
- function appendRow() {
- graphModel.append({"xPos": Math.random(),
- "yPos": Math.random(),
- "zPos": Math.random(),
- "rotation": generateQuaternion()
- });
- }
-
- //! [10]
- onTriggered: {
- rotationAngle = rotationAngle + 1
- qtCube.setRotationAxisAndAngle(Qt.vector3d(1, 0, 1), rotationAngle)
- //! [10]
- scatterSeries.setMeshAxisAndAngle(Qt.vector3d(1, 1, 1), rotationAngle)
- if (isIncreasing) {
- for (var i = 0; i < 10; i++)
- appendRow()
- if (graphModel.count > 2002) {
- scatterGraph.theme = isabelleTheme
- isIncreasing = false
- }
- } else {
- graphModel.remove(2, 10);
- if (graphModel.count === 2) {
- scatterGraph.theme = dynamicColorTheme
- isIncreasing = true
- }
- }
- }
- }
-
- ThemeColor {
- id: dynamicColor
- ColorAnimation on color {
- from: "red"
- to: "yellow"
- duration: 2000
- loops: Animation.Infinite
- }
- }
-
- Theme3D {
- id: dynamicColorTheme
- type: Theme3D.ThemeEbony
- baseColors: [dynamicColor]
- font.pointSize: 50
- labelBorderEnabled: true
- labelBackgroundColor: "gold"
- labelTextColor: "black"
- }
-
- Theme3D {
- id: isabelleTheme
- type: Theme3D.ThemeIsabelle
- font.pointSize: 50
- labelBorderEnabled: true
- labelBackgroundColor: "gold"
- labelTextColor: "black"
- }
-
- Item {
- id: dataView
- anchors.bottom: parent.bottom
- width: parent.width
- height: parent.height
-
- //! [0]
- Scatter3D {
- id: scatterGraph
- inputHandler: null
- //! [0]
- width: dataView.width
- height: dataView.height
- theme: dynamicColorTheme
- shadowQuality: AbstractGraph3D.ShadowQualityLow
- scene.activeCamera.yRotation: 45.0
- scene.activeCamera.xRotation: 45.0
- scene.activeCamera.zoomLevel: 75.0
-
- Scatter3DSeries {
- id: scatterSeries
- itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
- mesh: Abstract3DSeries.MeshCube
-
- ItemModelScatterDataProxy {
- itemModel: graphModel
- xPosRole: "xPos"
- yPosRole: "yPos"
- zPosRole: "zPos"
- rotationRole: "rotation"
- }
- }
- //! [9]
- customItemList: [
- Custom3DItem {
- id: qtCube
- meshFile: ":/qml/qmlaxisdrag/cube.obj"
- textureFile: ":/qml/qmlaxisdrag/cubetexture.png"
- position: Qt.vector3d(0.65, 0.35, 0.65)
- scaling: Qt.vector3d(0.3, 0.3, 0.3)
- }
- ]
- //! [9]
- //! [5]
- onSelectedElementChanged: {
- if (selectedElement >= AbstractGraph3D.ElementAxisXLabel
- && selectedElement <= AbstractGraph3D.ElementAxisZLabel)
- selectedAxisLabel = selectedElement
- else
- selectedAxisLabel = -1
- }
- //! [5]
- }
-
- //! [1]
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- acceptedButtons: Qt.LeftButton
- //! [1]
-
- //! [3]
- onPositionChanged: (mouse)=> {
- currentMouseX = mouse.x;
- currentMouseY = mouse.y;
- //! [3]
- //! [6]
- if (pressed && selectedAxisLabel != -1)
- dragAxis();
- //! [6]
- //! [4]
- previousMouseX = currentMouseX;
- previousMouseY = currentMouseY;
- }
- //! [4]
-
- //! [2]
- onPressed: (mouse)=> {
- scatterGraph.scene.selectionQueryPosition = Qt.point(mouse.x, mouse.y);
- }
- //! [2]
-
- onReleased: {
- // We need to clear mouse positions and selected axis, because touch devices cannot
- // track position all the time
- selectedAxisLabel = -1
- currentMouseX = -1
- currentMouseY = -1
- previousMouseX = -1
- previousMouseY = -1
- }
- }
- }
-
- //! [7]
- function dragAxis() {
- // Do nothing if previous mouse position is uninitialized
- if (previousMouseX === -1)
- return
-
- // Directional drag multipliers based on rotation. Camera is locked to 45 degrees, so we
- // can use one precalculated value instead of calculating xx, xy, zx and zy individually
- var cameraMultiplier = 0.70710678
-
- // Calculate the mouse move amount
- var moveX = currentMouseX - previousMouseX
- var moveY = currentMouseY - previousMouseY
-
- // Adjust axes
- switch (selectedAxisLabel) {
- case AbstractGraph3D.ElementAxisXLabel:
- var distance = ((moveX - moveY) * cameraMultiplier) / dragSpeedModifier
- // Check if we need to change min or max first to avoid invalid ranges
- if (distance > 0) {
- scatterGraph.axisX.min -= distance
- scatterGraph.axisX.max -= distance
- } else {
- scatterGraph.axisX.max -= distance
- scatterGraph.axisX.min -= distance
- }
- break
- case AbstractGraph3D.ElementAxisYLabel:
- distance = moveY / dragSpeedModifier
- // Check if we need to change min or max first to avoid invalid ranges
- if (distance > 0) {
- scatterGraph.axisY.max += distance
- scatterGraph.axisY.min += distance
- } else {
- scatterGraph.axisY.min += distance
- scatterGraph.axisY.max += distance
- }
- break
- case AbstractGraph3D.ElementAxisZLabel:
- distance = ((moveX + moveY) * cameraMultiplier) / dragSpeedModifier
- // Check if we need to change min or max first to avoid invalid ranges
- if (distance > 0) {
- scatterGraph.axisZ.max += distance
- scatterGraph.axisZ.min += distance
- } else {
- scatterGraph.axisZ.min += distance
- scatterGraph.axisZ.max += distance
- }
- break
- }
- }
- //! [7]
-
- Button {
- id: rangeToggle
- // We're adding 3 buttons and want to divide them equally, if not in portrait mode
- width: mainView.portraitMode ? parent.width : parent.width / 3
- text: "Use Preset Range"
- anchors.left: parent.left
- anchors.top: parent.top
- property bool autoRange: true
- onClicked: {
- if (autoRange) {
- text = "Use Automatic Range"
- scatterGraph.axisX.min = 0.3
- scatterGraph.axisX.max = 0.7
- scatterGraph.axisY.min = 0.3
- scatterGraph.axisY.max = 0.7
- scatterGraph.axisZ.min = 0.3
- scatterGraph.axisZ.max = 0.7
- autoRange = false
- dragSpeedModifier = 200.0
- } else {
- text = "Use Preset Range"
- autoRange = true
- dragSpeedModifier = 100.0
- }
- scatterGraph.axisX.autoAdjustRange = autoRange
- scatterGraph.axisY.autoAdjustRange = autoRange
- scatterGraph.axisZ.autoAdjustRange = autoRange
- }
- }
-
- //! [8]
- Button {
- id: orthoToggle
- width: mainView.portraitMode ? parent.width : parent.width / 3
- text: "Display Orthographic"
- anchors.left: mainView.portraitMode ? parent.left : rangeToggle.right
- anchors.top: mainView.portraitMode ? rangeToggle.bottom : parent.top
- onClicked: {
- if (scatterGraph.orthoProjection) {
- text = "Display Orthographic";
- scatterGraph.orthoProjection = false
- // Orthographic projection disables shadows, so we need to switch them back on
- scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityLow
- } else {
- text = "Display Perspective";
- scatterGraph.orthoProjection = true
- }
- }
- }
- //! [8]
-
- Button {
- id: exitButton
- width: mainView.portraitMode ? parent.width : parent.width / 3
- text: "Quit"
- anchors.left: mainView.portraitMode ? parent.left : orthoToggle.right
- anchors.top: mainView.portraitMode ? orthoToggle.bottom : parent.top
- onClicked: Qt.quit();
- }
-}
diff --git a/examples/datavisualization/qmlaxisdrag/qmlaxisdrag.pro b/examples/datavisualization/qmlaxisdrag/qmlaxisdrag.pro
deleted file mode 100644
index d45525ad..00000000
--- a/examples/datavisualization/qmlaxisdrag/qmlaxisdrag.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-!include( ../examples.pri ) {
- error( "Couldn't find the examples.pri file!" )
-}
-
-SOURCES += main.cpp
-
-RESOURCES += qmlaxisdrag.qrc
-
-OTHER_FILES += doc/src/* \
- doc/images/* \
- qml/qmlaxisdrag/*
diff --git a/examples/datavisualization/qmlaxisdrag/qmlaxisdrag.qrc b/examples/datavisualization/qmlaxisdrag/qmlaxisdrag.qrc
deleted file mode 100644
index 9e6b90c8..00000000
--- a/examples/datavisualization/qmlaxisdrag/qmlaxisdrag.qrc
+++ /dev/null
@@ -1,11 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>qml/qmlaxisdrag/main.qml</file>
- </qresource>
- <qresource prefix="/mesh">
- <file alias="cube">qml/qmlaxisdrag/cube.obj</file>
- </qresource>
- <qresource prefix="/texture">
- <file alias="texture">qml/qmlaxisdrag/cubetexture.png</file>
- </qresource>
-</RCC>
diff --git a/examples/datavisualization/qmlaxisformatter/doc/images/qmlaxisformatter-example.png b/examples/datavisualization/qmlaxisformatter/doc/images/qmlaxisformatter-example.png
deleted file mode 100644
index fbfbd833..00000000
--- a/examples/datavisualization/qmlaxisformatter/doc/images/qmlaxisformatter-example.png
+++ /dev/null
Binary files differ
diff --git a/examples/datavisualization/qmlaxisformatter/doc/src/qmlaxisformatter.qdoc b/examples/datavisualization/qmlaxisformatter/doc/src/qmlaxisformatter.qdoc
deleted file mode 100644
index 3dd1075f..00000000
--- a/examples/datavisualization/qmlaxisformatter/doc/src/qmlaxisformatter.qdoc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example qmlaxisformatter
- \meta tags {DataVisualization, Scatter3D, Custom Axis Formatter, Scatter Graph}
- \meta category {Graphics}
- \title Axis Formatters
- \ingroup qtdatavisualization_qmlexamples
- \brief Example of a hybrid C++ and QML application demonstrating different axis formatters.
- \since QtDataVisualization 1.1
-
- The Qt Quick axis formatters example shows how to use predefined axis formatters and how to
- create a custom one.
-
- \image qmlaxisformatter-example.png
-
- The interesting thing about this example is axis formatters, so we'll concentrate on
- that and skip explaining the basic functionality - for
- more detailed QML example documentation, see \l{Simple Scatter Graph}.
-
- \include examples-run.qdocinc
-
- \section1 Custom Axis Formatter
-
- Customizing axis formatters requires subclassing the QValue3DAxisFormatter, which cannot be
- done in QML code alone. In this example we want an axis that interprets the float values as
- a timestamp and shows the date in the axis labels. To achieve this, we introduce a new class
- called \c CustomFormatter, which subclasses the QValue3DAxisFormatter:
-
- \snippet qmlaxisformatter/customformatter.h 2
- \dots 0
-
- Since float values of a QScatter3DSeries cannot be directly cast into QDateTime values due to
- difference in data width, we need some sort of mapping between the two. We chose to do the
- mapping by specifying an origin date for the formatter and interpreting the float values
- from the QScatter3DSeries as date offsets to that origin value. The origin date is given as
- a property:
-
- \snippet qmlaxisformatter/customformatter.h 1
-
- The mapping from value to QDateTime is done using \c valueToDateTime() method:
-
- \snippet qmlaxisformatter/customformatter.cpp 0
-
- To function as an axis formatter, our \c CustomFormatter needs to reimplement some virtual
- methods:
-
- \snippet qmlaxisformatter/customformatter.h 0
-
- The first two are simple, we just create a new instance of \c CustomFormatter and copy the
- necessary data over to it. These two methods are used to create and update a cache of formatter for
- rendering purposes. It is important to remember to call the superclass implementation
- of \c populateCopy():
-
- \snippet qmlaxisformatter/customformatter.cpp 1
-
- Bulk of the work done by \c CustomFormatter is done in the \c recalculate() method, where
- our formatter calculates the grid, subgrid, and label positions, as well as formats the label
- strings.
- In our custom formatter we ignore the segment count of the axis and draw a grid line always at
- midnight. Subsegment count and label positioning is handled normally:
-
- \snippet qmlaxisformatter/customformatter.cpp 2
-
- The axis labels are formatted to show only the date, but for selection label we want little more
- resolution for the timestamp, so we specify another property for our custom formatter to allow
- user to customize it:
-
- \snippet qmlaxisformatter/customformatter.h 3
-
- This selection format property is used in the reimplemented \c stringToValue method, where we
- ignore the submitted format and substitute the custom selection format for it:
-
- \snippet qmlaxisformatter/customformatter.cpp 3
-
- To expose our new custom formatter to the QML, we must declare it and make it a QML module.
- Doing this was introduced in the \l{Surface Oscilloscope} so we will skip it here.
-
- \section1 QML
-
- In the QML codes, we define a different axis for each dimension:
-
- \snippet qmlaxisformatter/qml/qmlaxisformatter/main.qml 3
-
- Z-axis is just a regular ValueAxis3D:
-
- \snippet qmlaxisformatter/qml/qmlaxisformatter/main.qml 0
-
- For the Y-axis we define a logarithmic axis. ValueAxis3D can be made to show logarithmic scale
- by specifying LogValueAxis3DFormatter for \c formatter property of the axis:
-
- \snippet qmlaxisformatter/qml/qmlaxisformatter/main.qml 2
-
- And finally, for the X-axis we use our new \c CustomFormatter:
-
- \snippet qmlaxisformatter/qml/qmlaxisformatter/main.qml 1
-
- Rest of the application consists of fairly self-explanatory logic for modifying the axes and
- showing the graph.
-*/
diff --git a/examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/main.qml b/examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/main.qml
deleted file mode 100644
index c77c6e8b..00000000
--- a/examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/main.qml
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-import QtQuick
-import QtQuick.Layouts
-import QtQuick.Controls
-import QtDataVisualization
-import CustomFormatter
-
-Item {
- id: mainView
- width: 1280
- height: 1024
-
- Data {
- id: seriesData
- }
-
- Theme3D {
- id: themeIsabelle
- type: Theme3D.ThemePrimaryColors
- font.family: "Lucida Handwriting"
- font.pointSize: 40
- }
-
- //! [1]
- ValueAxis3D {
- id: dateAxis
- formatter: CustomFormatter {
- originDate: "2014-01-01"
- selectionFormat: "yyyy-MM-dd HH:mm:ss"
- }
- subSegmentCount: 2
- labelFormat: "yyyy-MM-dd"
- min: 0
- max: 14
- }
- //! [1]
-
- //! [2]
- ValueAxis3D {
- id: logAxis
- formatter: LogValueAxis3DFormatter {
- id: logAxisFormatter
- base: 10
- autoSubGrid: true
- showEdgeLabels: true
- }
- labelFormat: "%.2f"
- }
- //! [2]
-
- ValueAxis3D {
- id: linearAxis
- labelFormat: "%.2f"
- min: 0
- max: 500
- }
-
- //! [0]
- ValueAxis3D {
- id: valueAxis
- segmentCount: 5
- subSegmentCount: 2
- labelFormat: "%.2f"
- min: 0
- max: 10
- }
- //! [0]
-
- Item {
- id: dataView
- anchors.bottom: parent.bottom
- width: parent.width
- height: parent.height - buttonLayout.height
-
- Scatter3D {
- id: scatterGraph
- width: dataView.width
- height: dataView.height
- theme: themeIsabelle
- shadowQuality: AbstractGraph3D.ShadowQualitySoftLow
- scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricRight
- //! [3]
- axisZ: valueAxis
- axisY: logAxis
- axisX: dateAxis
- //! [3]
-
- Scatter3DSeries {
- id: scatterSeries
- itemLabelFormat: "@xLabel - (@yLabel, @zLabel)"
- meshSmooth: true
- ItemModelScatterDataProxy {
- itemModel: seriesData.model
- xPosRole: "xPos"
- yPosRole: "yPos"
- zPosRole: "zPos"
- }
- }
- }
- }
-
- RowLayout {
- id: buttonLayout
- Layout.minimumHeight: exitButton.height
- width: parent.width
- anchors.left: parent.left
- spacing: 0
-
- Button {
- id: yAxisBaseChange
- Layout.fillHeight: true
- Layout.fillWidth: true
- state: "enabled"
- onClicked: {
- if (logAxisFormatter.base === 10)
- logAxisFormatter.base = 0
- else if (logAxisFormatter.base === 2)
- logAxisFormatter.base = 10
- else
- logAxisFormatter.base = 2
- }
- states: [
- State {
- name: "enabled"
- PropertyChanges {
- target: yAxisBaseChange
- text: "Y-axis log base: " + logAxisFormatter.base
- enabled: true
- }
- },
- State {
- name: "disabled"
- PropertyChanges {
- target: yAxisBaseChange
- text: "Y-axis linear"
- enabled: false
- }
- }
- ]
- }
-
- Button {
- id: yAxisToggle
- Layout.fillHeight: true
- Layout.fillWidth: true
- text: "Toggle Y-axis"
- onClicked: {
- if (scatterGraph.axisY == linearAxis) {
- scatterGraph.axisY = logAxis
- yAxisBaseChange.state = "enabled"
- } else {
- scatterGraph.axisY = linearAxis
- yAxisBaseChange.state = "disabled"
- }
- }
- }
-
- Button {
- id: exitButton
- Layout.fillHeight: true
- Layout.fillWidth: true
- text: "Quit"
- onClicked: Qt.quit();
- }
- }
-}
diff --git a/examples/datavisualization/qmlaxisformatter/qmlaxisformatter.pro b/examples/datavisualization/qmlaxisformatter/qmlaxisformatter.pro
deleted file mode 100644
index 0f3b2f80..00000000
--- a/examples/datavisualization/qmlaxisformatter/qmlaxisformatter.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-!include( ../examples.pri ) {
- error( "Couldn't find the examples.pri file!" )
-}
-
-QT += datavisualization
-
-# The .cpp file which was generated for your project. Feel free to hack it.
-SOURCES += main.cpp \
- customformatter.cpp
-HEADERS += customformatter.h
-
-RESOURCES += qmlaxisformatter.qrc
-
-OTHER_FILES += doc/src/* \
- doc/images/* \
- qml/qmlaxisformatter/*
diff --git a/examples/datavisualization/qmlaxisformatter/qmlaxisformatter.qrc b/examples/datavisualization/qmlaxisformatter/qmlaxisformatter.qrc
deleted file mode 100644
index 27c30362..00000000
--- a/examples/datavisualization/qmlaxisformatter/qmlaxisformatter.qrc
+++ /dev/null
@@ -1,6 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>qml/qmlaxisformatter/main.qml</file>
- <file>qml/qmlaxisformatter/Data.qml</file>
- </qresource>
-</RCC>
diff --git a/examples/datavisualization/qmlaxisformatter/CMakeLists.txt b/examples/datavisualization/qmlaxishandling/CMakeLists.txt
index 6374edf7..062e0cb7 100644
--- a/examples/datavisualization/qmlaxisformatter/CMakeLists.txt
+++ b/examples/datavisualization/qmlaxishandling/CMakeLists.txt
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
-project(qmlaxisformatter LANGUAGES CXX)
+project(qmlaxishandling LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -22,14 +22,14 @@ find_package(Qt6 COMPONENTS Qml)
find_package(Qt6 COMPONENTS Quick)
find_package(Qt6 COMPONENTS DataVisualization)
-qt_add_executable(qmlaxisformatter
+qt_add_executable(qmlaxishandling
main.cpp
)
-set_target_properties(qmlaxisformatter PROPERTIES
+set_target_properties(qmlaxishandling PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
-target_link_libraries(qmlaxisformatter PUBLIC
+target_link_libraries(qmlaxishandling PUBLIC
Qt::Core
Qt::Gui
Qt::Qml
@@ -37,18 +37,23 @@ target_link_libraries(qmlaxisformatter PUBLIC
Qt::DataVisualization
)
-qt6_add_qml_module(qmlaxisformatter
- URI CustomFormatter
+qt6_add_qml_module(qmlaxishandling
+ URI AxisHandling
VERSION 1.0
NO_RESOURCE_TARGET_PATH
SOURCES
customformatter.cpp customformatter.h
QML_FILES
- qml/qmlaxisformatter/Data.qml
- qml/qmlaxisformatter/main.qml
+ qml/qmlaxishandling/main.qml
+ qml/qmlaxishandling/Data.qml
+ qml/qmlaxishandling/AxisDragging.qml
+ qml/qmlaxishandling/AxisFormatting.qml
+ RESOURCES
+ qml/qmlaxishandling/cube.obj
+ qml/qmlaxishandling/cubetexture.png
)
-install(TARGETS qmlaxisformatter
+install(TARGETS qmlaxishandling
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/datavisualization/qmlaxisformatter/customformatter.cpp b/examples/datavisualization/qmlaxishandling/customformatter.cpp
index d628c160..79425477 100644
--- a/examples/datavisualization/qmlaxisformatter/customformatter.cpp
+++ b/examples/datavisualization/qmlaxishandling/customformatter.cpp
@@ -1,10 +1,9 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "customformatter.h"
-#include <QtDataVisualization/QValue3DAxis>
-#include <QtQml/QQmlExtensionPlugin>
-#include <QtCore/QDebug>
+#include <QtDataVisualization/qvalue3daxis.h>
+#include <QtQml/qqmlextensionplugin.h>
Q_DECLARE_METATYPE(QValue3DAxisFormatter *)
diff --git a/examples/datavisualization/qmlaxisformatter/customformatter.h b/examples/datavisualization/qmlaxishandling/customformatter.h
index 995ca3ee..8708d466 100644
--- a/examples/datavisualization/qmlaxisformatter/customformatter.h
+++ b/examples/datavisualization/qmlaxishandling/customformatter.h
@@ -1,11 +1,11 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef CUSTOMFORMATTER_H
#define CUSTOMFORMATTER_H
-#include <QtDataVisualization/QValue3DAxisFormatter>
-#include <QtCore/QDateTime>
+#include <QtDataVisualization/qvalue3daxisformatter.h>
+#include <QtCore/qdatetime.h>
#include <QtQml/qqmlregistration.h>
//! [2]
diff --git a/examples/datavisualization/qmlaxishandling/doc/images/qmlaxishandling-example.png b/examples/datavisualization/qmlaxishandling/doc/images/qmlaxishandling-example.png
new file mode 100644
index 00000000..21e9551b
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/doc/images/qmlaxishandling-example.png
Binary files differ
diff --git a/examples/datavisualization/qmlaxishandling/doc/src/qmlaxishandling.qdoc b/examples/datavisualization/qmlaxishandling/doc/src/qmlaxishandling.qdoc
new file mode 100644
index 00000000..ae2470cf
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/doc/src/qmlaxishandling.qdoc
@@ -0,0 +1,189 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example qmlaxishandling
+ \meta tags {DataVisualization, Scatter3D, Custom Input Handler, Dynamic Data, Custom Axis Formatter, Scatter Graph}
+ \meta category {Graphics}
+ \title Axis Handling
+ \ingroup qtdatavisualization_qmlexamples
+ \brief Implementing axis dragging with a custom input handler in QML, and creating a custom axis formatter.
+ \since QtDataVisualization 6.5
+
+ \e {Axis Handling} demonstrates two different custom features with axes. The features have their
+ own tabs in the application.
+
+ The following sections concentrate on those features only and skip explaining the basic
+ functionality - for more detailed QML example documentation, see \l{Simple Scatter Graph}.
+
+ \image qmlaxishandling-example.png
+
+ \include examples-run.qdocinc
+
+ \section1 Axis Dragging
+
+ In the \uicontrol {Axis Dragging} tab, implement a custom input handler in QML that enables you
+ to drag axis labels to change axis ranges. Further, use orthographic projection and dynamically
+ update the properties of a custom item.
+
+ \section2 Overriding Default Input Handling
+
+ To deactivate the default input handling mechanism, set the active input handler of Scatter3D
+ graph to \c{null}:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 0
+ \dots
+
+ Then, add a MouseArea and set it to fill the parent, which is the same \c Item our
+ \c scatterGraph is contained in. Also, set it to accept only left mouse button presses,
+ as in this example the other buttons are not needed:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 1
+ \dots
+
+ Then, listen to mouse presses, and when caught, send a selection query to the graph:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 2
+
+ The \c{onPositionChanged} signal handler catches the current mouse position that will be
+ needed for move distance calculation:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 3
+ \dots
+
+ At the end of \c{onPositionChanged}, save the previous mouse position for move distance
+ calculation that will be introduced later:
+
+ \dots 0
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 4
+
+ \section2 Translating Mouse Movement to Axis Range Change
+
+ In \c {scatterGraph}, listen to \c {onSelectedElementChanged}. The signal
+ is emitted after the selection query has been made in the \c{onPressed} of the \c{inputArea}.
+ Set the element type into a property you defined (\c{property int selectedAxisLabel: -1}) in the
+ main component, since it is of a type you are interested in:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 5
+
+ Then, back in the \c onPositionChanged of \c{inputArea}, check if a mouse button is pressed
+ and if you have a current axis label selection. If the conditions are met, call the
+ function that does the conversion from mouse movement to axis range update:
+
+ \dots 0
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 6
+ \dots 0
+
+ The conversion is easy in this case, as the camera rotation is fixed. You can use some
+ precalculated values, calculate mouse move distance, and apply the values to the
+ selected axis range:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 7
+
+ For a more sophisticated conversion from mouse movement to axis range update, see
+ \l{Graph Gallery}.
+
+ \section2 Other Features
+
+ The example also demonstrates how to use orthographic projection and how to update properties
+ of a custom item on the fly.
+
+ Orthographic projection is very simple. You'll just need to change the \c orthoProjection
+ property of \c{scatterGraph}. The example has a button for toggling it on and off:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 8
+
+ For custom items, add one to the \c customItemList of \c{scatterGraph}:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 9
+
+ You implement a timer to add, remove, and rotate all the items in the graph, and use the same
+ timer for rotating the custom item:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml 10
+ \dots
+
+ \section1 Axis Formatters
+
+ In the \uicontrol {Axis Formatter} tab, create a custom axis formatter. It also illustrates how
+ to use predefined axis formatters.
+
+ \section2 Custom Axis Formatter
+
+ Customizing axis formatters requires subclassing the QValue3DAxisFormatter, which cannot be
+ done in QML code alone. In this example, the axis interprets the float values as
+ a timestamp and shows the date in the axis labels. To achieve this, introduce a new class
+ called \c CustomFormatter, which subclasses the QValue3DAxisFormatter:
+
+ \snippet qmlaxishandling/customformatter.h 2
+ \dots 0
+
+ Since float values of a QScatter3DSeries cannot be directly cast into QDateTime values due to
+ difference in data width, some sort of mapping between the two is needed. To do the mapping,
+ specify an origin date for the formatter and interpret the float values from the
+ QScatter3DSeries as date offsets to that origin value. The origin date is given as
+ a property:
+
+ \snippet qmlaxishandling/customformatter.h 1
+
+ For the mapping from value to QDateTime, use the \c valueToDateTime() method:
+
+ \snippet qmlaxishandling/customformatter.cpp 0
+
+ To function as an axis formatter, \c CustomFormatter needs to reimplement some virtual
+ methods:
+
+ \snippet qmlaxishandling/customformatter.h 0
+
+ The first two are simple, just create a new instance of \c CustomFormatter and copy the
+ necessary data over to it. Use these two methods to create and update a cache of formatter for
+ rendering purposes. Remember to call the superclass implementation of \c populateCopy():
+
+ \snippet qmlaxishandling/customformatter.cpp 1
+
+ \c CustomFormatter does the bulk of its work in the \c recalculate() method, where
+ our formatter calculates the grid, subgrid, and label positions, as well as formats the label
+ strings.
+ In the custom formatter, ignore the segment count of the axis and draw a grid line always at
+ midnight. Subsegment count and label positioning is handled normally:
+
+ \snippet qmlaxishandling/customformatter.cpp 2
+
+ The axis labels are formatted to show only the date. However, to increase the resolution of the
+ timestamp of the selection label, specify another property for the custom formatter to allow
+ the user to customize it:
+
+ \snippet qmlaxishandling/customformatter.h 3
+
+ This selection format property is used in the reimplemented \c stringToValue method, where
+ the submitted format is ignored and the custom selection format substituted for it:
+
+ \snippet qmlaxishandling/customformatter.cpp 3
+
+ To expose our new custom formatter to the QML, declare it and make it a QML module.
+ For information about how to do this, see \l{Surface Graph Gallery}.
+
+ \section2 QML
+
+ In the QML code, define a different axis for each dimension:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml 3
+
+ The Z-axis is just a regular ValueAxis3D:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml 0
+
+ For the Y-axis, define a logarithmic axis. To make ValueAxis3D show a logarithmic scale,
+ specify LogValueAxis3DFormatter for \c formatter property of the axis:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml 2
+
+ And finally, for the X-axis use the new \c CustomFormatter:
+
+ \snippet qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml 1
+
+ The rest of the application consists of fairly self-explanatory logic for modifying the axes and
+ showing the graph.
+
+ \section1 Example Contents
+*/
diff --git a/examples/datavisualization/qmlaxisformatter/main.cpp b/examples/datavisualization/qmlaxishandling/main.cpp
index 557b77b2..aa128bf4 100644
--- a/examples/datavisualization/qmlaxisformatter/main.cpp
+++ b/examples/datavisualization/qmlaxishandling/main.cpp
@@ -1,15 +1,25 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-#include <QtGui/QGuiApplication>
-#include <QtQuick/QQuickView>
+#include <QtGui/qguiapplication.h>
+#include <QtQuick/qquickview.h>
+#include <QtQml/qqmlengine.h>
#include <QtQml>
+#ifdef QMAKE_BUILD
+#include "customformatter.h"
+Q_DECLARE_METATYPE(CustomFormatter *)
+#endif
+
int main(int argc, char *argv[])
{
qputenv("QSG_RHI_BACKEND", "opengl");
QGuiApplication app(argc, argv);
+#ifdef QMAKE_BUILD
+ qmlRegisterType<CustomFormatter>("AxisHandling", 1, 0, "CustomFormatter");
+#endif
+
QQuickView viewer;
// The following are needed to make examples run without having to install the module
@@ -23,9 +33,9 @@ int main(int argc, char *argv[])
QString::fromLatin1("qml")));
QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);
- viewer.setTitle(QStringLiteral("Axis formatter example"));
+ viewer.setTitle(QStringLiteral("Axis Handling"));
- viewer.setSource(QUrl("qrc:/qml/qmlaxisformatter/main.qml"));
+ viewer.setSource(QUrl("qrc:/qml/qmlaxishandling/main.qml"));
viewer.setResizeMode(QQuickView::SizeRootObjectToView);
viewer.show();
diff --git a/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml
new file mode 100644
index 00000000..eeb4bba5
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisDragging.qml
@@ -0,0 +1,298 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtDataVisualization
+
+Item {
+ id: axisDragView
+
+ property int selectedAxisLabel: -1
+ property real dragSpeedModifier: 100.0
+ property int currentMouseX: -1
+ property int currentMouseY: -1
+ property int previousMouseX: -1
+ property int previousMouseY: -1
+
+ required property bool portraitMode
+
+ ListModel {
+ id: graphModel
+ ListElement{ xPos: 0.0; yPos: 0.0; zPos: 0.0; rotation: "@0,0,0,0" }
+ ListElement{ xPos: 1.0; yPos: 1.0; zPos: 1.0; rotation: "@45,1,1,1" }
+ }
+
+ Timer {
+ id: dataTimer
+ interval: 1
+ running: true
+ repeat: true
+ property bool isIncreasing: true
+ property real rotationAngle: 0
+
+ function generateQuaternion() {
+ return "@" + Math.random() * 360 + "," + Math.random() + ","
+ + Math.random() + "," + Math.random();
+ }
+
+ function appendRow() {
+ graphModel.append({"xPos": Math.random(),
+ "yPos": Math.random(),
+ "zPos": Math.random(),
+ "rotation": generateQuaternion()
+ });
+ }
+
+ //! [10]
+ onTriggered: {
+ rotationAngle = rotationAngle + 1;
+ qtCube.setRotationAxisAndAngle(Qt.vector3d(1, 0, 1), rotationAngle);
+ //! [10]
+ scatterSeries.setMeshAxisAndAngle(Qt.vector3d(1, 1, 1), rotationAngle);
+ if (isIncreasing) {
+ for (var i = 0; i < 10; i++)
+ appendRow();
+ if (graphModel.count > 2002) {
+ scatterGraph.theme = isabelleTheme;
+ isIncreasing = false;
+ }
+ } else {
+ graphModel.remove(2, 10);
+ if (graphModel.count === 2) {
+ scatterGraph.theme = dynamicColorTheme;
+ isIncreasing = true;
+ }
+ }
+ }
+ }
+
+ ThemeColor {
+ id: dynamicColor
+ ColorAnimation on color {
+ from: "red"
+ to: "yellow"
+ duration: 2000
+ loops: Animation.Infinite
+ }
+ }
+
+ Theme3D {
+ id: dynamicColorTheme
+ type: Theme3D.ThemeEbony
+ baseColors: [dynamicColor]
+ font.pointSize: 50
+ labelBorderEnabled: true
+ labelBackgroundColor: "gold"
+ labelTextColor: "black"
+ }
+
+ Theme3D {
+ id: isabelleTheme
+ type: Theme3D.ThemeIsabelle
+ font.pointSize: 50
+ labelBorderEnabled: true
+ labelBackgroundColor: "gold"
+ labelTextColor: "black"
+ }
+
+ //! [0]
+ Scatter3D {
+ id: scatterGraph
+ inputHandler: null
+ //! [0]
+ anchors.fill: parent
+ theme: dynamicColorTheme
+ shadowQuality: AbstractGraph3D.ShadowQualityMedium
+ scene.activeCamera.yRotation: 45.0
+ scene.activeCamera.xRotation: 45.0
+ scene.activeCamera.zoomLevel: 75.0
+
+ Scatter3DSeries {
+ id: scatterSeries
+ itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel"
+ mesh: Abstract3DSeries.MeshCube
+
+ ItemModelScatterDataProxy {
+ itemModel: graphModel
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ rotationRole: "rotation"
+ }
+ }
+ //! [9]
+ customItemList: [
+ Custom3DItem {
+ id: qtCube
+ meshFile: ":/qml/qmlaxishandling/cube.obj"
+ textureFile: ":/qml/qmlaxishandling/cubetexture.png"
+ position: Qt.vector3d(0.65, 0.35, 0.65)
+ scaling: Qt.vector3d(0.3, 0.3, 0.3)
+ }
+ ]
+ //! [9]
+ //! [5]
+ onSelectedElementChanged: {
+ if (selectedElement >= AbstractGraph3D.ElementAxisXLabel
+ && selectedElement <= AbstractGraph3D.ElementAxisZLabel) {
+ selectedAxisLabel = selectedElement;
+ } else {
+ selectedAxisLabel = -1;
+ }
+ }
+ //! [5]
+ }
+
+ //! [1]
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ acceptedButtons: Qt.LeftButton
+ //! [1]
+
+ //! [3]
+ onPositionChanged: (mouse)=> {
+ currentMouseX = mouse.x;
+ currentMouseY = mouse.y;
+ //! [3]
+ //! [6]
+ if (pressed && selectedAxisLabel != -1)
+ axisGradView.dragAxis();
+ //! [6]
+ //! [4]
+ previousMouseX = currentMouseX;
+ previousMouseY = currentMouseY;
+ }
+ //! [4]
+
+ //! [2]
+ onPressed: (mouse)=> {
+ scatterGraph.scene.selectionQueryPosition = Qt.point(mouse.x, mouse.y);
+ }
+ //! [2]
+
+ onReleased: {
+ // We need to clear mouse positions and selected axis, because touch devices cannot
+ // track position all the time
+ selectedAxisLabel = -1;
+ currentMouseX = -1;
+ currentMouseY = -1;
+ previousMouseX = -1;
+ previousMouseY = -1;
+ }
+ }
+
+ //! [7]
+ function dragAxis() {
+ // Do nothing if previous mouse position is uninitialized
+ if (previousMouseX === -1)
+ return;
+
+ // Directional drag multipliers based on rotation. Camera is locked to 45 degrees, so we
+ // can use one precalculated value instead of calculating xx, xy, zx and zy individually
+ var cameraMultiplier = 0.70710678;
+
+ // Calculate the mouse move amount
+ var moveX = currentMouseX - previousMouseX;
+ var moveY = currentMouseY - previousMouseY;
+
+ // Adjust axes
+ switch (selectedAxisLabel) {
+ case AbstractGraph3D.ElementAxisXLabel:
+ var distance = ((moveX - moveY) * cameraMultiplier) / dragSpeedModifier;
+ // Check if we need to change min or max first to avoid invalid ranges
+ if (distance > 0) {
+ scatterGraph.axisX.min -= distance;
+ scatterGraph.axisX.max -= distance;
+ } else {
+ scatterGraph.axisX.max -= distance;
+ scatterGraph.axisX.min -= distance;
+ }
+ break;
+ case AbstractGraph3D.ElementAxisYLabel:
+ distance = moveY / dragSpeedModifier;
+ // Check if we need to change min or max first to avoid invalid ranges
+ if (distance > 0) {
+ scatterGraph.axisY.max += distance;
+ scatterGraph.axisY.min += distance;
+ } else {
+ scatterGraph.axisY.min += distance;
+ scatterGraph.axisY.max += distance;
+ }
+ break;
+ case AbstractGraph3D.ElementAxisZLabel:
+ distance = ((moveX + moveY) * cameraMultiplier) / dragSpeedModifier;
+ // Check if we need to change min or max first to avoid invalid ranges
+ if (distance > 0) {
+ scatterGraph.axisZ.max += distance;
+ scatterGraph.axisZ.min += distance;
+ } else {
+ scatterGraph.axisZ.min += distance;
+ scatterGraph.axisZ.max += distance;
+ }
+ break;
+ }
+ }
+ //! [7]
+
+ Button {
+ id: rangeToggle
+ // We're adding 3 buttons and want to divide them equally, if not in portrait mode
+ width: axisDragView.portraitMode ? parent.width : parent.width / 3
+ text: "Use Preset Range"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ property bool autoRange: true
+ onClicked: {
+ if (autoRange) {
+ text = "Use Automatic Range";
+ scatterGraph.axisX.min = 0.3;
+ scatterGraph.axisX.max = 0.7;
+ scatterGraph.axisY.min = 0.3;
+ scatterGraph.axisY.max = 0.7;
+ scatterGraph.axisZ.min = 0.3;
+ scatterGraph.axisZ.max = 0.7;
+ autoRange = false;
+ dragSpeedModifier = 200.0;
+ } else {
+ text = "Use Preset Range";
+ autoRange = true;
+ dragSpeedModifier = 100.0;
+ }
+ scatterGraph.axisX.autoAdjustRange = autoRange;
+ scatterGraph.axisY.autoAdjustRange = autoRange;
+ scatterGraph.axisZ.autoAdjustRange = autoRange;
+ }
+ }
+
+ //! [8]
+ Button {
+ id: orthoToggle
+ width: axisDragView.portraitMode ? parent.width : parent.width / 3
+ text: "Display Orthographic"
+ anchors.left: axisDragView.portraitMode ? parent.left : rangeToggle.right
+ anchors.top: axisDragView.portraitMode ? rangeToggle.bottom : parent.top
+ onClicked: {
+ if (scatterGraph.orthoProjection) {
+ text = "Display Orthographic";
+ scatterGraph.orthoProjection = false;
+ // Orthographic projection disables shadows, so we need to switch them back on
+ scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityMedium
+ } else {
+ text = "Display Perspective";
+ scatterGraph.orthoProjection = true;
+ }
+ }
+ }
+ //! [8]
+
+ Button {
+ id: exitButton
+ width: axisDragView.portraitMode ? parent.width : parent.width / 3
+ text: "Quit"
+ anchors.left: axisDragView.portraitMode ? parent.left : orthoToggle.right
+ anchors.top: axisDragView.portraitMode ? orthoToggle.bottom : parent.top
+ onClicked: Qt.quit();
+ }
+}
diff --git a/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml
new file mode 100644
index 00000000..bf7624ca
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/AxisFormatting.qml
@@ -0,0 +1,156 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtDataVisualization
+import AxisHandling
+
+Item {
+ id: axisFormattingView
+
+ required property bool portraitMode
+
+ Data {
+ id: seriesData
+ }
+
+ Theme3D {
+ id: themePrimaryColors
+ type: Theme3D.ThemePrimaryColors
+ font.family: "Lucida Handwriting"
+ font.pointSize: 40
+ }
+
+ //! [1]
+ ValueAxis3D {
+ id: dateAxis
+ formatter: CustomFormatter {
+ originDate: "2023-01-01"
+ selectionFormat: "yyyy-MM-dd HH:mm:ss"
+ }
+ subSegmentCount: 2
+ labelFormat: "yyyy-MM-dd"
+ min: 0
+ max: 14
+ }
+ //! [1]
+
+ //! [2]
+ ValueAxis3D {
+ id: logAxis
+ formatter: LogValueAxis3DFormatter {
+ id: logAxisFormatter
+ base: 10
+ autoSubGrid: true
+ showEdgeLabels: true
+ }
+ labelFormat: "%.2f"
+ }
+ //! [2]
+
+ ValueAxis3D {
+ id: linearAxis
+ labelFormat: "%.2f"
+ min: 0
+ max: 500
+ }
+
+ //! [0]
+ ValueAxis3D {
+ id: valueAxis
+ segmentCount: 5
+ subSegmentCount: 2
+ labelFormat: "%.2f"
+ min: 0
+ max: 10
+ }
+ //! [0]
+
+ Scatter3D {
+ id: scatterGraph
+ anchors.top: exitButton.bottom
+ anchors.bottom: parent.bottom
+ width: parent.width
+ theme: themePrimaryColors
+ shadowQuality: AbstractGraph3D.ShadowQualitySoftMedium
+ scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricRight
+ //! [3]
+ axisZ: valueAxis
+ axisY: logAxis
+ axisX: dateAxis
+ //! [3]
+
+ Scatter3DSeries {
+ id: scatterSeries
+ itemLabelFormat: "@xLabel - (@yLabel, @zLabel)"
+ meshSmooth: true
+ ItemModelScatterDataProxy {
+ itemModel: seriesData.model
+ xPosRole: "xPos"
+ yPosRole: "yPos"
+ zPosRole: "zPos"
+ }
+ }
+ }
+
+ Button {
+ id: yAxisBaseChange
+ width: axisFormattingView.portraitMode ? parent.width : parent.width / 3
+ anchors.left: parent.left
+ anchors.top: parent.top
+ state: "enabled"
+ onClicked: {
+ if (logAxisFormatter.base === 10)
+ logAxisFormatter.base = 0;
+ else if (logAxisFormatter.base === 2)
+ logAxisFormatter.base = 10;
+ else
+ logAxisFormatter.base = 2;
+ }
+ states: [
+ State {
+ name: "enabled"
+ PropertyChanges {
+ target: yAxisBaseChange
+ text: "Y-axis log base: " + logAxisFormatter.base
+ enabled: true
+ }
+ },
+ State {
+ name: "disabled"
+ PropertyChanges {
+ target: yAxisBaseChange
+ text: "Y-axis linear"
+ enabled: false
+ }
+ }
+ ]
+ }
+
+ Button {
+ id: yAxisToggle
+ width: axisFormattingView.portraitMode ? parent.width : parent.width / 3
+ anchors.left: axisFormattingView.portraitMode ? parent.left : yAxisBaseChange.right
+ anchors.top: axisFormattingView.portraitMode ? yAxisBaseChange.bottom : parent.top
+ text: "Toggle Y-axis"
+ onClicked: {
+ if (scatterGraph.axisY == linearAxis) {
+ scatterGraph.axisY = logAxis;
+ yAxisBaseChange.state = "enabled";
+ } else {
+ scatterGraph.axisY = linearAxis;
+ yAxisBaseChange.state = "disabled";
+ }
+ }
+ }
+
+ Button {
+ id: exitButton
+ width: axisFormattingView.portraitMode ? parent.width : parent.width / 3
+ anchors.left: axisFormattingView.portraitMode ? parent.left : yAxisToggle.right
+ anchors.top: axisFormattingView.portraitMode ? yAxisToggle.bottom : parent.top
+ text: "Quit"
+ onClicked: Qt.quit();
+ }
+}
diff --git a/examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/Data.qml b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/Data.qml
index 689069e2..5db8e855 100644
--- a/examples/datavisualization/qmlaxisformatter/qml/qmlaxisformatter/Data.qml
+++ b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/Data.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cube.obj b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cube.obj
index 0197618f..0197618f 100644
--- a/examples/datavisualization/qmlaxisdrag/qml/qmlaxisdrag/cube.obj
+++ b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cube.obj
diff --git a/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cubetexture.png b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cubetexture.png
new file mode 100644
index 00000000..6369363f
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/cubetexture.png
Binary files differ
diff --git a/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/main.qml b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/main.qml
new file mode 100644
index 00000000..52312359
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qml/qmlaxishandling/main.qml
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Item {
+ id: mainView
+ width: 1280
+ height: 1024
+ visible: true
+
+ property bool portraitMode: width < height
+
+ TabBar {
+ id: tabBar
+ width: parent.width
+
+ TabButton {
+ text: "Axis Dragging"
+ }
+
+ TabButton {
+ text: "Axis Formatting"
+ }
+ }
+
+ StackLayout {
+ anchors.top: tabBar.bottom
+ anchors.bottom: parent.bottom
+ width: parent.width
+ currentIndex: tabBar.currentIndex
+
+ AxisDragging {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ portraitMode: mainView.portraitMode
+ }
+
+ AxisFormatting {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ portraitMode: mainView.portraitMode
+ }
+ }
+}
diff --git a/examples/datavisualization/qmlaxishandling/qmlaxishandling.pro b/examples/datavisualization/qmlaxishandling/qmlaxishandling.pro
new file mode 100644
index 00000000..36b0deee
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qmlaxishandling.pro
@@ -0,0 +1,16 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+DEFINES += QMAKE_BUILD
+
+SOURCES += main.cpp \
+ customformatter.cpp
+
+HEADERS += customformatter.h
+
+RESOURCES += qmlaxishandling.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/* \
+ qml/qmlaxishandling/*
diff --git a/examples/datavisualization/qmlaxishandling/qmlaxishandling.qrc b/examples/datavisualization/qmlaxishandling/qmlaxishandling.qrc
new file mode 100644
index 00000000..136734f5
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qmlaxishandling.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/qmlaxishandling/AxisDragging.qml</file>
+ <file>qml/qmlaxishandling/AxisFormatting.qml</file>
+ <file>qml/qmlaxishandling/cube.obj</file>
+ <file>qml/qmlaxishandling/cubetexture.png</file>
+ <file>qml/qmlaxishandling/Data.qml</file>
+ <file>qml/qmlaxishandling/main.qml</file>
+ </qresource>
+ <qresource prefix="/mesh"/>
+ <qresource prefix="/texture"/>
+</RCC>
diff --git a/examples/datavisualization/qmlaxishandling/qmldir b/examples/datavisualization/qmlaxishandling/qmldir
new file mode 100644
index 00000000..f6da01e7
--- /dev/null
+++ b/examples/datavisualization/qmlaxishandling/qmldir
@@ -0,0 +1,2 @@
+module AxisHandling
+plugin customformatterplugin