Revision control
++ // Copyright (C) 2025 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++
++ #include "qcustom3ditem.h"
++ #include "qgraphs3dlogging_p.h"
++ #include "qquickgraphsnode_p.h"
++ #include <qtconfigmacros.h>
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ * \qmltype GraphsNode
++ * \inherits Node
++ * \qmlabstract
++ * \inqmlmodule QtGraphs
++ * \ingroup graphs_qml_3D
++ * \brief Base type for 3D graphs.
++ *
++ * The uncreatable base type for all 3D graph nodes in Qt Graphs.
++ *
++ * \sa Bars3DNode, Scatter3DNode, Surface3DNode, {Qt Graphs C++ Classes for 3D}
++ */
++
++ /*!
++ * \qmlproperty Graphs3D.SelectionMode GraphsNode::selectionMode
++ * The active selection mode in the graph.
++ * One of the \l graphs3d.selectionflag enum values.
++ */
++
++ /*!
++ * \qmlproperty GraphsTheme GraphsNode::theme
++ * The active theme of the graph.
++ *
++ * \sa GraphsTheme
++ */
++
++ /*!
++ * \qmlproperty list<Custom3DItem> GraphsNode::customItemList
++ *
++ * The list of \l{Custom3DItem} items added to the graph. The graph takes
++ * ownership of the added items.
++ */
++
++ /*!
++ * \qmlproperty bool GraphsNode::polar
++ *
++ * If \c {true}, the horizontal axes are changed into polar axes. The x-axis
++ * becomes the angular axis and the z-axis becomes the radial axis.
++ * Polar mode is not available for bar graphs.
++ *
++ * Defaults to \c{false}.
++ *
++ * \sa radialLabelOffset
++ */
++
++ /*!
++ * \qmlproperty real GraphsNode::labelMargin
++ *
++ * This property specifies the margin for the placement of the axis labels.
++ *
++ * Negative values place the labels inside the plot-area while positive values
++ * place them outside the plot-area. Label automatic rotation is disabled when
++ * the value is negative. Defaults to \c 0.1
++ *
++ * \sa QAbstract3DAxis::labelAutoAngle
++ *
++ */
++
++ /*!
++ * \qmlproperty real GraphsNode::radialLabelOffset
++ *
++ * This property specifies the normalized horizontal offset for the axis labels
++ * of the radial polar axis. The value \c 0.0 indicates that the labels should
++ * be drawn next to the 0-angle angular axis grid line. The value \c 1.0
++ * indicates that the labels are drawn in their usual place at the edge of the
++ * graph background. This property is ignored if the polar property value is
++ * \c{false}. Defaults to \c 1.0.
++ *
++ * \sa polar
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::clearSelection()
++ * Clears selection from all attached series.
++ */
++
++ /*!
++ * \qmlmethod bool GraphsNode::hasSeries(Abstract3DSeries series)
++ * Returns whether the \a series has already been added to the graph.
++ */
++
++ /*!
++ * \qmlmethod qsizetype GraphsNode::addCustomItem(Custom3DItem item)
++ *
++ * Adds a Custom3DItem \a item to the graph. Graph takes ownership of the added
++ * item.
++ *
++ * \return index to the added item if add was successful, -1 if trying to add a
++ * null item, and index of the item if trying to add an already added item.
++ *
++ * \sa removeCustomItems(), removeCustomItem(), removeCustomItemAt()
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::removeCustomItems()
++ *
++ * Removes all custom items. Deletes the resources allocated to them.
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::removeCustomItem(Custom3DItem item)
++ *
++ * Removes the custom \a {item}. Deletes the resources allocated to it.
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::removeCustomItemAt(vector3d position)
++ *
++ * Removes all custom items at \a {position}. Deletes the resources allocated to them.
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::releaseCustomItem(Custom3DItem item)
++ *
++ * Gets ownership of \a item back and removes the \a item from the graph.
++ *
++ * \note If the same item is added back to the graph, the texture file needs to
++ * be re-set.
++ *
++ * \sa Custom3DItem::textureFile
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::doPicking(QPoint point)
++ *
++ * Performs picking using view coordinates from \a point
++ * on the elements of the graph, selecting the first item hit.
++ * Default input handling performs this upon receiving the onTapped event.
++ *
++ * \sa selectedElement
++ */
++
++ /*!
++ * \qmlmethod void GraphsNode::doRayPicking(QVector3D origin, QVector3D direction)
++ *
++ * Performs picking starting from \a origin and in \a direction
++ * on the elements of the graph, selecting the first item hit.
++ *
++ * \sa selectedElement
++ */
++
++ /*!
++ * \qmlmethod int GraphsNode::selectedLabelIndex()
++ *
++ * Can be used to query the index of the selected label after receiving
++ * \c selectedElementChanged signal with any label type. Selection is valid
++ * until the next \c selectedElementChanged signal.
++ *
++ * \return index of the selected label, or -1.
++ *
++ * \sa selectedElement
++ */
++
++ /*!
++ * \qmlmethod Abstract3DAxis GraphsNode::selectedAxis()
++ *
++ * Can be used to get the selected axis after receiving \c selectedElementChanged
++ * signal with any label type. Selection is valid until the next
++ * \c selectedElementChanged signal.
++ *
++ * \return the selected axis, or null.
++ *
++ * \sa selectedElement
++ */
++
++ /*!
++ * \qmlmethod qsizetype GraphsNode::selectedCustomItemIndex()
++ *
++ * Can be used to query the index of the selected custom item after receiving
++ * \c selectedElementChanged signal with
++ * \l{QtGraphs3D::ElementType::CustomItem}{ElementType.CustomItem} type.
++ * Selection is valid until the next \c selectedElementChanged signal.
++ *
++ * \return index of the selected custom item, or -1.
++ *
++ * \sa selectedElement
++ */
++
++ /*!
++ * \qmlmethod Custom3DItem GraphsNode::selectedCustomItem()
++ *
++ * Can be used to get the selected custom item after receiving
++ * \c selectedElementChanged signal with
++ * \l{QtGraphs3D::ElementType::CustomItem}{ElementType.CustomItem} type.
++ * Ownership of the item remains with the graph.
++ * Selection is valid until the next \c selectedElementChanged signal.
++ *
++ * \return the selected custom item, or null.
++ *
++ * \sa selectedElement
++ */
++
++ /*!
++ * \qmlproperty Graphs3D.ElementType GraphsNode::selectedElement
++ * \readonly
++ *
++ * The element selected in the graph.
++ *
++ * This property can be used to query the selected element type.
++ * The type is valid until a new selection is made in the graph and the
++ * \c selectedElementChanged signal is emitted.
++ *
++ * The signal can be used for example for implementing customized input
++ * handling, as demonstrated by the \l {Axis Handling} example.
++ *
++ * \sa selectedLabelIndex(), selectedAxis(), selectedCustomItemIndex(),
++ * selectedCustomItem(), Bars3DNode::selectedSeries, Scatter3DNode::selectedSeries,
++ * Scene3D::selectionQueryPosition, Graphs3D.ElementType
++ */
++
++ /*!
++ * \qmlproperty real GraphsNode::aspectRatio
++ *
++ * The ratio of the graph scaling between the longest axis on the horizontal
++ * plane and the y-axis. Defaults to \c{2.0}.
++ *
++ * \note Has no effect on Bars3D.
++ *
++ * \sa horizontalAspectRatio
++ */
++
++ /*!
++ * \qmlproperty real GraphsNode::horizontalAspectRatio
++ *
++ * The ratio of the graph scaling between the x-axis and z-axis.
++ * The value of \c 0.0 indicates automatic scaling according to axis ranges.
++ * Defaults to \c{0.0}.
++ *
++ * \note Has no effect on Bars3DNode, which handles scaling on the horizontal plane
++ * via the \l{Bars3DNode::barThickness}{barThickness} and
++ * \l{Bars3DNode::barSpacing}{barSpacing} properties. Polar graphs also ignore this
++ * property.
++ *
++ * \sa aspectRatio, polar, Bars3DNode::barThickness, Bars3DNode::barSpacing
++ */
++
++ /*!
++ * \qmlproperty Graphs3D.OptimizationHint GraphsNode::optimizationHint
++ *
++ * \brief Specifies whether the default or legacy mode is used for rendering optimization.
++ *
++ * The default mode uses instanced rendering, and provides the full feature set
++ * at the best level of performance on most systems. The static mode optimizes
++ * graph rendering and is ideal for large non-changing data sets. It is slower
++ * with dynamic data changes and item rotations. Selection is not optimized, so
++ * using the static mode with massive data sets is not advisable. Legacy mode
++ * renders all items in th graph individually, without instancing. It should be
++ * used only if default mode does not work, that is the same as if the target
++ * system does not support instancing. Defaults to
++ * \l{QtGraphs3D::OptimizationHint::Default}{Default}.
++ *
++ * \note On some environments, large graphs using static optimization may not
++ * render, because all of the items are rendered using a single draw call, and
++ * different graphics drivers support different maximum vertice counts per call.
++ * This is mostly an issue on 32bit and OpenGL ES2 platforms. To work around
++ * this issue, choose an item mesh with a low vertex count or use the point mesh.
++ *
++ * \sa Abstract3DSeries::mesh, Graphs3D.OptimizationHint
++ */
++
++ /*!
++ * \qmlproperty locale GraphsNode::locale
++ *
++ * Sets the locale used for formatting various numeric labels.
++ * Defaults to the \c{"C"} locale.
++ *
++ * \sa Value3DAxis::labelFormat
++ */
++
++ /*!
++ * \qmlproperty vector3d GraphsNode::queriedGraphPosition
++ * \readonly
++ *
++ * This read-only property contains the latest graph position values along each
++ * axis queried using Scene3D::graphPositionQuery. The values are normalized to
++ * range \c{[-1, 1]}. If the queried position was outside the graph bounds, the
++ * values will not reflect the real position, but will instead be some undefined
++ * position outside the range \c{[-1, 1]}. The value will be undefined until a
++ * query is made.
++ *
++ * There is no single correct 3D coordinate to match a particular screen
++ * position, so to be consistent, the queries are always done against the inner
++ * sides of an invisible box surrounding the graph.
++ *
++ * \note Bar graphs only allow querying graph position at the graph floor level,
++ * so the y-value is always zero for bar graphs and valid queries can be only
++ * made at screen positions that contain the floor of the graph.
++ *
++ * \sa Scene3D::graphPositionQuery
++ */
++
++ /*!
++ * \qmlproperty real GraphsNode::margin
++ *
++ * The absolute value used for the space left between the edge of the
++ * plottable graph area and the edge of the graph background.
++ *
++ * If the margin value is negative, the margins are determined automatically and
++ * can vary according to the size of the items in the series and the type of the
++ * graph. The value is interpreted as a fraction of the y-axis range if the
++ * graph aspect ratios have not been changed from the default values.
++ * Defaults to \c{-1.0}.
++ *
++ * \note Setting a smaller margin for a scatter graph than the automatically
++ * determined margin can cause the scatter items at the edges of the graph to
++ * overlap with the graph background.
++ *
++ * \note On scatter and surface graphs, if the margin is small in comparison to
++ * the axis label size, the positions of the edge labels of the axes are
++ * adjusted to avoid overlap with the edge labels of the neighboring axes.
++ */
++
++ /*!
++ * \qmlproperty Graphs3D.GridLineType GraphsNode::gridLineType
++ *
++ * Defines whether the grid lines type is \c Graphs3D.GridLineType.Shader or
++ * \c Graphs3D.GridLineType.Geometry.
++ *
++ * This value affects all grid lines.
++ *
++ * \sa Graphs3D.GridLineType
++ */
++
++ 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 : std::as_const(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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "theme is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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) {
++ qCDebug(lcProperties3D) << __FUNCTION__
++ << "value is already set to:" << 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 : std::as_const(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
++
++ #include "moc_qquickgraphsnode_p.cpp"