Fix: crash when closing Graphs2D

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
Fixes: QTBUG-138506
Change-Id: I7aca4970c38cbf83413818b0a77e7cf5d76195b6
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Reviewed-by: Kaj Grönholm <kaj.gronholm@qt.io>
(cherry picked from commit 630b38b3ee)
Reviewed-by: Sami Varanka <sami.varanka@qt.io>
This commit is contained in:
Sami Varanka 2025-08-12 09:08:50 +03:00
parent 86c90e3ae2
commit 43ccf20e67
11 changed files with 45 additions and 21 deletions

View File

@ -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 <QtGraphs/qareaseries.h>
#include <private/qareaseries_p.h>
#include <private/qgraphsview_p.h>
@ -366,6 +367,8 @@ void QAreaSeries::setLowerSeries(QXYSeries *newLowerSeries)
emit lowerSeriesChanged();
}
QAreaSeriesPrivate::QAreaSeriesPrivate() {}
QAreaSeriesPrivate::QAreaSeriesPrivate()
: QAbstractSeriesPrivate(QAbstractSeries::SeriesType::Area)
{}
QT_END_NAMESPACE

View File

@ -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 <QtGraphs/qabstractseries.h>
#include <QtGraphs/qbarseries.h>
#include <QtGraphs/qbarset.h>
@ -1146,7 +1147,8 @@ void QBarSeries::setBarDelegateDirty(bool dirty)
}
QBarSeriesPrivate::QBarSeriesPrivate()
: m_barWidth(0.5) // Default value is 50% of category width
: QAbstractSeriesPrivate(QAbstractSeries::SeriesType::Bar)
, m_barWidth(0.5) // Default value is 50% of category width
, m_labelsVisible(false)
, m_visible(true)
, m_blockBarUpdate(false)

View File

@ -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 <QtGraphs/qlineseries.h>
#include <private/qgraphsview_p.h>
#include <private/qlineseries_p.h>
@ -110,7 +111,9 @@ QAbstractSeries::SeriesType QLineSeries::type() const
return QAbstractSeries::SeriesType::Line;
}
QLineSeriesPrivate::QLineSeriesPrivate() {}
QLineSeriesPrivate::QLineSeriesPrivate()
: QXYSeriesPrivate(QAbstractSeries::SeriesType::Line)
{}
qreal QLineSeries::width() const
{

View File

@ -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)

View File

@ -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 <QtGraphs/qabstractseries.h>
#include <private/qabstractseries_p.h>
#include <private/qgraphsview_p.h>
@ -680,7 +681,8 @@ void QAbstractSeries::componentComplete()
///////////////////////////////////////////////////////////////////////////////////////////////////
QAbstractSeriesPrivate::QAbstractSeriesPrivate()
QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries::SeriesType type)
: m_type(type)
{
}

View File

@ -14,8 +14,8 @@
//
// We mean it.
#include "graphs2d/qabstractseries.h"
#include <QtGraphs/qabstractseries.h>
#include <memory>
#include <private/qobject_p.h>
#include <QtCore/qloggingcategory.h>
@ -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<QLegendData> &legendData);
void clearLegendData();
QAbstractSeries::SeriesType type() { return m_type; }
static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element);
@ -56,6 +60,8 @@ private:
QAbstractAxis *m_axisX = nullptr;
QAbstractAxis *m_axisY = nullptr;
QAbstractSeries::SeriesType m_type;
};
QT_END_NAMESPACE

View File

@ -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 <QtGraphs/qareaseries.h>
#include <private/arearenderer_p.h>
@ -177,7 +179,7 @@ void QGraphsView::insertSeries(qsizetype index, QObject *object)
*/
void QGraphsView::removeSeries(QObject *object)
{
if (auto series = reinterpret_cast<QAbstractSeries *>(object)) {
if (auto series = qobject_cast<QAbstractSeries *>(object)) {
series->setGraph(nullptr);
m_seriesList.removeAll(series);
auto &cleanupSeriesList = m_cleanupSeriesList[getSeriesRendererIndex(series)];
@ -1692,7 +1694,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;

View File

@ -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 <QtGraphs/qscatterseries.h>
#include <private/qxypoint_p.h>
#include <private/qscatterseries_p.h>
@ -140,6 +141,7 @@ QAbstractSeries::SeriesType QScatterSeries::type() const
}
QScatterSeriesPrivate::QScatterSeriesPrivate()
: QXYSeriesPrivate(QAbstractSeries::SeriesType::Scatter)
{
}

View File

@ -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()

View File

@ -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 <QtGraphs/qxyseries.h>
#include <private/qxyseries_p.h>
#include <private/charthelpers_p.h>
@ -961,7 +962,9 @@ QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
return *this;
}
QXYSeriesPrivate::QXYSeriesPrivate() {}
QXYSeriesPrivate::QXYSeriesPrivate(QAbstractSeries::SeriesType type)
: QAbstractSeriesPrivate(type)
{}
void QXYSeriesPrivate::setPointSelected(qsizetype index, bool selected, bool &callSignal)
{

View File

@ -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;