From 630b38b3eed20c654cc13f5aedae4f704adfd963 Mon Sep 17 00:00:00 2001 From: Sami Varanka Date: Tue, 12 Aug 2025 09:08:50 +0300 Subject: [PATCH] Fix: crash when closing Graphs2D MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When series is created outside of graphsview and then added into a graphsview, the app crashes while closing. This seems to be because it ends up calling pure virtual type function from the QAbstractSeries in the getSeriesRendererIndex. This patch adds type variable to QAbstractSeriesPrivate. The variable is set by QAbstractSeriesPrivate constructor. The getSeriesRendererIndex function checks the value of that variable instead of calling the virtual type(). Pick-to: 6.8 6.9 6.10 Fixes: QTBUG-138506 Change-Id: I7aca4970c38cbf83413818b0a77e7cf5d76195b6 Reviewed-by: Tomi Korpipää Reviewed-by: Kaj Grönholm --- src/graphs2d/areachart/qareaseries.cpp | 5 ++++- src/graphs2d/barchart/qbarseries.cpp | 22 +++++++++++--------- src/graphs2d/linechart/qlineseries.cpp | 5 ++++- src/graphs2d/piechart/qpieseries.cpp | 3 ++- src/graphs2d/qabstractseries.cpp | 4 +++- src/graphs2d/qabstractseries_p.h | 10 +++++++-- src/graphs2d/qgraphsview.cpp | 6 ++++-- src/graphs2d/scatterchart/qscatterseries.cpp | 2 ++ src/graphs2d/splinechart/qsplineseries.cpp | 2 +- src/graphs2d/xychart/qxyseries.cpp | 5 ++++- src/graphs2d/xychart/qxyseries_p.h | 2 +- 11 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/graphs2d/areachart/qareaseries.cpp b/src/graphs2d/areachart/qareaseries.cpp index 6a98be33..8299f01d 100644 --- a/src/graphs2d/areachart/qareaseries.cpp +++ b/src/graphs2d/areachart/qareaseries.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/qabstractseries_p.h" #include #include #include @@ -472,6 +473,8 @@ void QAreaSeries::setSelectedGradient(QQuickShapeGradient* newSelectedGradient) emit selectedGradientChanged(newSelectedGradient); } -QAreaSeriesPrivate::QAreaSeriesPrivate() {} +QAreaSeriesPrivate::QAreaSeriesPrivate() + : QAbstractSeriesPrivate(QAbstractSeries::SeriesType::Area) +{} QT_END_NAMESPACE diff --git a/src/graphs2d/barchart/qbarseries.cpp b/src/graphs2d/barchart/qbarseries.cpp index 0c441e98..226220b3 100644 --- a/src/graphs2d/barchart/qbarseries.cpp +++ b/src/graphs2d/barchart/qbarseries.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/qabstractseries_p.h" #include #include #include @@ -1155,16 +1156,17 @@ void QBarSeries::setBarDelegateDirty(bool dirty) } QBarSeriesPrivate::QBarSeriesPrivate() - : m_barWidth(0.5) // Default value is 50% of category width - , m_labelsVisible(false) - , m_visible(true) - , m_blockBarUpdate(false) - , m_labelsFormat() - , m_labelsMargin(0) - , m_labelsAngle(0) - , m_labelsPrecision(6) - , m_labelsDirty(true) - , m_barDelegateDirty(false) + : QAbstractSeriesPrivate(QAbstractSeries::SeriesType::Bar) + , m_barWidth(0.5) // Default value is 50% of category width + , m_labelsVisible(false) + , m_visible(true) + , m_blockBarUpdate(false) + , m_labelsFormat() + , m_labelsMargin(0) + , m_labelsAngle(0) + , m_labelsPrecision(6) + , m_labelsDirty(true) + , m_barDelegateDirty(false) { } diff --git a/src/graphs2d/linechart/qlineseries.cpp b/src/graphs2d/linechart/qlineseries.cpp index 1a494ceb..52c50f44 100644 --- a/src/graphs2d/linechart/qlineseries.cpp +++ b/src/graphs2d/linechart/qlineseries.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/xychart/qxyseries_p.h" #include #include #include @@ -176,7 +177,9 @@ QAbstractSeries::SeriesType QLineSeries::type() const return QAbstractSeries::SeriesType::Line; } -QLineSeriesPrivate::QLineSeriesPrivate() {} +QLineSeriesPrivate::QLineSeriesPrivate() + : QXYSeriesPrivate(QAbstractSeries::SeriesType::Line) +{} /*! \property QLineSeries::width diff --git a/src/graphs2d/piechart/qpieseries.cpp b/src/graphs2d/piechart/qpieseries.cpp index c3cd2e66..19e388c3 100644 --- a/src/graphs2d/piechart/qpieseries.cpp +++ b/src/graphs2d/piechart/qpieseries.cpp @@ -1198,7 +1198,8 @@ void QPieSeries::setAngleSpanLabelVisibility(QPieSeries::LabelVisibility newAngl } QPieSeriesPrivate::QPieSeriesPrivate() - : m_pieRelativeHorPos(.5) + : QAbstractSeriesPrivate(QAbstractSeries::SeriesType::Pie) + , m_pieRelativeHorPos(.5) , m_pieRelativeVerPos(.5) , m_pieRelativeSize(.7) , m_pieStartAngle(0) diff --git a/src/graphs2d/qabstractseries.cpp b/src/graphs2d/qabstractseries.cpp index 2c0bc8ee..a919893b 100644 --- a/src/graphs2d/qabstractseries.cpp +++ b/src/graphs2d/qabstractseries.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/qabstractseries.h" #include #include #include @@ -680,7 +681,8 @@ void QAbstractSeries::componentComplete() /////////////////////////////////////////////////////////////////////////////////////////////////// -QAbstractSeriesPrivate::QAbstractSeriesPrivate() +QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries::SeriesType type) + : m_type(type) { } diff --git a/src/graphs2d/qabstractseries_p.h b/src/graphs2d/qabstractseries_p.h index 9907e644..f58c7bd2 100644 --- a/src/graphs2d/qabstractseries_p.h +++ b/src/graphs2d/qabstractseries_p.h @@ -14,8 +14,8 @@ // // We mean it. +#include "graphs2d/qabstractseries.h" #include -#include #include #include @@ -31,11 +31,15 @@ class QAbstractSeriesPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QAbstractSeries) public: - explicit QAbstractSeriesPrivate(); + static QAbstractSeriesPrivate *get(QAbstractSeries *item) { return item->d_func(); } + static const QAbstractSeriesPrivate *get(const QAbstractSeries *item) { return item->d_func(); } + + explicit QAbstractSeriesPrivate(QAbstractSeries::SeriesType type); ~QAbstractSeriesPrivate() override; void setLegendData(const QList &legendData); void clearLegendData(); + QAbstractSeries::SeriesType type() { return m_type; } static void appendSeriesChildren(QQmlListProperty *list, QObject *element); @@ -56,6 +60,8 @@ private: QAbstractAxis *m_axisX = nullptr; QAbstractAxis *m_axisY = nullptr; + + QAbstractSeries::SeriesType m_type; }; QT_END_NAMESPACE diff --git a/src/graphs2d/qgraphsview.cpp b/src/graphs2d/qgraphsview.cpp index e0240998..7a731876 100644 --- a/src/graphs2d/qgraphsview.cpp +++ b/src/graphs2d/qgraphsview.cpp @@ -1,6 +1,8 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/qabstractseries.h" +#include "graphs2d/qabstractseries_p.h" #ifdef USE_AREAGRAPH #include #include @@ -177,7 +179,7 @@ void QGraphsView::insertSeries(qsizetype index, QObject *object) */ void QGraphsView::removeSeries(QObject *object) { - if (auto series = reinterpret_cast(object)) { + if (auto series = qobject_cast(object)) { series->setGraph(nullptr); m_seriesList.removeAll(series); auto &cleanupSeriesList = m_cleanupSeriesList[getSeriesRendererIndex(series)]; @@ -1699,7 +1701,7 @@ int QGraphsView::getSeriesRendererIndex(QAbstractSeries *series) { int index = 0; if (series) { - switch (series->type()) { + switch (QAbstractSeriesPrivate::get(series)->type()) { case QAbstractSeries::SeriesType::Bar: index = 0; break; diff --git a/src/graphs2d/scatterchart/qscatterseries.cpp b/src/graphs2d/scatterchart/qscatterseries.cpp index 41d3b1d2..b7ddd000 100644 --- a/src/graphs2d/scatterchart/qscatterseries.cpp +++ b/src/graphs2d/scatterchart/qscatterseries.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/xychart/qxyseries_p.h" #include #include #include @@ -140,6 +141,7 @@ QAbstractSeries::SeriesType QScatterSeries::type() const } QScatterSeriesPrivate::QScatterSeriesPrivate() + : QXYSeriesPrivate(QAbstractSeries::SeriesType::Scatter) { } diff --git a/src/graphs2d/splinechart/qsplineseries.cpp b/src/graphs2d/splinechart/qsplineseries.cpp index 98b6207f..4023e571 100644 --- a/src/graphs2d/splinechart/qsplineseries.cpp +++ b/src/graphs2d/splinechart/qsplineseries.cpp @@ -166,7 +166,7 @@ void QSplineSeries::setCapStyle(Qt::PenCapStyle newCapStyle) } QSplineSeriesPrivate::QSplineSeriesPrivate() - : QXYSeriesPrivate() + : QXYSeriesPrivate(QAbstractSeries::SeriesType::Spline) , m_width(1.0) , m_capStyle(Qt::PenCapStyle::SquareCap) , m_controlPoints() diff --git a/src/graphs2d/xychart/qxyseries.cpp b/src/graphs2d/xychart/qxyseries.cpp index 3597df15..764f748f 100644 --- a/src/graphs2d/xychart/qxyseries.cpp +++ b/src/graphs2d/xychart/qxyseries.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "graphs2d/qabstractseries.h" #include #include #include @@ -959,7 +960,9 @@ QXYSeries &QXYSeries::operator<< (const QList& points) return *this; } -QXYSeriesPrivate::QXYSeriesPrivate() {} +QXYSeriesPrivate::QXYSeriesPrivate(QAbstractSeries::SeriesType type) + : QAbstractSeriesPrivate(type) +{} void QXYSeriesPrivate::setPointSelected(qsizetype index, bool selected, bool &callSignal) { diff --git a/src/graphs2d/xychart/qxyseries_p.h b/src/graphs2d/xychart/qxyseries_p.h index 12153f09..77d6ec9f 100644 --- a/src/graphs2d/xychart/qxyseries_p.h +++ b/src/graphs2d/xychart/qxyseries_p.h @@ -27,7 +27,7 @@ public: static QXYSeriesPrivate *get(QXYSeries *item) { return item->d_func(); } static const QXYSeriesPrivate *get(const QXYSeries *item) { return item->d_func(); } - QXYSeriesPrivate(); + QXYSeriesPrivate(QAbstractSeries::SeriesType type); void setPointSelected(qsizetype index, bool selected, bool &callSignal); bool isPointSelected(qsizetype index) const;