Add graph node classes

Creates Surface3DNode, Bars3DNode and Scatter3DNode QML elements.

The node classes create a graph, reparent the graphs rootNode to itself
and forward the parameters.

Task-number: QTBUG-134041
Change-Id: I7e53ff96e59bb42febeaf5c0c084646b50785d19
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
This commit is contained in:
Sakaria Pouke 2025-02-20 15:16:16 +02:00
parent cbdf1f7f94
commit 55cea0dc89
20 changed files with 2054 additions and 18 deletions

View File

@ -34,6 +34,8 @@ else()
utils/qgraphs3dnamespace.cpp utils/qgraphs3dnamespace.h
qml/qquickgraphsitem.cpp qml/qquickgraphsitem_p.h
qml/qquickgraphsnode.cpp qml/qquickgraphsnode_p.h
qml/qquickgraphstexturedata.cpp qml/qquickgraphstexturedata_p.h
qml/gradientholder_p.h
INCLUDE_DIRECTORIES
@ -57,6 +59,7 @@ else()
engine/barinstancing.cpp engine/barinstancing_p.h
qml/qquickgraphsbars.cpp qml/qquickgraphsbars_p.h
qml/qquickgraphsbarsnode.cpp qml/qquickgraphsbarsnode_p.h
qml/qquickgraphsbarsseries.cpp qml/qquickgraphsbarsseries_p.h
INCLUDE_DIRECTORIES
data
@ -76,6 +79,7 @@ else()
engine/scatterinstancing.cpp engine/scatterinstancing_p.h
qml/qquickgraphsscatter.cpp qml/qquickgraphsscatter_p.h
qml/qquickgraphsscatternode.cpp qml/qquickgraphsscatternode_p.h
qml/qquickgraphsscatterseries.cpp qml/qquickgraphsscatterseries_p.h
qml/qquickgraphssplineseries.cpp qml/qquickgraphssplineseries_p.h
INCLUDE_DIRECTORIES
@ -94,6 +98,7 @@ else()
data/surfaceitemmodelhandler.cpp data/surfaceitemmodelhandler_p.h
qml/qquickgraphssurface.cpp qml/qquickgraphssurface_p.h
qml/qquickgraphssurfacenode.cpp qml/qquickgraphssurfacenode_p.h
qml/qquickgraphssurfaceseries.cpp qml/qquickgraphssurfaceseries_p.h
INCLUDE_DIRECTORIES
data

View File

@ -924,8 +924,8 @@ void QQuickGraphsBars::componentComplete()
m_floorBackgroundScale = new QQuick3DNode();
m_floorBackgroundRotation = new QQuick3DNode();
m_floorBackgroundScale->setParent(rootNode());
m_floorBackgroundScale->setParentItem(rootNode());
m_floorBackgroundScale->setParent(graphNode());
m_floorBackgroundScale->setParentItem(graphNode());
m_floorBackgroundRotation->setParent(m_floorBackgroundScale);
m_floorBackgroundRotation->setParentItem(m_floorBackgroundScale);
@ -1570,7 +1570,7 @@ void QQuickGraphsBars::generateBars(QList<QBar3DSeries *> &barSeriesList)
for (int col = 0; col < newColSize; ++col) {
QBarDataItem &dataItem = const_cast<QBarDataItem &>(
dataRow.at(dataColIndex));
auto scene = QQuick3DViewport::scene();
auto scene = graphNode();
QQuick3DModel *model = createDataItem(scene, barSeries);
model->setVisible(visible);
@ -1589,7 +1589,7 @@ void QQuickGraphsBars::generateBars(QList<QBar3DSeries *> &barSeriesList)
}
}
} else if (optimizationHint() == QtGraphs3D::OptimizationHint::Default) {
auto scene = QQuick3DViewport::scene();
auto scene = graphNode();
BarModel *barInstancing = new BarModel();
barInstancing->texture = texture;
@ -1929,7 +1929,11 @@ void QQuickGraphsBars::updateBarVisuals(QBar3DSeries *series)
if (optimizationHint() == QtGraphs3D::OptimizationHint::Legacy) {
// Release resources that might not have been deleted even though deleteLater had been set
window()->releaseResources();
if (m_customView)
m_customView->window()->releaseResources();
else
window()->releaseResources();
for (int i = 0; i < barList.count(); i++) {
QQuick3DModel *model = barList.at(i)->model;

View File

@ -0,0 +1,386 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qquickgraphsbarsnode_p.h"
QT_BEGIN_NAMESPACE
QQuickGraphsBarsNode::QQuickGraphsBarsNode(QQuick3DNode *parent)
: QQuickGraphsNode(parent)
, m_multiSeriesUniform(false)
, m_barSpacing(QSizeF(1.0f, 1.0f))
, m_barThickness(1.0f)
, m_barSpacingRelative(false)
, m_floorLevel(0.0f)
{}
QQuickGraphsBarsNode::~QQuickGraphsBarsNode() {}
void QQuickGraphsBarsNode::componentComplete()
{
const QString qmlData = QLatin1StringView(R"QML(
import QtQuick;
import QtGraphs;
Bars3D{}
)QML");
QQmlComponent *component = new QQmlComponent(qmlEngine(this), this);
component->setData(qmlData.toUtf8(), QUrl());
m_graph.reset(qobject_cast<QQuickGraphsItem *>(component->create()));
setGraphParent();
QQuickGraphsNode::componentComplete();
//initialize components
if (m_axisX)
graphBars()->setAxisX(static_cast<QCategory3DAxis *>(m_axisX));
if (m_axisY)
graphBars()->setAxisY(static_cast<QValue3DAxis *>(m_axisY));
if (m_axisZ)
graphBars()->setAxisZ(static_cast<QCategory3DAxis *>(m_axisZ));
graphBars()->setSelectionMode(m_selectionMode);
graphBars()->setMultiSeriesUniform(m_multiSeriesUniform);
graphBars()->setBarSpacing(m_barSpacing);
graphBars()->setBarThickness(m_barThickness);
graphBars()->setBarSpacingRelative(m_barSpacingRelative);
graphBars()->setFloorLevel(m_floorLevel);
for (auto series : m_seriesList)
graphBars()->addSeries(static_cast<QBar3DSeries *>(series));
//connect signals
connect(graphBars(),
&QQuickGraphsBars::rowAxisChanged,
this,
&QQuickGraphsBarsNode::rowAxisChanged);
connect(graphBars(),
&QQuickGraphsBars::valueAxisChanged,
this,
&QQuickGraphsBarsNode::valueAxisChanged);
connect(graphBars(),
&QQuickGraphsBars::columnAxisChanged,
this,
&QQuickGraphsBarsNode::columnAxisChanged);
connect(graphBars(),
&QQuickGraphsBars::multiSeriesUniformChanged,
this,
&QQuickGraphsBarsNode::multiSeriesUniformChanged);
connect(graphBars(),
&QQuickGraphsBars::barThicknessChanged,
this,
&QQuickGraphsBarsNode::barThicknessChanged);
connect(graphBars(),
&QQuickGraphsBars::barSpacingChanged,
this,
&QQuickGraphsBarsNode::barSpacingChanged);
connect(graphBars(),
&QQuickGraphsBars::barSpacingRelativeChanged,
this,
&QQuickGraphsBarsNode::barSpacingRelativeChanged);
connect(graphBars(),
&QQuickGraphsBars::barSeriesMarginChanged,
this,
&QQuickGraphsBarsNode::barSeriesMarginChanged);
connect(graphBars(),
&QQuickGraphsBars::primarySeriesChanged,
this,
&QQuickGraphsBarsNode::primarySeriesChanged);
connect(graphBars(),
&QQuickGraphsBars::selectedSeriesChanged,
this,
&QQuickGraphsBarsNode::selectedSeriesChanged);
connect(graphBars(),
&QQuickGraphsBars::floorLevelChanged,
this,
&QQuickGraphsBarsNode::floorLevelChanged);
}
void QQuickGraphsBarsNode::setRowAxis(QCategory3DAxis *axis)
{
if (m_axisZ == axis)
return;
m_axisZ = axis;
if (graphBars())
graphBars()->setRowAxis(axis);
}
QCategory3DAxis *QQuickGraphsBarsNode::rowAxis() const
{
if (graphBars())
return graphBars()->rowAxis();
else
return static_cast<QCategory3DAxis *>(m_axisZ);
}
void QQuickGraphsBarsNode::setValueAxis(QValue3DAxis *axis)
{
if (m_axisY == axis)
return;
m_axisY = axis;
if (graphBars())
graphBars()->setValueAxis(axis);
}
QValue3DAxis *QQuickGraphsBarsNode::valueAxis() const
{
if (graphBars())
return graphBars()->valueAxis();
else
return static_cast<QValue3DAxis *>(m_axisY);
}
void QQuickGraphsBarsNode::setColumnAxis(QCategory3DAxis *axis)
{
if (m_axisX == axis)
return;
m_axisX = axis;
if (graphBars())
graphBars()->setColumnAxis(axis);
}
QCategory3DAxis *QQuickGraphsBarsNode::columnAxis() const
{
if (graphBars())
return graphBars()->columnAxis();
else
return static_cast<QCategory3DAxis *>(m_axisX);
}
void QQuickGraphsBarsNode::setMultiSeriesUniform(bool uniform)
{
if (m_multiSeriesUniform == uniform)
return;
m_multiSeriesUniform = uniform;
if (graphBars())
graphBars()->setMultiSeriesUniform(uniform);
}
bool QQuickGraphsBarsNode::isMultiSeriesUniform() const
{
if (graphBars())
return graphBars()->isMultiSeriesUniform();
else
return m_multiSeriesUniform;
}
void QQuickGraphsBarsNode::setBarThickness(float thickness)
{
if (m_barThickness == thickness)
return;
m_barThickness = thickness;
if (graphBars())
graphBars()->setBarThickness(thickness);
}
float QQuickGraphsBarsNode::barThickness() const
{
if (graphBars())
return graphBars()->barThickness();
else
return m_barThickness;
}
void QQuickGraphsBarsNode::setBarSpacing(QSizeF spacing)
{
if (m_barSpacing == spacing)
return;
m_barSpacing = spacing;
if (graphBars())
graphBars()->setBarSpacing(spacing);
}
QSizeF QQuickGraphsBarsNode::barSpacing() const
{
if (graphBars())
return graphBars()->barSpacing();
else
return m_barSpacing;
}
void QQuickGraphsBarsNode::setBarSpacingRelative(bool relative)
{
if (m_barSpacingRelative == relative)
return;
m_barSpacingRelative = relative;
if (graphBars())
graphBars()->setBarSpacingRelative(relative);
}
bool QQuickGraphsBarsNode::isBarSpacingRelative() const
{
if (graphBars())
return graphBars()->isBarSpacingRelative();
else
return m_barSpacingRelative;
}
void QQuickGraphsBarsNode::setBarSeriesMargin(QSizeF margin)
{
if (m_barSeriesMargin == margin)
return;
m_barSeriesMargin = margin;
if (graphBars())
graphBars()->setBarSeriesMargin(margin);
}
QSizeF QQuickGraphsBarsNode::barSeriesMargin() const
{
if (graphBars())
return graphBars()->barSeriesMargin();
else
return m_barSeriesMargin;
}
QBar3DSeries *QQuickGraphsBarsNode::selectedSeries() const
{
if (graphBars())
return graphBars()->selectedSeries();
else
return nullptr;
}
void QQuickGraphsBarsNode::setPrimarySeries(QBar3DSeries *series)
{
if (m_primarySeries == series)
return;
m_primarySeries = series;
if (graphBars())
graphBars()->setPrimarySeries(series);
}
QBar3DSeries *QQuickGraphsBarsNode::primarySeries() const
{
if (graphBars())
return graphBars()->primarySeries();
else
return m_primarySeries;
}
void QQuickGraphsBarsNode::setFloorLevel(float floorLevel)
{
if (m_floorLevel == floorLevel)
return;
m_floorLevel = floorLevel;
if (graphBars())
graphBars()->setFloorLevel(floorLevel);
}
float QQuickGraphsBarsNode::floorLevel() const
{
if (graphBars())
return graphBars()->floorLevel();
else
return m_floorLevel;
}
QList<QBar3DSeries *> QQuickGraphsBarsNode::barSeriesList()
{
if (graphBars()) {
return graphBars()->barSeriesList();
} else {
QList<QBar3DSeries *> barSeriesList;
for (QAbstract3DSeries *abstractSeries : m_seriesList) {
QBar3DSeries *barSeries = qobject_cast<QBar3DSeries *>(abstractSeries);
if (barSeries)
barSeriesList.append(barSeries);
}
return barSeriesList;
}
}
QQmlListProperty<QBar3DSeries> QQuickGraphsBarsNode::seriesList()
{
if (graphBars()) {
return graphBars()->seriesList();
} else {
return QQmlListProperty<QBar3DSeries>(this,
this,
&QQuickGraphsBarsNode::appendSeriesFunc,
&QQuickGraphsBarsNode::countSeriesFunc,
&QQuickGraphsBarsNode::atSeriesFunc,
&QQuickGraphsBarsNode::clearSeriesFunc);
}
}
void QQuickGraphsBarsNode::appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list,
QBar3DSeries *series)
{
reinterpret_cast<QQuickGraphsBarsNode *>(list->data)->addSeries(series);
}
qsizetype QQuickGraphsBarsNode::countSeriesFunc(QQmlListProperty<QBar3DSeries> *list)
{
return reinterpret_cast<QQuickGraphsBarsNode *>(list->data)->barSeriesList().size();
}
QBar3DSeries *QQuickGraphsBarsNode::atSeriesFunc(QQmlListProperty<QBar3DSeries> *list,
qsizetype index)
{
return reinterpret_cast<QQuickGraphsBarsNode *>(list->data)->barSeriesList().at(index);
}
void QQuickGraphsBarsNode::clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list)
{
QQuickGraphsBarsNode *declBarsNode = reinterpret_cast<QQuickGraphsBarsNode *>(list->data);
QList<QBar3DSeries *> realList = declBarsNode->barSeriesList();
qsizetype count = realList.size();
for (qsizetype i = 0; i < count; i++)
declBarsNode->removeSeries(realList.at(i));
}
void QQuickGraphsBarsNode::addSeries(QBar3DSeries *series)
{
Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesType::Bar);
if (graphBars())
graphBars()->addSeries(series);
QQuickGraphsNode::addSeriesInternal(series);
}
void QQuickGraphsBarsNode::removeSeries(QBar3DSeries *series)
{
if (graphBars())
graphBars()->removeSeries(series);
QQuickGraphsNode::removeSeriesInternal(series);
}
void QQuickGraphsBarsNode::insertSeries(qsizetype index, QBar3DSeries *series)
{
if (graphBars())
graphBars()->insertSeries(index, series);
QQuickGraphsNode::insertSeries(index, series);
}
void QQuickGraphsBarsNode::clearSelection()
{
if (graphBars())
graphBars()->clearSelection();
}
/*!
* \internal
*/
QQuickGraphsBars *QQuickGraphsBarsNode::graphBars()
{
return static_cast<QQuickGraphsBars *>(m_graph.get());
}
/*!
* \internal
*/
const QQuickGraphsBars *QQuickGraphsBarsNode::graphBars() const
{
return static_cast<QQuickGraphsBars *>(m_graph.get());
}
QT_END_NAMESPACE

View File

@ -0,0 +1,130 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//
// W A R N I N G
// -------------
//
// This file is not part of the QtGraphs API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QQUICKGRAPHSBARSNODE_P_H
#define QQUICKGRAPHSBARSNODE_P_H
#include "qbar3dseries.h"
#include "qquickgraphsbars_p.h"
#include "qquickgraphsnode_p.h"
#include <private/qgraphsglobal_p.h>
QT_BEGIN_NAMESPACE
class QQuickGraphsBarsNode;
class Q_GRAPHS_EXPORT QQuickGraphsBarsNode : public QQuickGraphsNode
{
Q_OBJECT
Q_PROPERTY(QCategory3DAxis *rowAxis READ rowAxis WRITE setRowAxis NOTIFY rowAxisChanged)
Q_PROPERTY(QValue3DAxis *valueAxis READ valueAxis WRITE setValueAxis NOTIFY valueAxisChanged)
Q_PROPERTY(
QCategory3DAxis *columnAxis READ columnAxis WRITE setColumnAxis NOTIFY columnAxisChanged)
Q_PROPERTY(bool multiSeriesUniform READ isMultiSeriesUniform WRITE setMultiSeriesUniform NOTIFY
multiSeriesUniformChanged)
Q_PROPERTY(float barThickness READ barThickness WRITE setBarThickness NOTIFY barThicknessChanged)
Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing NOTIFY barSpacingChanged)
Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative NOTIFY
barSpacingRelativeChanged)
Q_PROPERTY(QSizeF barSeriesMargin READ barSeriesMargin WRITE setBarSeriesMargin NOTIFY
barSeriesMarginChanged)
Q_PROPERTY(QQmlListProperty<QBar3DSeries> seriesList READ seriesList CONSTANT)
Q_PROPERTY(QBar3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged)
Q_PROPERTY(QBar3DSeries *primarySeries READ primarySeries WRITE setPrimarySeries NOTIFY
primarySeriesChanged)
Q_PROPERTY(float floorLevel READ floorLevel WRITE setFloorLevel NOTIFY floorLevelChanged)
Q_CLASSINFO("DefaultProperty", "seriesList")
QML_ADDED_IN_VERSION(6, 10)
QML_NAMED_ELEMENT(Bars3DNode)
public:
explicit QQuickGraphsBarsNode(QQuick3DNode *parent = nullptr);
~QQuickGraphsBarsNode() override;
void setRowAxis(QCategory3DAxis *axis);
QCategory3DAxis *rowAxis() const;
void setValueAxis(QValue3DAxis *axis);
QValue3DAxis *valueAxis() const;
void setColumnAxis(QCategory3DAxis *axis);
QCategory3DAxis *columnAxis() const;
void setMultiSeriesUniform(bool uniform);
bool isMultiSeriesUniform() const;
void setBarThickness(float thickness);
float barThickness() const;
void setBarSpacing(QSizeF spacing);
QSizeF barSpacing() const;
void setBarSpacingRelative(bool relative);
bool isBarSpacingRelative() const;
void setBarSeriesMargin(QSizeF margin);
QSizeF barSeriesMargin() const;
QBar3DSeries *selectedSeries() const;
void setPrimarySeries(QBar3DSeries *series);
QBar3DSeries *primarySeries() const;
void setFloorLevel(float floorLevel);
float floorLevel() const;
QList<QBar3DSeries *> barSeriesList();
QQmlListProperty<QBar3DSeries> seriesList();
static void appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series);
static qsizetype countSeriesFunc(QQmlListProperty<QBar3DSeries> *list);
static QBar3DSeries *atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, qsizetype index);
static void clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list);
Q_INVOKABLE void addSeries(QBar3DSeries *series);
Q_INVOKABLE void removeSeries(QBar3DSeries *series);
Q_INVOKABLE void insertSeries(qsizetype index, QBar3DSeries *series);
Q_INVOKABLE void clearSelection() override;
protected:
void componentComplete() override;
Q_SIGNALS:
void rowAxisChanged(QCategory3DAxis *axis);
void valueAxisChanged(QValue3DAxis *axis);
void columnAxisChanged(QCategory3DAxis *axis);
void multiSeriesUniformChanged(bool uniform);
void barThicknessChanged(float thicknessRatio);
void barSpacingChanged(QSizeF spacing);
void barSpacingRelativeChanged(bool relative);
void barSeriesMarginChanged(QSizeF margin);
void primarySeriesChanged(QBar3DSeries *series);
void selectedSeriesChanged(QBar3DSeries *series);
void floorLevelChanged(float level);
private:
QQuickGraphsBars *graphBars();
const QQuickGraphsBars *graphBars() const;
bool m_multiSeriesUniform;
QSizeF m_barSpacing;
float m_barThickness;
bool m_barSpacingRelative;
QSizeF m_barSeriesMargin;
QBar3DSeries *m_primarySeries = nullptr;
QBar3DSeries *m_selectedSeries = nullptr;
float m_floorLevel;
};
QT_END_NAMESPACE
#endif // QQUICKGRAPHSBARSNODE_P_H

View File

@ -1793,8 +1793,8 @@ void QQuickGraphsItem::componentComplete()
m_backgroundRotation = new QQuick3DNode();
m_graphNode = new QQuick3DNode();
m_backgroundScale->setParent(rootNode());
m_backgroundScale->setParentItem(rootNode());
m_backgroundScale->setParent(graphNode());
m_backgroundScale->setParentItem(graphNode());
m_backgroundRotation->setParent(m_backgroundScale);
m_backgroundRotation->setParentItem(m_backgroundScale);
@ -5277,10 +5277,51 @@ void QQuickGraphsItem::setMsaaSamples(int samples)
}
}
void QQuickGraphsItem::setParentNode(QQuick3DNode *node) {
if (node) {
m_parentNode = node;
// find active sceneManager
auto *p = node->parent();
QQuick3DViewport *view = nullptr;
while (p && !view) {
view = qobject_cast<QQuick3DViewport *>(p);
p = p->parent();
}
if (view) {
m_customView = view;
auto sceneManager = QQuick3DObjectPrivate::get(view->scene())->sceneManager;
setParent(view);
if (graphNode()) {
graphNode()->setParent(view->parent());
graphNode()->setParentItem(node);
}
connect(sceneManager.data(),
&QQuick3DSceneManager::windowChanged,
this,
&QQuickGraphsItem::handleWindowChanged);
handleWindowChanged();
}
}
}
void QQuickGraphsItem::handleWindowChanged(/*QQuickWindow *window*/)
{
auto window = QQuick3DObjectPrivate::get(rootNode())->sceneManager->window();
QQuick3DSceneManager *manager = nullptr;
if (m_customView)
manager = QQuick3DObjectPrivate::get(m_customView->scene())->sceneManager;
else
manager = QQuick3DObjectPrivate::get(rootNode())->sceneManager;
auto window = manager->window();
checkWindowList(window);
if (!window)
return;
@ -5625,7 +5666,10 @@ qreal QQuickGraphsItem::margin() const
QQuick3DNode *QQuickGraphsItem::rootNode() const
{
return QQuick3DViewport::scene();
if (m_parentNode)
return m_parentNode;
else
return QQuick3DViewport::scene();
}
void QQuickGraphsItem::changeLabelBackgroundColor(QQuick3DRepeater *repeater, QColor color)
@ -6333,8 +6377,10 @@ void QQuickGraphsItem::createSliceView()
m_sliceView->setParent(parent());
m_sliceView->setParentItem(parentItem());
m_sliceView->setVisible(false);
m_sliceView->setWidth(parentItem()->width());
m_sliceView->setHeight(parentItem()->height());
if (!m_parentNode) {
m_sliceView->setHeight(parentItem()->height());
m_sliceView->setWidth(parentItem()->width());
}
m_sliceView->setZ(-1);
m_sliceView->environment()->setBackgroundMode(QQuick3DSceneEnvironment::QQuick3DEnvironmentBackgroundTypes::Color);
m_sliceView->environment()->setClearColor(environment()->clearColor());

View File

@ -638,6 +638,7 @@ Q_SIGNALS:
protected:
bool event(QEvent *event) override;
void setParentNode(QQuick3DNode *node);
virtual void handleWindowChanged(/*QQuickWindow *win*/);
void itemChange(ItemChange change, const ItemChangeData &value) override;
virtual void updateWindowParameters();
@ -807,6 +808,9 @@ protected:
QMutex m_renderMutex;
QQuickGraphsItem *m_qml = nullptr;
QQuick3DViewport *m_customView = nullptr;
QQuick3DNode *m_parentNode = nullptr;
private:
// This is the same as the minimum bound of GridLine model.
const float angularLineOffset = -49.98f;
@ -975,6 +979,7 @@ private:
QGraphsTheme *m_activeTheme = nullptr;
friend class Q3DGraphsWidgetItem;
friend class QQuickGraphsNode;
};
QT_END_NAMESPACE

View File

@ -0,0 +1,428 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qcustom3ditem.h"
#include "qquickgraphsnode_p.h"
#include <qtconfigmacros.h>
QT_BEGIN_NAMESPACE
QQuickGraphsNode::QQuickGraphsNode(QQuick3DNode *parent)
: QQuick3DNode(parent)
, m_selectionMode(QtGraphs3D::SelectionFlag::Item)
, m_aspectRatio(2.0)
, m_optimizationHint(QtGraphs3D::OptimizationHint::Default)
, m_polar(false)
, m_labelMargin(.1f)
, m_radialLabelOffset(1.0f)
, m_horizontalAspectRatio(0.0)
, m_locale(QLocale::c())
, m_margin(-1.0)
, m_gridLineType(QtGraphs3D::GridLineType::Geometry)
{
QGraphsTheme *theme = new QGraphsTheme(this);
setTheme(theme);
}
QQuickGraphsNode::~QQuickGraphsNode() {}
void QQuickGraphsNode::componentComplete()
{
QQuick3DNode::componentComplete();
//initialize properties
m_graph->setTheme(m_theme);
m_graph->setAspectRatio(m_aspectRatio);
m_graph->setOptimizationHint(m_optimizationHint);
m_graph->setPolar(m_polar);
m_graph->setLabelMargin(m_labelMargin);
m_graph->setRadialLabelOffset(m_radialLabelOffset);
m_graph->setHorizontalAspectRatio(m_horizontalAspectRatio);
m_graph->setLocale(m_locale);
m_graph->setMargin(m_margin);
m_graph->setGridLineType(m_gridLineType);
for (auto item : m_customItemList)
m_graph->addCustomItem(item);
//connect signals
connect(m_graph.get(),
&QQuickGraphsItem::selectionModeChanged,
this,
&QQuickGraphsNode::selectionModeChanged);
connect(m_graph.get(), &QQuickGraphsItem::themeChanged, this, &QQuickGraphsNode::themeChanged);
connect(m_graph.get(),
&QQuickGraphsItem::aspectRatioChanged,
this,
&QQuickGraphsNode::aspectRatioChanged);
connect(m_graph.get(),
&QQuickGraphsItem::optimizationHintChanged,
this,
&QQuickGraphsNode::optimizationHintChanged);
connect(m_graph.get(), &QQuickGraphsItem::polarChanged, this, &QQuickGraphsNode::polarChanged);
connect(m_graph.get(),
&QQuickGraphsItem::labelMarginChanged,
this,
&QQuickGraphsNode::labelMarginChanged);
connect(m_graph.get(),
&QQuickGraphsItem::radialLabelOffsetChanged,
this,
&QQuickGraphsNode::radialLabelOffsetChanged);
connect(m_graph.get(),
&QQuickGraphsItem::horizontalAspectRatioChanged,
this,
&QQuickGraphsNode::horizontalAspectRatioChanged);
connect(m_graph.get(), &QQuickGraphsItem::localeChanged, this, &QQuickGraphsNode::localeChanged);
connect(m_graph.get(),
&QQuickGraphsItem::queriedGraphPositionChanged,
this,
&QQuickGraphsNode::queriedGraphPositionChanged);
connect(m_graph.get(), &QQuickGraphsItem::marginChanged, this, &QQuickGraphsNode::marginChanged);
connect(m_graph.get(),
&QQuickGraphsItem::gridLineTypeChanged,
this,
&QQuickGraphsNode::gridLineTypeChanged);
}
void QQuickGraphsNode::setGraphParent()
{
if (m_graph)
m_graph->setParentNode(this);
}
void QQuickGraphsNode::setSelectionMode(QtGraphs3D::SelectionFlags selectionMode)
{
if (m_selectionMode == selectionMode)
return;
m_selectionMode = selectionMode;
if (m_graph)
m_graph->setSelectionMode(m_selectionMode);
}
QtGraphs3D::SelectionFlags QQuickGraphsNode::selectionMode() const
{
if (m_graph)
return m_graph->selectionMode();
else
return m_selectionMode;
}
void QQuickGraphsNode::setTheme(QGraphsTheme *theme)
{
if (m_theme == theme)
return;
m_theme = theme;
if (m_graph)
m_graph->setTheme(m_theme);
}
QGraphsTheme *QQuickGraphsNode::theme() const
{
if (m_graph)
return m_graph->theme();
else
return m_theme;
}
QQmlListProperty<QCustom3DItem> QQuickGraphsNode::customItemList() const
{
if (m_graph)
return m_graph->customItemList();
else
return QQmlListProperty<QCustom3DItem>();
}
QtGraphs3D::ElementType QQuickGraphsNode::selectedElement() const
{
if (m_graph)
return m_graph->selectedElement();
else
return QtGraphs3D::ElementType::None;
}
void QQuickGraphsNode::setAspectRatio(qreal aspectRatio)
{
if (m_aspectRatio == aspectRatio)
return;
m_aspectRatio = aspectRatio;
if (m_graph)
m_graph->setAspectRatio(aspectRatio);
}
qreal QQuickGraphsNode::aspectRatio() const
{
if (m_graph)
return m_graph->aspectRatio();
else
return m_aspectRatio;
}
void QQuickGraphsNode::setOptimizationHint(QtGraphs3D::OptimizationHint optimizationHint)
{
if (m_optimizationHint == optimizationHint)
return;
m_optimizationHint = optimizationHint;
if (m_graph)
m_graph->setOptimizationHint(optimizationHint);
}
QtGraphs3D::OptimizationHint QQuickGraphsNode::optimizationHint() const
{
if (m_graph)
return m_graph->optimizationHint();
else
return m_optimizationHint;
}
void QQuickGraphsNode::setPolar(bool enabled)
{
if (m_polar == enabled)
return;
m_polar = enabled;
if (m_graph)
m_graph->setPolar(enabled);
}
bool QQuickGraphsNode::isPolar() const
{
if (m_graph)
return m_graph->isPolar();
else
return m_polar;
}
void QQuickGraphsNode::setLabelMargin(float labelMargin)
{
if (m_labelMargin == labelMargin)
return;
m_labelMargin = labelMargin;
if (m_graph)
m_graph->setLabelMargin(labelMargin);
}
float QQuickGraphsNode::labelMargin() const
{
if (m_graph)
return m_graph->labelMargin();
else
return m_labelMargin;
}
void QQuickGraphsNode::setRadialLabelOffset(float radialLabelOffset)
{
if (m_radialLabelOffset == radialLabelOffset)
return;
m_radialLabelOffset = radialLabelOffset;
if (m_graph)
m_graph->setRadialLabelOffset(radialLabelOffset);
}
float QQuickGraphsNode::radialLabelOffset() const
{
if (m_graph)
return m_graph->radialLabelOffset();
else
return m_radialLabelOffset;
}
void QQuickGraphsNode::setHorizontalAspectRatio(qreal horizontalAspectRatio)
{
if (m_horizontalAspectRatio == horizontalAspectRatio)
return;
m_horizontalAspectRatio = horizontalAspectRatio;
if (m_graph)
m_graph->setHorizontalAspectRatio(horizontalAspectRatio);
}
qreal QQuickGraphsNode::horizontalAspectRatio() const
{
if (m_graph)
return m_graph->horizontalAspectRatio();
else
return m_horizontalAspectRatio;
}
void QQuickGraphsNode::setLocale(QLocale locale)
{
if (m_locale == locale)
return;
m_locale = locale;
if (m_graph)
m_graph->setLocale(locale);
}
QLocale QQuickGraphsNode::locale() const
{
if (m_graph)
return m_graph->locale();
else
return m_locale;
}
QVector3D QQuickGraphsNode::queriedGraphPosition() const
{
if (m_graph)
return m_graph->queriedGraphPosition();
else
return QVector3D();
}
qreal QQuickGraphsNode::margin() const
{
if (m_graph)
return m_graph->margin();
else
return m_margin;
}
void QQuickGraphsNode::setMargin(qreal margin)
{
if (m_margin == margin)
return;
m_margin = margin;
if (m_graph)
m_graph->setMargin(margin);
}
QtGraphs3D::GridLineType QQuickGraphsNode::gridLineType() const
{
if (m_graph)
return m_graph->gridLineType();
else
return m_gridLineType;
}
void QQuickGraphsNode::setGridLineType(const QtGraphs3D::GridLineType &gridLineType)
{
if (m_gridLineType == gridLineType)
return;
m_gridLineType = gridLineType;
if (m_graph)
m_graph->setGridLineType(gridLineType);
}
bool QQuickGraphsNode::hasSeries(QAbstract3DSeries *series)
{
if (m_graph)
return m_graph->hasSeries(series);
else
return m_seriesList.contains(series);
}
void QQuickGraphsNode::addSeriesInternal(QAbstract3DSeries *series)
{
insertSeries(m_seriesList.size(), series);
}
void QQuickGraphsNode::insertSeries(qsizetype index, QAbstract3DSeries *series)
{
if (series) {
if (m_seriesList.contains(series)) {
qsizetype oldIndex = m_seriesList.indexOf(series);
if (index != oldIndex) {
m_seriesList.removeOne(series);
if (oldIndex < index)
index--;
m_seriesList.insert(index, series);
}
} else {
m_seriesList.insert(index, series);
}
}
}
void QQuickGraphsNode::removeSeriesInternal(QAbstract3DSeries *series)
{
if (series)
m_seriesList.removeAll(series);
}
QList<QAbstract3DSeries *> QQuickGraphsNode::seriesList()
{
return m_seriesList;
}
qsizetype QQuickGraphsNode::addCustomItem(QCustom3DItem *item)
{
if (m_graph)
m_graph->addCustomItem(item);
m_customItemList.append(item);
return m_customItemList.size() - 1;
}
void QQuickGraphsNode::removeCustomItems()
{
if (m_graph)
m_graph->removeCustomItems();
m_customItemList.clear();
}
void QQuickGraphsNode::removeCustomItem(QCustom3DItem *item)
{
if (m_graph)
m_graph->deleteCustomItem(item);
m_customItemList.removeOne(item);
}
void QQuickGraphsNode::removeCustomItemAt(QVector3D position)
{
if (m_graph)
m_graph->removeCustomItemAt(position);
for (QCustom3DItem *item : m_customItemList) {
if (item->position() == position)
m_customItemList.removeOne(item);
}
}
void QQuickGraphsNode::releaseCustomItem(QCustom3DItem *item)
{
if (m_graph)
m_graph->releaseCustomItem(item);
m_customItemList.removeOne(item);
}
int QQuickGraphsNode::selectedLabelIndex() const
{
if (m_graph)
return selectedLabelIndex();
else
return -1;
}
QAbstract3DAxis *QQuickGraphsNode::selectedAxis() const
{
if (m_graph)
return m_graph->selectedAxis();
return nullptr;
}
qsizetype QQuickGraphsNode::selectedCustomItemIndex() const
{
if (m_graph)
return m_graph->selectedCustomItemIndex();
else
return -1;
}
QCustom3DItem *QQuickGraphsNode::selectedCustomItem() const
{
if (m_graph)
return m_graph->selectedCustomItem();
else
return nullptr;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,161 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QQUICKGRAPHSNODE_P_H
#define QQUICKGRAPHSNODE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the QtGraphs API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#include "qgraphs3dnamespace.h"
#include "qquickgraphsitem_p.h"
#include <QtQuick3D/private/qquick3dnode_p.h>
QT_BEGIN_NAMESPACE
class Q_GRAPHS_EXPORT QQuickGraphsNode : public QQuick3DNode
{
Q_OBJECT
Q_PROPERTY(QtGraphs3D::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode
NOTIFY selectionModeChanged)
Q_PROPERTY(QGraphsTheme *theme READ theme WRITE setTheme NOTIFY themeChanged)
Q_PROPERTY(QQmlListProperty<QCustom3DItem> customItemList READ customItemList CONSTANT)
Q_PROPERTY(
QtGraphs3D::ElementType selectedElement READ selectedElement NOTIFY selectedElementChanged)
Q_PROPERTY(qreal aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged)
Q_PROPERTY(QtGraphs3D::OptimizationHint optimizationHint READ optimizationHint WRITE
setOptimizationHint NOTIFY optimizationHintChanged)
Q_PROPERTY(bool polar READ isPolar WRITE setPolar NOTIFY polarChanged)
Q_PROPERTY(float labelMargin READ labelMargin WRITE setLabelMargin NOTIFY labelMarginChanged)
Q_PROPERTY(float radialLabelOffset READ radialLabelOffset WRITE setRadialLabelOffset NOTIFY
radialLabelOffsetChanged)
Q_PROPERTY(qreal horizontalAspectRatio READ horizontalAspectRatio WRITE setHorizontalAspectRatio
NOTIFY horizontalAspectRatioChanged)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged)
Q_PROPERTY(
QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged)
Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged)
Q_PROPERTY(QtGraphs3D::GridLineType gridLineType READ gridLineType WRITE setGridLineType NOTIFY
gridLineTypeChanged FINAL)
QML_NAMED_ELEMENT(GraphsNode)
QML_UNCREATABLE("")
public:
explicit QQuickGraphsNode(QQuick3DNode *parent = nullptr);
~QQuickGraphsNode();
void componentComplete() override;
QtGraphs3D::ElementType selectedElement() const;
virtual void setSelectionMode(QtGraphs3D::SelectionFlags selectionMode);
QtGraphs3D::SelectionFlags selectionMode() const;
void setTheme(QGraphsTheme *theme);
QGraphsTheme *theme() const;
QQmlListProperty<QCustom3DItem> customItemList() const;
void setAspectRatio(qreal aspectRatio);
qreal aspectRatio() const;
void setOptimizationHint(QtGraphs3D::OptimizationHint optimizationHint);
QtGraphs3D::OptimizationHint optimizationHint() const;
void setPolar(bool enabled);
bool isPolar() const;
void setLabelMargin(float labelMargin);
float labelMargin() const;
void setRadialLabelOffset(float radialLabelOffset);
float radialLabelOffset() const;
void setHorizontalAspectRatio(qreal horizontalAspectRatio);
qreal horizontalAspectRatio() const;
void setLocale(QLocale locale);
QLocale locale() const;
QVector3D queriedGraphPosition() const;
void setMargin(qreal margin);
qreal margin() const;
QtGraphs3D::GridLineType gridLineType() const;
void setGridLineType(const QtGraphs3D::GridLineType &gridLineType);
Q_INVOKABLE virtual bool hasSeries(QAbstract3DSeries *series);
Q_INVOKABLE virtual void clearSelection() = 0;
virtual void addSeriesInternal(QAbstract3DSeries *series);
void insertSeries(qsizetype index, QAbstract3DSeries *series);
virtual void removeSeriesInternal(QAbstract3DSeries *series);
QList<QAbstract3DSeries *> seriesList();
Q_INVOKABLE virtual qsizetype addCustomItem(QCustom3DItem *item);
Q_INVOKABLE virtual void removeCustomItems();
Q_INVOKABLE virtual void removeCustomItem(QCustom3DItem *item);
Q_INVOKABLE virtual void removeCustomItemAt(QVector3D position);
Q_INVOKABLE virtual void releaseCustomItem(QCustom3DItem *item);
Q_INVOKABLE virtual int selectedLabelIndex() const;
Q_INVOKABLE virtual QAbstract3DAxis *selectedAxis() const;
Q_INVOKABLE virtual qsizetype selectedCustomItemIndex() const;
Q_INVOKABLE virtual QCustom3DItem *selectedCustomItem() const;
//TODO: get rayPicking to work
// Q_INVOKABLE virtual bool doPicking(QPointF point);
// Q_INVOKABLE virtual bool doRayPicking(const QVector3D &origin, const QVector3D &direction);
protected:
void setGraphParent();
std::unique_ptr<QQuickGraphsItem> m_graph;
QList<QAbstract3DSeries *> m_seriesList;
QtGraphs3D::SelectionFlags m_selectionMode;
QAbstract3DAxis *m_axisX = nullptr;
QAbstract3DAxis *m_axisY = nullptr;
QAbstract3DAxis *m_axisZ = nullptr;
Q_SIGNALS:
void queriedGraphPositionChanged();
void selectedElementChanged();
void optimizationHintChanged();
void selectionModeChanged();
void themeChanged();
void aspectRatioChanged();
void polarChanged();
void labelMarginChanged();
void radialLabelOffsetChanged();
void horizontalAspectRatioChanged();
void localeChanged();
void marginChanged(qreal margin);
void gridLineTypeChanged();
private:
QGraphsTheme *m_theme = nullptr;
qreal m_aspectRatio;
QtGraphs3D::OptimizationHint m_optimizationHint;
bool m_polar;
float m_labelMargin;
float m_radialLabelOffset;
qreal m_horizontalAspectRatio;
QLocale m_locale;
qreal m_margin;
QtGraphs3D::GridLineType m_gridLineType;
QList<QCustom3DItem *> m_customItemList = {};
};
QT_END_NAMESPACE
#endif // QQUICKGRAPHSNODE_P_H

View File

@ -401,7 +401,10 @@ void QQuickGraphsScatter::updateScatterGraphItemVisuals(ScatterModel *graphModel
if (optimizationHint() == QtGraphs3D::OptimizationHint::Legacy) {
// Release resources that might not have been deleted even though deleteLater had been set
window()->releaseResources();
if (m_customView)
m_customView->window()->releaseResources();
else
window()->releaseResources();
if (itemCount != graphModel->dataItems.size())
qWarning("%ls Item count differs from itemList count",
@ -698,7 +701,7 @@ QQuick3DNode *QQuickGraphsScatter::createSeriesRoot()
{
auto model = new QQuick3DNode();
model->setParentItem(QQuick3DViewport::scene());
model->setParentItem(graphNode());
return model;
}
@ -706,7 +709,7 @@ QQuick3DModel *QQuickGraphsScatter::createDataItem(QAbstract3DSeries *series)
{
auto model = new QQuick3DModel();
model->setParent(this);
model->setParentItem(QQuick3DViewport::scene());
model->setParentItem(graphNode());
QString fileName = getMeshFileName(series);
if (fileName.isEmpty())
fileName = series->userDefinedMesh();

View File

@ -0,0 +1,218 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qquickgraphsscatternode_p.h"
QT_BEGIN_NAMESPACE
QQuickGraphsScatterNode::QQuickGraphsScatterNode(QQuick3DNode *parent)
: QQuickGraphsNode(parent)
{}
QQuickGraphsScatterNode::~QQuickGraphsScatterNode() {}
void QQuickGraphsScatterNode::componentComplete()
{
const QString qmlData = QLatin1StringView(R"QML(
import QtQuick;
import QtGraphs;
Scatter3D{}
)QML");
QQmlComponent *component = new QQmlComponent(qmlEngine(this), this);
component->setData(qmlData.toUtf8(), QUrl());
m_graph.reset(qobject_cast<QQuickGraphsItem *>(component->create()));
setGraphParent();
QQuickGraphsNode::componentComplete();
//initialize components
if (m_axisX)
graphScatter()->setAxisX(static_cast<QValue3DAxis *>(m_axisX));
if (m_axisY)
graphScatter()->setAxisY(static_cast<QValue3DAxis *>(m_axisY));
if (m_axisZ)
graphScatter()->setAxisZ(static_cast<QValue3DAxis *>(m_axisZ));
graphScatter()->setSelectionMode(m_selectionMode);
for (auto series : m_seriesList)
graphScatter()->addSeries(static_cast<QScatter3DSeries *>(series));
//connect signals
connect(graphScatter(),
&QQuickGraphsScatter::axisXChanged,
this,
&QQuickGraphsScatterNode::axisXChanged);
connect(graphScatter(),
&QQuickGraphsScatter::axisYChanged,
this,
&QQuickGraphsScatterNode::axisYChanged);
connect(graphScatter(),
&QQuickGraphsScatter::axisZChanged,
this,
&QQuickGraphsScatterNode::axisZChanged);
}
QValue3DAxis *QQuickGraphsScatterNode::axisX() const
{
if (graphScatter())
return graphScatter()->axisX();
else
return static_cast<QValue3DAxis *>(m_axisX);
}
void QQuickGraphsScatterNode::setAxisX(QValue3DAxis *axis)
{
if (m_axisX == axis)
return;
m_axisX = axis;
if (graphScatter())
graphScatter()->setAxisX(axis);
}
QValue3DAxis *QQuickGraphsScatterNode::axisY() const
{
if (graphScatter())
return graphScatter()->axisY();
else
return static_cast<QValue3DAxis *>(m_axisY);
}
void QQuickGraphsScatterNode::setAxisY(QValue3DAxis *axis)
{
if (m_axisY == axis)
return;
m_axisY = axis;
if (graphScatter())
graphScatter()->setAxisY(axis);
}
QValue3DAxis *QQuickGraphsScatterNode::axisZ() const
{
if (graphScatter())
return graphScatter()->axisZ();
else
return static_cast<QValue3DAxis *>(m_axisZ);
}
void QQuickGraphsScatterNode::setAxisZ(QValue3DAxis *axis)
{
if (m_axisZ == axis)
return;
m_axisZ = axis;
if (graphScatter())
graphScatter()->setAxisZ(axis);
}
QScatter3DSeries *QQuickGraphsScatterNode::selectedSeries() const
{
if (graphScatter())
return graphScatter()->selectedSeries();
else
return nullptr;
}
void QQuickGraphsScatterNode::setSelectionMode(QtGraphs3D::SelectionFlags mode)
{
if (graphScatter())
graphScatter()->setSelectionMode(mode);
else
setSelectionMode(mode);
}
QList<QScatter3DSeries *> QQuickGraphsScatterNode::scatterSeriesList()
{
if (graphScatter()) {
return graphScatter()->scatterSeriesList();
} else {
QList<QScatter3DSeries *> scatterSeriesList;
for (QAbstract3DSeries *abstractSeries : m_seriesList) {
QScatter3DSeries *scatterSeries = qobject_cast<QScatter3DSeries *>(abstractSeries);
if (scatterSeries)
scatterSeriesList.append(scatterSeries);
}
return scatterSeriesList;
}
}
QQmlListProperty<QScatter3DSeries> QQuickGraphsScatterNode::seriesList()
{
if (graphScatter()) {
return graphScatter()->seriesList();
} else {
return QQmlListProperty<QScatter3DSeries>(this,
this,
&QQuickGraphsScatterNode::appendSeriesFunc,
&QQuickGraphsScatterNode::countSeriesFunc,
&QQuickGraphsScatterNode::atSeriesFunc,
&QQuickGraphsScatterNode::clearSeriesFunc);
}
}
void QQuickGraphsScatterNode::appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list,
QScatter3DSeries *series)
{
reinterpret_cast<QQuickGraphsScatterNode *>(list->data)->addSeries(series);
}
qsizetype QQuickGraphsScatterNode::countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list)
{
return reinterpret_cast<QQuickGraphsScatterNode *>(list->data)->scatterSeriesList().size();
}
QScatter3DSeries *QQuickGraphsScatterNode::atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list,
qsizetype index)
{
return reinterpret_cast<QQuickGraphsScatterNode *>(list->data)->scatterSeriesList().at(index);
}
void QQuickGraphsScatterNode::clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list)
{
QQuickGraphsScatterNode *declScatterNode = reinterpret_cast<QQuickGraphsScatterNode *>(
list->data);
QList<QScatter3DSeries *> realList = declScatterNode->scatterSeriesList();
qsizetype count = realList.size();
for (qsizetype i = 0; i < count; i++)
declScatterNode->removeSeries(realList.at(i));
}
void QQuickGraphsScatterNode::addSeries(QScatter3DSeries *series)
{
Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesType::Scatter);
if (graphScatter())
graphScatter()->addSeries(series);
QQuickGraphsNode::addSeriesInternal(series);
}
void QQuickGraphsScatterNode::removeSeries(QScatter3DSeries *series)
{
if (graphScatter())
graphScatter()->removeSeries(series);
QQuickGraphsNode::removeSeriesInternal(series);
}
void QQuickGraphsScatterNode::clearSelection()
{
if (graphScatter())
graphScatter()->clearSelection();
}
/*!
* \internal
*/
QQuickGraphsScatter *QQuickGraphsScatterNode::graphScatter()
{
return static_cast<QQuickGraphsScatter *>(m_graph.get());
}
/*!
* \internal
*/
const QQuickGraphsScatter *QQuickGraphsScatterNode::graphScatter() const
{
return static_cast<QQuickGraphsScatter *>(m_graph.get());
}
QT_END_NAMESPACE

View File

@ -0,0 +1,93 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//
// W A R N I N G
// -------------
//
// This file is not part of the QtGraphs API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QQUICKGRAPHSSCATTERNODE_P_H
#define QQUICKGRAPHSSCATTERNODE_P_H
#include "qquickgraphsnode_p.h"
#include "qquickgraphsscatter_p.h"
#include "qbar3dseries.h"
#include <private/qgraphsglobal_p.h>
QT_BEGIN_NAMESPACE
class QQuickGraphsScatterNode;
class Q_GRAPHS_EXPORT QQuickGraphsScatterNode : public QQuickGraphsNode
{
Q_OBJECT
Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged)
Q_PROPERTY(QScatter3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged)
Q_PROPERTY(QQmlListProperty<QScatter3DSeries> seriesList READ seriesList CONSTANT)
Q_CLASSINFO("DefaultProperty", "seriesList")
QML_ADDED_IN_VERSION(6, 10)
QML_NAMED_ELEMENT(Scatter3DNode)
public:
explicit QQuickGraphsScatterNode(QQuick3DNode *parent = nullptr);
~QQuickGraphsScatterNode() override;
QValue3DAxis *axisX() const;
void setAxisX(QValue3DAxis *axis);
QValue3DAxis *axisY() const;
void setAxisY(QValue3DAxis *axis);
QValue3DAxis *axisZ() const;
void setAxisZ(QValue3DAxis *axis);
QScatter3DSeries *selectedSeries() const;
void setSelectionMode(QtGraphs3D::SelectionFlags mode) override;
QList<QScatter3DSeries *> scatterSeriesList();
QQmlListProperty<QScatter3DSeries> seriesList();
static void appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series);
static qsizetype countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list);
static QScatter3DSeries *atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, qsizetype index);
static void clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list);
Q_INVOKABLE void addSeries(QScatter3DSeries *series);
Q_INVOKABLE void removeSeries(QScatter3DSeries *series);
Q_INVOKABLE void clearSelection() override;
protected:
void componentComplete() override;
Q_SIGNALS:
void axisXChanged(QValue3DAxis *axis);
void axisYChanged(QValue3DAxis *axis);
void axisZChanged(QValue3DAxis *axis);
void selectedSeriesChanged(QScatter3DSeries *series);
private:
QQuickGraphsScatter *graphScatter();
const QQuickGraphsScatter *graphScatter() const;
bool m_multiSeriesUniform;
QSizeF m_barSpacing;
float m_barThickness;
bool m_barSpacingRelative;
QSizeF m_barSeriesMargin;
QBar3DSeries *m_primarySeries = nullptr;
QBar3DSeries *m_selectedSeries = nullptr;
float m_floorLevel;
};
QT_END_NAMESPACE
#endif // QQUICKGRAPHSSCATTERNODE_P_H

View File

@ -308,7 +308,7 @@ void QQuickGraphsSurface::changePointerForSeries(const QString &filename, QSurfa
{
if (!filename.isEmpty()) {
// Selection pointer
QQuick3DNode *parent = rootNode();
QQuick3DNode *parent = graphNode();
QQuick3DPrincipledMaterial *pointerMaterial = nullptr;
QQuick3DModel *pointer = m_selectionPointers.value(series);
@ -1025,8 +1025,8 @@ void QQuickGraphsSurface::synchData()
m_topGridScale = new QQuick3DNode();
m_topGridRotation = new QQuick3DNode();
m_topGridScale->setParent(rootNode());
m_topGridScale->setParentItem(rootNode());
m_topGridScale->setParent(graphNode());
m_topGridScale->setParentItem(graphNode());
m_topGridRotation->setParent(m_topGridScale);
m_topGridRotation->setParentItem(m_topGridScale);

View File

@ -284,6 +284,7 @@ private:
DataDimensions m_dataDimensions;
friend class Q3DSurfaceWidgetItem;
friend class QQuickGraphsSurfaceNode;
};
QT_END_NAMESPACE

View File

@ -0,0 +1,239 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qquickgraphssurfacenode_p.h"
QT_BEGIN_NAMESPACE
QQuickGraphsSurfaceNode::QQuickGraphsSurfaceNode(QQuick3DNode *parent)
: QQuickGraphsNode(parent)
, m_flipHorizontalGrid(false)
{}
QQuickGraphsSurfaceNode::~QQuickGraphsSurfaceNode() {}
void QQuickGraphsSurfaceNode::componentComplete()
{
const QString qmlData = QLatin1StringView(R"QML(
import QtQuick;
import QtGraphs;
Surface3D{}
)QML");
QQmlComponent *component = new QQmlComponent(qmlEngine(this), this);
component->setData(qmlData.toUtf8(), QUrl());
m_graph.reset(qobject_cast<QQuickGraphsItem *>(component->create()));
setGraphParent();
QQuickGraphsNode::componentComplete();
//initialize components
if (m_axisX)
graphSurface()->setAxisX(static_cast<QValue3DAxis *>(m_axisX));
if (m_axisY)
graphSurface()->setAxisY(static_cast<QValue3DAxis *>(m_axisY));
if (m_axisZ)
graphSurface()->setAxisZ(static_cast<QValue3DAxis *>(m_axisZ));
graphSurface()->setSelectionMode(m_selectionMode);
graphSurface()->setFlipHorizontalGrid(m_flipHorizontalGrid);
for (auto series : m_seriesList)
graphSurface()->addSeries(static_cast<QSurface3DSeries *>(series));
//connect signals
connect(graphSurface(),
&QQuickGraphsSurface::axisXChanged,
this,
&QQuickGraphsSurfaceNode::axisXChanged);
connect(graphSurface(),
&QQuickGraphsSurface::axisYChanged,
this,
&QQuickGraphsSurfaceNode::axisYChanged);
connect(graphSurface(),
&QQuickGraphsSurface::axisZChanged,
this,
&QQuickGraphsSurfaceNode::axisZChanged);
connect(graphSurface(),
&QQuickGraphsSurface::flipHorizontalGridChanged,
this,
&QQuickGraphsSurfaceNode::flipHorizontalGridChanged);
}
QValue3DAxis *QQuickGraphsSurfaceNode::axisX() const
{
if (graphSurface())
return graphSurface()->axisX();
else
return static_cast<QValue3DAxis *>(m_axisX);
}
void QQuickGraphsSurfaceNode::setAxisX(QValue3DAxis *axis)
{
if (m_axisX == axis)
return;
m_axisX = axis;
if (graphSurface())
graphSurface()->setAxisX(axis);
}
QValue3DAxis *QQuickGraphsSurfaceNode::axisY() const
{
if (graphSurface())
return graphSurface()->axisY();
else
return static_cast<QValue3DAxis *>(m_axisY);
}
void QQuickGraphsSurfaceNode::setAxisY(QValue3DAxis *axis)
{
if (m_axisY == axis)
return;
m_axisY = axis;
if (graphSurface())
graphSurface()->setAxisY(axis);
}
QValue3DAxis *QQuickGraphsSurfaceNode::axisZ() const
{
if (graphSurface())
return graphSurface()->axisZ();
else
return static_cast<QValue3DAxis *>(m_axisZ);
}
void QQuickGraphsSurfaceNode::setAxisZ(QValue3DAxis *axis)
{
if (m_axisZ == axis)
return;
m_axisZ = axis;
if (graphSurface())
graphSurface()->setAxisZ(axis);
}
QSurface3DSeries *QQuickGraphsSurfaceNode::selectedSeries() const
{
if (graphSurface())
return graphSurface()->selectedSeries();
else
return nullptr;
}
void QQuickGraphsSurfaceNode::setSelectionMode(QtGraphs3D::SelectionFlags mode)
{
if (graphSurface())
graphSurface()->setSelectionMode(mode);
else
setSelectionMode(mode);
}
bool QQuickGraphsSurfaceNode::flipHorizontalGrid() const
{
if (graphSurface())
return graphSurface()->flipHorizontalGrid();
else
return m_flipHorizontalGrid;
}
void QQuickGraphsSurfaceNode::setFlipHorizontalGrid(bool flip)
{
if (m_flipHorizontalGrid == flip)
return;
m_flipHorizontalGrid = flip;
if (graphSurface())
graphSurface()->setFlipHorizontalGrid(flip);
}
QList<QSurface3DSeries *> QQuickGraphsSurfaceNode::surfaceSeriesList()
{
if (graphSurface()) {
return graphSurface()->surfaceSeriesList();
} else {
QList<QSurface3DSeries *> surfaceSeriesList;
for (QAbstract3DSeries *abstractSeries : m_seriesList) {
QSurface3DSeries *surfaceSeries = qobject_cast<QSurface3DSeries *>(abstractSeries);
if (surfaceSeries)
surfaceSeriesList.append(surfaceSeries);
}
return surfaceSeriesList;
}
}
QQmlListProperty<QSurface3DSeries> QQuickGraphsSurfaceNode::seriesList()
{
if (graphSurface()) {
return graphSurface()->seriesList();
} else {
return QQmlListProperty<QSurface3DSeries>(this,
this,
&QQuickGraphsSurfaceNode::appendSeriesFunc,
&QQuickGraphsSurfaceNode::countSeriesFunc,
&QQuickGraphsSurfaceNode::atSeriesFunc,
&QQuickGraphsSurfaceNode::clearSeriesFunc);
}
}
void QQuickGraphsSurfaceNode::appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list,
QSurface3DSeries *series)
{
reinterpret_cast<QQuickGraphsSurfaceNode *>(list->data)->addSeries(series);
}
qsizetype QQuickGraphsSurfaceNode::countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list)
{
return reinterpret_cast<QQuickGraphsSurfaceNode *>(list->data)->surfaceSeriesList().size();
}
QSurface3DSeries *QQuickGraphsSurfaceNode::atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list,
qsizetype index)
{
return reinterpret_cast<QQuickGraphsSurfaceNode *>(list->data)->surfaceSeriesList().at(index);
}
void QQuickGraphsSurfaceNode::clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list)
{
QQuickGraphsSurfaceNode *declSurfaceNode = reinterpret_cast<QQuickGraphsSurfaceNode *>(
list->data);
QList<QSurface3DSeries *> realList = declSurfaceNode->surfaceSeriesList();
qsizetype count = realList.size();
for (qsizetype i = 0; i < count; i++)
declSurfaceNode->removeSeries(realList.at(i));
}
void QQuickGraphsSurfaceNode::addSeries(QSurface3DSeries *series)
{
Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesType::Surface);
if (graphSurface())
graphSurface()->addSeries(series);
QQuickGraphsNode::addSeriesInternal(series);
}
void QQuickGraphsSurfaceNode::removeSeries(QSurface3DSeries *series)
{
if (graphSurface())
graphSurface()->removeSeries(series);
QQuickGraphsNode::removeSeriesInternal(series);
}
void QQuickGraphsSurfaceNode::clearSelection()
{
if (graphSurface())
graphSurface()->clearSelection();
}
/*!
* \internal
*/
QQuickGraphsSurface *QQuickGraphsSurfaceNode::graphSurface()
{
return static_cast<QQuickGraphsSurface *>(m_graph.get());
}
/*!
* \internal
*/
const QQuickGraphsSurface *QQuickGraphsSurfaceNode::graphSurface() const
{
return static_cast<QQuickGraphsSurface *>(m_graph.get());
}
QT_END_NAMESPACE

View File

@ -0,0 +1,92 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//
// W A R N I N G
// -------------
//
// This file is not part of the QtGraphs API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QQUICKGRAPHSSURFACENODE_P_H
#define QQUICKGRAPHSSURFACENODE_P_H
#include "qquickgraphsnode_p.h"
#include "qquickgraphssurface_p.h"
#include "qsurface3dseries.h"
#include <private/qgraphsglobal_p.h>
QT_BEGIN_NAMESPACE
class QQuickGraphsSurfaceNode;
class Q_GRAPHS_EXPORT QQuickGraphsSurfaceNode : public QQuickGraphsNode
{
Q_OBJECT
Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged)
Q_PROPERTY(QSurface3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged)
Q_PROPERTY(QQmlListProperty<QSurface3DSeries> seriesList READ seriesList CONSTANT)
Q_PROPERTY(bool flipHorizontalGrid READ flipHorizontalGrid WRITE setFlipHorizontalGrid NOTIFY
flipHorizontalGridChanged)
Q_CLASSINFO("DefaultProperty", "seriesList")
QML_ADDED_IN_VERSION(6, 10)
QML_NAMED_ELEMENT(Surface3DNode)
public:
explicit QQuickGraphsSurfaceNode(QQuick3DNode *parent = nullptr);
~QQuickGraphsSurfaceNode() override;
QValue3DAxis *axisX() const;
void setAxisX(QValue3DAxis *axis);
QValue3DAxis *axisY() const;
void setAxisY(QValue3DAxis *axis);
QValue3DAxis *axisZ() const;
void setAxisZ(QValue3DAxis *axis);
QSurface3DSeries *selectedSeries() const;
void setSelectionMode(QtGraphs3D::SelectionFlags mode) override;
bool flipHorizontalGrid() const;
void setFlipHorizontalGrid(bool flip);
QList<QSurface3DSeries *> surfaceSeriesList();
QQmlListProperty<QSurface3DSeries> seriesList();
static void appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, QSurface3DSeries *series);
static qsizetype countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list);
static QSurface3DSeries *atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, qsizetype index);
static void clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list);
Q_INVOKABLE void addSeries(QSurface3DSeries *series);
Q_INVOKABLE void removeSeries(QSurface3DSeries *series);
Q_INVOKABLE void clearSelection() override;
protected:
void componentComplete() override;
Q_SIGNALS:
void axisXChanged(QValue3DAxis *axis);
void axisYChanged(QValue3DAxis *axis);
void axisZChanged(QValue3DAxis *axis);
void selectedSeriesChanged(QSurface3DSeries *series);
void flipHorizontalGridChanged(bool flip);
private:
QQuickGraphsSurface *graphSurface();
const QQuickGraphsSurface *graphSurface() const;
bool m_flipHorizontalGrid;
};
QT_END_NAMESPACE
#endif // QQUICKGRAPHSSURFACENODE_P_H

View File

@ -24,11 +24,13 @@ target_link_libraries(tst_qmlinjection PUBLIC
set(qmlinjection_resource_files
"qml/qmlinjection/main.qml"
"qml/qmlinjection/GraphInjection.qml"
"qml/qmlinjection/GraphNodeInjection.qml"
"qml/qmlinjection/MultiView.qml"
"qml/qmlinjection/MultiGraph.qml"
"qml/qmlinjection/australia.png"
"qml/qmlinjection/australiaSatellite.jpg"
"qml/qmlinjection/plane.mesh"
"qml/qmlinjection/layer_1.png"
)
qt_internal_add_resource(tst_qmlinjection "qmlinjection"

View File

@ -85,7 +85,7 @@ Item {
3,
zPos
)
lookAtNode: bars.rootNode
lookAtNode: cube
eulerRotation.x: -30
clipNear: 0.001
}

View File

@ -0,0 +1,216 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick3D
import QtQuick3D.Helpers
import QtGraphs
import QtQml
import QtQuick
import QtQuick.Controls.Fusion
import QtQuick.Layouts
Item {
Gradient {
id: customGradient
GradientStop { id: redstop; position: 0.0; color: "red" }
GradientStop { id: greenstop; position: 1.0; color: "green" }
}
View3D {
id: view3d
anchors.fill: parent
camera: cam
environment: SceneEnvironment {
clearColor: "skyblue"
backgroundMode: SceneEnvironment.Color
}
DirectionalLight {
eulerRotation.x: -30
}
PerspectiveCamera {
id: cam
property real xPos: Math.cos(camRot.value * 2 * Math.PI) * 100
property real zPos: Math.sin(camRot.value * 2 * Math.PI) * 100
position: Qt.vector3d(
xPos,
3,
zPos
)
lookAtNode: lookAt
eulerRotation.x: -30
clipNear: 0.001
}
Surface3DNode {
scale: Qt.vector3d(cSlider.value, cSlider.value, cSlider.value)
position: Qt.vector3d(0,0, 4.0 * cSlider.value)
polar: propertyButton.isEnabled
flipHorizontalGrid: propertyButton.isEnabled
margin: propertyButton.isEnabled? 0 : 0.1
aspectRatio: 3
theme: GraphsTheme {
colorScheme: GraphsTheme.ColorScheme.Dark
labelBorderVisible: true
labelFont.pointSize: 35
labelBackgroundVisible: true
colorStyle: propertyButton.isEnabled? GraphsTheme.ColorStyle.RangeGradient : GraphsTheme.ColorStyle.Uniform
baseGradients: [customGradient]
}
Surface3DSeries {
id: heightSeries
shading: Surface3DSeries.Shading.Smooth
drawMode: propertyButton.isEnabled? Surface3DSeries.DrawSurface : Surface3DSeries.DrawSurfaceAndWireframe
meshSmooth: true
HeightMapSurfaceDataProxy {
heightMapFile: "://qml/qmlinjection/layer_1.png"
minYValue: 0
maxYValue: 7
autoScaleY: true
}
}
}
Bars3DNode {
scale: Qt.vector3d(cSlider.value, cSlider.value, cSlider.value)
optimizationHint: propertyButton.isEnabled? Graphs3D.OptimizationHint.Legacy : Graphs3D.OptimizationHint.Default
theme: GraphsTheme {
colorScheme: GraphsTheme.ColorScheme.Dark
labelBorderVisible: true
labelFont.pointSize: 35
labelBackgroundVisible: true
colorStyle: GraphsTheme.ColorStyle.RangeGradient
baseGradients: [customGradient]
}
Bar3DSeries {
mesh: Abstract3DSeries.Mesh.Cylinder
ItemModelBarDataProxy {
itemModel: ListModel {
ListElement{ coords: "0,0"; data: "20.0/10.0/4.75"; }
ListElement{ coords: "1,0"; data: "21.1/10.3/3.00"; }
ListElement{ coords: "2,0"; data: "22.5/10.7/1.24"; }
ListElement{ coords: "3,0"; data: "24.0/10.5/2.53"; }
ListElement{ coords: "0,1"; data: "20.2/11.2/3.55"; }
ListElement{ coords: "1,1"; data: "21.3/11.5/3.03"; }
ListElement{ coords: "2,1"; data: "22.6/11.7/3.46"; }
ListElement{ coords: "3,1"; data: "23.4/11.5/4.12"; }
ListElement{ coords: "0,2"; data: "20.2/12.3/3.37"; }
ListElement{ coords: "1,2"; data: "21.1/12.4/2.98"; }
ListElement{ coords: "2,2"; data: "22.5/12.1/3.33"; }
ListElement{ coords: "3,2"; data: "23.3/12.7/3.23"; }
ListElement{ coords: "0,3"; data: "20.7/13.3/5.34"; }
ListElement{ coords: "1,3"; data: "21.5/13.2/4.54"; }
ListElement{ coords: "2,3"; data: "22.4/13.6/4.65"; }
ListElement{ coords: "3,3"; data: "23.2/13.4/6.67"; }
ListElement{ coords: "0,4"; data: "20.6/15.0/6.01"; }
ListElement{ coords: "1,4"; data: "21.3/14.6/5.83"; }
ListElement{ coords: "2,4"; data: "22.5/14.8/7.32"; }
ListElement{ coords: "3,4"; data: "23.7/14.3/6.90"; }
}
rowRole: "coords"
valueRole: "coords"
columnRole: "data"
rowRolePattern: /(\d),\d/
valueRolePattern: /(\d),(\d)/
columnRolePattern: /^([^\/]*)\/([^\/]*)\/(.*)$/
rowRoleReplace: "\\1"
valueRoleReplace: "\\2"
columnRoleReplace: "\\3"
}
}
}
Scatter3DNode {
scale: Qt.vector3d(cSlider.value, cSlider.value, cSlider.value)
position: Qt.vector3d(0,0, -4.0 * cSlider.value)
optimizationHint: propertyButton.isEnabled? Graphs3D.OptimizationHint.Legacy : Graphs3D.OptimizationHint.Default
theme: GraphsTheme {
colorScheme: GraphsTheme.ColorScheme.Dark
labelBorderVisible: true
labelFont.pointSize: 35
labelBackgroundVisible: true
colorStyle: GraphsTheme.ColorStyle.RangeGradient
baseGradients: [customGradient]
}
Scatter3DSeries {
ItemModelScatterDataProxy {
itemModel: ListModel {
ListElement{ coords: "0,0"; data: "20.0/10.0/4.75"; }
ListElement{ coords: "1,0"; data: "21.1/10.3/3.00"; }
ListElement{ coords: "2,0"; data: "22.5/10.7/1.24"; }
ListElement{ coords: "3,0"; data: "24.0/10.5/2.53"; }
ListElement{ coords: "0,1"; data: "20.2/11.2/3.55"; }
ListElement{ coords: "1,1"; data: "21.3/11.5/3.03"; }
ListElement{ coords: "2,1"; data: "22.6/11.7/3.46"; }
ListElement{ coords: "3,1"; data: "23.4/11.5/4.12"; }
ListElement{ coords: "0,2"; data: "20.2/12.3/3.37"; }
ListElement{ coords: "1,2"; data: "21.1/12.4/2.98"; }
ListElement{ coords: "2,2"; data: "22.5/12.1/3.33"; }
ListElement{ coords: "3,2"; data: "23.3/12.7/3.23"; }
ListElement{ coords: "0,3"; data: "20.7/13.3/5.34"; }
ListElement{ coords: "1,3"; data: "21.5/13.2/4.54"; }
ListElement{ coords: "2,3"; data: "22.4/13.6/4.65"; }
ListElement{ coords: "3,3"; data: "23.2/13.4/6.67"; }
ListElement{ coords: "0,4"; data: "20.6/15.0/6.01"; }
ListElement{ coords: "1,4"; data: "21.3/14.6/5.83"; }
ListElement{ coords: "2,4"; data: "22.5/14.8/7.32"; }
ListElement{ coords: "3,4"; data: "23.7/14.3/6.90"; }
}
zPosRole: "coords"
yPosRole: "coords"
xPosRole: "data"
zPosRolePattern: /(\d),\d/
yPosRolePattern: /(\d),(\d)/
xPosRolePattern: /^([^\/]*)\/([^\/]*)\/(.*)$/
zPosRoleReplace: "\\1"
yPosRoleReplace: "\\2"
xPosRoleReplace: "\\3"
}
}
}
Node {
id: lookAt
}
}
Slider {
anchors.bottom: view3d.bottom
anchors.left: view3d.left
anchors.right: view3d.right
id: camRot
from: 0
to: 1
stepSize: 0.01
value: 0
}
RowLayout {
Button {
id: propertyButton
property bool isEnabled: true
text: "Change various properties"
onClicked: isEnabled = !isEnabled
}
Text {
text: "Graph scale"
}
Slider {
id: cSlider
from: 1
value: 20
to: 50
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -21,6 +21,10 @@ Item {
text: qsTr("Basic Injection")
}
TabButton {
text: qsTr("Node Injection")
}
TabButton {
text: qsTr("Multi-view")
}
@ -39,9 +43,12 @@ Item {
GraphInjection {}
GraphNodeInjection {}
MultiView {}
MultiGraph {}
}
}