widgetgraphgallery example: Use QRangeModel for the rainfall data

QRangeModel can be used conveniently read tables from
range-based data. Replace the previously existing mappers by a
QItemModelBarDataProxy based on QRangeModel.

Pick-to: 6.10
Change-Id: Ic6b1ce66a41d8edf5ae080ea9974b44d45a22c4e
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Friedemann Kleint 2025-05-06 15:19:16 +02:00 committed by Volker Hilsheimer
parent 32120c2030
commit 467bcff49d
14 changed files with 110 additions and 593 deletions

View File

@ -32,9 +32,6 @@ qt_add_executable(widgetgraphgallery
graphmodifier.cpp graphmodifier.h
rainfalldata.cpp rainfalldata.h
variantbardatamapping.cpp variantbardatamapping.h
variantbardataproxy.cpp variantbardataproxy.h
variantdataset.cpp variantdataset.h
scattergraph.cpp scattergraph.h
scattergraphwidget.cpp scattergraphwidget.h

View File

@ -201,9 +201,9 @@ void BarGraph::initialize()
auto *modeGroup = new QButtonGroup(m_container);
auto *modeWeather = new QRadioButton(u"Temperature Data"_s, m_container);
modeWeather->setChecked(true);
auto *modeCustomProxy = new QRadioButton(u"Custom Proxy Data"_s, m_container);
auto *modelProxy = new QRadioButton(u"Model Proxy Data"_s, m_container);
modeGroup->addButton(modeWeather);
modeGroup->addButton(modeCustomProxy);
modeGroup->addButton(modelProxy);
//! [adding the slider]
vLayout->addWidget(new QLabel(u"Rotate horizontally"_s));
@ -238,7 +238,7 @@ void BarGraph::initialize()
vLayout->addWidget(new QLabel(u"Axis label rotation"_s));
vLayout->addWidget(axisLabelRotationSlider, 0, Qt::AlignTop);
vLayout->addWidget(modeWeather, 0, Qt::AlignTop);
vLayout->addWidget(modeCustomProxy, 1, Qt::AlignTop);
vLayout->addWidget(modelProxy, 1, Qt::AlignTop);
// Raise the graph to the top of the widget stack, to hide UI if resized smaller
m_quickWidget->raise();
@ -365,10 +365,10 @@ void BarGraph::initialize()
&QRadioButton::toggled,
m_modifier,
&GraphModifier::setDataModeToWeather);
QObject::connect(modeCustomProxy,
QObject::connect(modelProxy,
&QRadioButton::toggled,
m_modifier,
&GraphModifier::setDataModeToCustom);
&GraphModifier::setDataModeToModel);
QObject::connect(modeWeather, &QRadioButton::toggled, seriesCheckBox, &QCheckBox::setEnabled);
QObject::connect(modeWeather, &QRadioButton::toggled, rangeList, &QComboBox::setEnabled);
QObject::connect(modeWeather,

View File

@ -201,98 +201,30 @@
\snippet 3d/widgetgraphgallery/graphmodifier.cpp center camera
\section2 Custom Proxy for Data
\section2 Model Proxy for Data
When you toggle \uicontrol {Custom Proxy Data} data mode on, the graph in
the example uses a custom dataset and the corresponding proxy.
Define a simple flexible data set, \c{VariantDataSet}, where each data item
is a variant list. Each item can have multiple values, identified by their
index in the list. In this case, the data set is designed to store monthly
rainfall data. The value in index zero represents the year, the value in
index one represents the month, and the value in index two represents the
amount of rainfall in that month.
The custom proxy is similar to itemmodel-based proxies,
QItemModelBarDataProxy, provided by QtGraphs, and it requires mapping to
interpret the data.
\section3 Implement a data set
Define the data items as QVariantList objects. Add functionality for
clearing the data set and querying a reference to the data contained in the
set. Also, add signals to be emitted when data is added or the set is cleared:
\snippet 3d/widgetgraphgallery/variantdataset.h 0
\dots 0
\codeline
\snippet 3d/widgetgraphgallery/variantdataset.h 1
\section3 Implement a data proxy
Derive the \c VariantBarDataProxy class from QBarDataProxy and implement a
simple API of getters and setters for the data set and the mapping:
\snippet 3d/widgetgraphgallery/variantbardataproxy.h 0
\dots 0
\codeline
\snippet 3d/widgetgraphgallery/variantbardataproxy.h 1
The proxy listens for changes in the data set and the mapping, resolving the
data set if any changes are detected. While this implementation may not be
particularly efficient, as any change triggers the re-resolving of the
entire data set, it is not a concern for this example.
In the \c resolveDataSet() method, sort the variant data values into rows
and columns based on the mapping. This is very similar to how the
QItemModelBarDataProxy handles mapping, except you use list indexes instead
of item model roles here. Once the values are sorted, generate a
\c QBarDataArray out of them, and call the \c resetArray() method in the
parent class:
\snippet 3d/widgetgraphgallery/variantbardataproxy.cpp 0
\section3 Implement a data mapper
Store the mapping information between \c VariantDataSet data item indexes
and rows, columns, and values of \c QBarDataArray in
\c VariantBarDataMapping. It contains the lists of rows and columns to be
included in the resolved data:
\snippet 3d/widgetgraphgallery/variantbardatamapping.h 0
\dots 0
\codeline
\snippet 3d/widgetgraphgallery/variantbardatamapping.h 1
\dots 0
\codeline
\snippet 3d/widgetgraphgallery/variantbardatamapping.h 2
\dots 0
\codeline
\snippet 3d/widgetgraphgallery/variantbardatamapping.h 3
The primary way to use a \c VariantBarDataMapping object is to give the
mappings in the constructor, though you can also use the \c remap() method
to set them later, either individually or all together. Emit a signal if
mapping changes. The outcome is a simplified version of the mapping
functionality of QItemModelBarDataProxy, adapted to work with variant lists
instead of item models.
When you toggle \uicontrol {Model Proxy Data} data mode on, the graph in
the example uses an item model based dataset and the corresponding proxy.
\section3 RainfallData
Class \c RainfallData sets up a QItemModelBarDataProxy along with the series
and axes.
\list 1
\li Handle the setup of QBar3DSeries with the custom proxy in the \c RainfallData class:
\li We use a \c{std::array<double, 12>} to store the values of a year
indexed by month. The static \c readData() helper function reads
the data, returning a QList of them indexed by year:
\snippet 3d/widgetgraphgallery/rainfalldata.cpp 1
\dots
\li The QList represents a two dimensional array indexed by year and month,
respectively. From this, we populate a QRangeModel and pass it to
a QItemModelBarDataProxy() in the \c RainfallData class:
\snippet 3d/widgetgraphgallery/rainfalldata.cpp 0
\li Populate the variant data set in the \c addDataSet() method:
\snippet 3d/widgetgraphgallery/rainfalldata.cpp 1
\dots
\li Use the custom proxy functions to add the data set to the series and set the mapping:
\snippet 3d/widgetgraphgallery/rainfalldata.cpp 2
\li Finally, add a function for getting the created series for displaying:
\snippet 3d/widgetgraphgallery/rainfalldata.h 0

View File

@ -377,7 +377,7 @@ void GraphModifier::setDataModeToWeather(bool enabled)
changeDataMode(false);
}
void GraphModifier::setDataModeToCustom(bool enabled)
void GraphModifier::setDataModeToModel(bool enabled)
{
if (enabled)
changeDataMode(true);
@ -432,11 +432,11 @@ void GraphModifier::setReverseValueAxis(int enabled)
m_graph->valueAxis()->setReversed(enabled);
}
void GraphModifier::changeDataMode(bool customData)
void GraphModifier::changeDataMode(bool modelData)
{
int enabled = false;
// Change between weather data and data from custom proxy
if (customData) {
// Change between weather data and data from model proxy
if (modelData) {
m_graph->removeSeries(m_primarySeries);
m_graph->removeSeries(m_secondarySeries);
m_graph->addSeries(m_customData->customSeries());

View File

@ -32,7 +32,7 @@ public:
void setSmoothBars(int smooth);
void setSeriesVisibility(int visible);
void setReverseValueAxis(int enabled);
void changeDataMode(bool customData);
void changeDataMode(bool modelData);
public Q_SLOTS:
void changeRange(int range);
@ -46,7 +46,7 @@ public Q_SLOTS:
void setAxisTitleFixed(bool enabled);
void zoomToSelectedBar();
void setDataModeToWeather(bool enabled);
void setDataModeToCustom(bool enabled);
void setDataModeToModel(bool enabled);
Q_SIGNALS:
void shadowQualityChanged(int quality);

View File

@ -4,24 +4,88 @@
#include "rainfalldata.h"
#include <QtCore/qfile.h>
#include <QtCore/qrangemodel.h>
#include <QtCore/qlist.h>
#include <QtCore/qtextstream.h>
#include <QtGraphs/q3dscene.h>
#include <QtGraphs/qgraphstheme.h>
#include <QtGraphs/qbar3dseries.h>
#include <QtGraphs/qcategory3daxis.h>
#include <QtGraphs/qgraphstheme.h>
#include <QtGraphs/qitemmodelbardataproxy.h>
#include <QtGraphs/qvalue3daxis.h>
#include <array>
using namespace Qt::StringLiterals;
//! [1]
using YearlyData = std::array<double, 12>;
using ModelData = QList<YearlyData>;
static ModelData readData(const QString &fileName, int *firstYear)
{
ModelData result;
*firstYear = -1;
// Read data from a data file into the data item list
QFile dataFile(fileName);
if (!dataFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open data file:" << dataFile.fileName() << dataFile.errorString();
return result;
}
QTextStream stream(&dataFile);
int lastYear = -1;
while (!stream.atEnd()) {
QString line = stream.readLine();
if (line.startsWith(u'#')) // Ignore comments
continue;
const auto strList = QStringView{line}.split(',', Qt::SkipEmptyParts);
// Each line has three data items: Year, month, and rainfall value
if (strList.size() < 3) {
qWarning() << "Invalid row read from data:" << line;
continue;
}
// Store year and month as int, and rainfall value as double
bool yearOk{};
bool monthOk{};
bool valueOk{};
const int year = strList.at(0).trimmed().toInt(&yearOk);
const int month = strList.at(1).trimmed().toInt(&monthOk);
const double value = strList.at(2).trimmed().toDouble(&valueOk);
if (!yearOk || !monthOk || month < 1 || month > 12 || !valueOk) {
qWarning() << "Invalid row values:" << line;
continue;
}
if (year != lastYear) {
if (lastYear == -1) {
*firstYear = year;
} else if (year != lastYear + 1) {
qWarning() << "Non-consecutive years" << year << lastYear;
return {};
}
lastYear = year;
result.emplace_back(YearlyData{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
}
result.back()[month - 1] = value;
}
return result;
}
//! [1]
RainfallData::RainfallData()
{
// In data file the months are in numeric format, so create custom list
for (int i = 1; i <= 12; ++i)
m_numericMonths << QString::number(i);
updateYearsList(2010, 2022);
// Create proxy and series
//! [0]
m_proxy = new VariantBarDataProxy;
int firstYear{};
auto data = readData(":/data/raindata.txt"_L1, &firstYear);
Q_ASSERT(!data.isEmpty());
updateYearsList(firstYear, firstYear + int(data.size()) - 1);
auto *model = new QRangeModel(data, this);
m_proxy = new QItemModelBarDataProxy(model);
m_proxy->setUseModelCategories(true);
m_series = new QBar3DSeries(m_proxy);
//! [0]
@ -57,14 +121,9 @@ RainfallData::RainfallData()
m_rowAxis->setTitleVisible(true);
m_colAxis->setTitleVisible(true);
m_valueAxis->setTitleVisible(true);
addDataSet();
}
RainfallData::~RainfallData()
{
delete m_mapping;
}
RainfallData::~RainfallData() = default;
void RainfallData::updateYearsList(int start, int end)
{
@ -73,48 +132,3 @@ void RainfallData::updateYearsList(int start, int end)
for (int i = start; i <= end; ++i)
m_years << QString::number(i);
}
//! [1]
void RainfallData::addDataSet()
{
// Create a new variant data set and data item list
m_dataSet = new VariantDataSet;
auto *itemList = new VariantDataItemList;
// Read data from a data file into the data item list
QFile dataFile(":/data/raindata.txt");
if (dataFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream stream(&dataFile);
while (!stream.atEnd()) {
QString line = stream.readLine();
if (line.startsWith('#')) // Ignore comments
continue;
const auto strList = QStringView{line}.split(',', Qt::SkipEmptyParts);
// Each line has three data items: Year, month, and rainfall value
if (strList.size() < 3) {
qWarning() << "Invalid row read from data:" << line;
continue;
}
// Store year and month as strings, and rainfall value as double
// into a variant data item and add the item to the item list.
auto *newItem = new VariantDataItem;
for (int i = 0; i < 2; ++i)
newItem->append(strList.at(i).trimmed().toString());
newItem->append(strList.at(2).trimmed().toDouble());
itemList->append(newItem);
}
} else {
qWarning() << "Unable to open data file:" << dataFile.fileName();
}
//! [1]
//! [2]
// Add items to the data set and set it to the proxy
m_dataSet->addItems(itemList);
m_proxy->setDataSet(m_dataSet);
// Create new mapping for the data and set it to the proxy
m_mapping = new VariantBarDataMapping(0, 1, 2, m_years, m_numericMonths);
m_proxy->setMapping(m_mapping);
//! [2]
}

View File

@ -4,9 +4,14 @@
#ifndef RAINFALLDATA_H
#define RAINFALLDATA_H
#include "variantbardataproxy.h"
#include <QtGraphs/qcategory3daxis.h>
#include <QtGraphs/qvalue3daxis.h>
#include <QtCore/qobject.h>
#include <QtCore/qstringlist.h>
QT_FORWARD_DECLARE_CLASS(QBar3DSeries)
QT_FORWARD_DECLARE_CLASS(QItemModelBarDataProxy)
QT_FORWARD_DECLARE_CLASS(QBar3DSeries)
QT_FORWARD_DECLARE_CLASS(QValue3DAxis)
QT_FORWARD_DECLARE_CLASS(QCategory3DAxis)
class RainfallData : public QObject
{
@ -17,8 +22,6 @@ public:
explicit RainfallData();
~RainfallData() override;
void addDataSet();
//! [0]
QBar3DSeries *customSeries() { return m_series; }
//! [0]
@ -29,11 +32,9 @@ public:
private:
void updateYearsList(int start, int end);
QStringList m_years;
QStringList m_numericMonths;
VariantBarDataProxy *m_proxy;
VariantBarDataMapping *m_mapping;
VariantDataSet *m_dataSet;
QItemModelBarDataProxy *m_proxy;
QBar3DSeries *m_series;
QValue3DAxis *m_valueAxis;
QCategory3DAxis *m_rowAxis;

View File

@ -1,89 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "variantbardatamapping.h"
VariantBarDataMapping::VariantBarDataMapping(int rowIndex,
int columnIndex,
int valueIndex,
const QStringList &rowCategories,
const QStringList &columnCategories)
: QObject(nullptr)
{
m_rowIndex = rowIndex;
m_columnIndex = columnIndex;
m_valueIndex = valueIndex;
m_rowCategories = rowCategories;
m_columnCategories = columnCategories;
}
VariantBarDataMapping::~VariantBarDataMapping() = default;
void VariantBarDataMapping::setRowIndex(int index)
{
m_rowIndex = index;
emit mappingChanged();
}
int VariantBarDataMapping::rowIndex() const
{
return m_rowIndex;
}
void VariantBarDataMapping::setColumnIndex(int index)
{
m_columnIndex = index;
emit mappingChanged();
}
int VariantBarDataMapping::columnIndex() const
{
return m_columnIndex;
}
void VariantBarDataMapping::setValueIndex(int index)
{
m_valueIndex = index;
emit mappingChanged();
}
int VariantBarDataMapping::valueIndex() const
{
return m_valueIndex;
}
void VariantBarDataMapping::setRowCategories(const QStringList &categories)
{
m_rowCategories = categories;
emit mappingChanged();
}
const QStringList &VariantBarDataMapping::rowCategories() const
{
return m_rowCategories;
}
void VariantBarDataMapping::setColumnCategories(const QStringList &categories)
{
m_columnCategories = categories;
emit mappingChanged();
}
const QStringList &VariantBarDataMapping::columnCategories() const
{
return m_columnCategories;
}
void VariantBarDataMapping::remap(int rowIndex,
int columnIndex,
int valueIndex,
const QStringList &rowCategories,
const QStringList &columnCategories)
{
m_rowIndex = rowIndex;
m_columnIndex = columnIndex;
m_valueIndex = valueIndex;
m_rowCategories = rowCategories;
m_columnCategories = columnCategories;
emit mappingChanged();
}

View File

@ -1,73 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef VARIANTBARDATAMAPPING_H
#define VARIANTBARDATAMAPPING_H
#include <QtCore/qobject.h>
#include <QtCore/qstringlist.h>
class VariantBarDataMapping : public QObject
{
Q_OBJECT
//! [0]
Q_PROPERTY(int rowIndex READ rowIndex WRITE setRowIndex NOTIFY rowIndexChanged)
Q_PROPERTY(int columnIndex READ columnIndex WRITE setColumnIndex NOTIFY columnIndexChanged)
Q_PROPERTY(int valueIndex READ valueIndex WRITE setValueIndex NOTIFY valueIndexChanged)
Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories NOTIFY
rowCategoriesChanged)
Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories NOTIFY
columnCategoriesChanged)
//! [0]
public:
//! [1]
explicit VariantBarDataMapping(int rowIndex,
int columnIndex,
int valueIndex,
const QStringList &rowCategories,
const QStringList &columnCategories);
//! [1]
~VariantBarDataMapping() override;
void setRowIndex(int index);
int rowIndex() const;
void setColumnIndex(int index);
int columnIndex() const;
void setValueIndex(int index);
int valueIndex() const;
void setRowCategories(const QStringList &categories);
const QStringList &rowCategories() const;
void setColumnCategories(const QStringList &categories);
const QStringList &columnCategories() const;
//! [2]
void remap(int rowIndex,
int columnIndex,
int valueIndex,
const QStringList &rowCategories,
const QStringList &columnCategories);
//! [2]
Q_SIGNALS:
void rowIndexChanged();
void columnIndexChanged();
void valueIndexChanged();
void rowCategoriesChanged();
void columnCategoriesChanged();
//! [3]
void mappingChanged();
//! [3]
private:
// Indexes of the mapped items in the VariantDataItem
int m_rowIndex = 0;
int m_columnIndex = 1;
int m_valueIndex = 2;
// For row/column items, sort items into these categories. Other categories
// are ignored.
QStringList m_rowCategories = {};
QStringList m_columnCategories = {};
};
#endif

View File

@ -1,123 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "variantbardataproxy.h"
VariantBarDataProxy::VariantBarDataProxy() = default;
VariantBarDataProxy::~VariantBarDataProxy()
{
delete m_dataSet;
}
void VariantBarDataProxy::setDataSet(VariantDataSet *newSet)
{
if (!m_dataSet.isNull())
QObject::disconnect(m_dataSet.data(), nullptr, this, nullptr);
m_dataSet = newSet;
if (!m_dataSet.isNull()) {
QObject::connect(m_dataSet.data(),
&VariantDataSet::itemsAdded,
this,
&VariantBarDataProxy::handleItemsAdded);
QObject::connect(m_dataSet.data(),
&VariantDataSet::dataCleared,
this,
&VariantBarDataProxy::handleDataCleared);
}
resolveDataSet();
}
VariantDataSet *VariantBarDataProxy::dataSet()
{
return m_dataSet.data();
}
void VariantBarDataProxy::setMapping(VariantBarDataMapping *mapping)
{
if (!m_mapping.isNull()) {
QObject::disconnect(m_mapping.data(),
&VariantBarDataMapping::mappingChanged,
this,
&VariantBarDataProxy::handleMappingChanged);
}
m_mapping = mapping;
if (!m_mapping.isNull()) {
QObject::connect(m_mapping.data(),
&VariantBarDataMapping::mappingChanged,
this,
&VariantBarDataProxy::handleMappingChanged);
}
resolveDataSet();
}
VariantBarDataMapping *VariantBarDataProxy::mapping()
{
return m_mapping.data();
}
void VariantBarDataProxy::handleItemsAdded(int index, int count)
{
Q_UNUSED(index);
Q_UNUSED(count);
// Resolve new items
resolveDataSet();
}
void VariantBarDataProxy::handleDataCleared()
{
// Data cleared, reset array
resetArray();
}
void VariantBarDataProxy::handleMappingChanged()
{
resolveDataSet();
}
// Resolve entire dataset into QBarDataArray.
//! [0]
void VariantBarDataProxy::resolveDataSet()
{
// If we have no data or mapping, or the categories are not defined, simply
// clear the array
if (m_dataSet.isNull() || m_mapping.isNull() || !m_mapping->rowCategories().size()
|| !m_mapping->columnCategories().size()) {
resetArray();
return;
}
const VariantDataItemList &itemList = m_dataSet->itemList();
int rowIndex = m_mapping->rowIndex();
int columnIndex = m_mapping->columnIndex();
int valueIndex = m_mapping->valueIndex();
const QStringList &rowList = m_mapping->rowCategories();
const QStringList &columnList = m_mapping->columnCategories();
// Sort values into rows and columns
using ColumnValueMap = QHash<QString, float>;
QHash<QString, ColumnValueMap> itemValueMap;
for (const VariantDataItem *item : itemList) {
itemValueMap[item->at(rowIndex).toString()][item->at(columnIndex).toString()]
= item->at(valueIndex).toReal();
}
// Create a new data array in format the parent class understands
QBarDataArray newProxyArray;
for (const QString &rowKey : rowList) {
QBarDataRow newProxyRow(columnList.size());
for (qsizetype i = 0; i < columnList.size(); ++i)
newProxyRow[i].setValue(itemValueMap[rowKey][columnList.at(i)]);
newProxyArray.append(newProxyRow);
}
// Finally, reset the data array in the parent class
resetArray(newProxyArray);
}
//! [0]

View File

@ -1,50 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef VARIANTBARDATAPROXY_H
#define VARIANTBARDATAPROXY_H
#include <QtCore/qpointer.h>
#include <QtGraphs/qbardataproxy.h>
#include "variantbardatamapping.h"
#include "variantdataset.h"
//! [0]
class VariantBarDataProxy : public QBarDataProxy
//! [0]
{
Q_OBJECT
public:
explicit VariantBarDataProxy();
~VariantBarDataProxy() override;
//! [1]
// Doesn't gain ownership of the dataset, but does connect to it to listen for
// data changes.
void setDataSet(VariantDataSet *newSet);
VariantDataSet *dataSet();
// Map key (row, column, value) to value index in data item (VariantItem).
// Doesn't gain ownership of mapping, but does connect to it to listen for
// mapping changes. Modifying mapping that is set to proxy will trigger
// dataset re-resolving.
void setMapping(VariantBarDataMapping *mapping);
VariantBarDataMapping *mapping();
//! [1]
public Q_SLOTS:
void handleItemsAdded(int index, int count);
void handleDataCleared();
void handleMappingChanged();
private:
void resolveDataSet();
QPointer<VariantDataSet> m_dataSet;
QPointer<VariantBarDataMapping> m_mapping;
Q_DISABLE_COPY(VariantBarDataProxy)
};
#endif

View File

@ -1,45 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "variantdataset.h"
VariantDataSet::VariantDataSet() = default;
VariantDataSet::~VariantDataSet()
{
clear();
}
void VariantDataSet::clear()
{
for (VariantDataItem *item : m_variantData) {
item->clear();
delete item;
}
m_variantData.clear();
emit dataCleared();
}
int VariantDataSet::addItem(VariantDataItem *item)
{
m_variantData.append(item);
int addIndex = m_variantData.size();
emit itemsAdded(addIndex, 1);
return addIndex;
}
int VariantDataSet::addItems(VariantDataItemList *itemList)
{
int newCount = itemList->size();
int addIndex = m_variantData.size();
m_variantData.append(*itemList);
delete itemList;
emit itemsAdded(addIndex, newCount);
return addIndex;
}
const VariantDataItemList &VariantDataSet::itemList() const
{
return m_variantData;
}

View File

@ -1,41 +0,0 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef VARIANTDATASET_H
#define VARIANTDATASET_H
#include <QtCore/qvariantlist.h>
//! [0]
using VariantDataItem = QVariantList;
using VariantDataItemList = QList<VariantDataItem *>;
//! [0]
class VariantDataSet : public QObject
{
Q_OBJECT
public:
explicit VariantDataSet();
~VariantDataSet();
//! [1]
void clear();
int addItem(VariantDataItem *item);
int addItems(VariantDataItemList *itemList);
const VariantDataItemList &itemList() const;
Q_SIGNALS:
void itemsAdded(int index, int count);
void dataCleared();
//! [1]
private:
VariantDataItemList m_variantData;
Q_DISABLE_COPY(VariantDataSet)
};
#endif

View File

@ -15,9 +15,6 @@ SOURCES += main.cpp \
bargraph.cpp \
graphmodifier.cpp \
rainfalldata.cpp \
variantdataset.cpp \
variantbardataproxy.cpp \
variantbardatamapping.cpp \
scattergraph.cpp \
scatterdatamodifier.cpp \
surfacegraph.cpp \
@ -31,9 +28,6 @@ HEADERS += \
bargraph.h \
graphmodifier.h \
rainfalldata.h \
variantdataset.h \
variantbardataproxy.h \
variantbardatamapping.h \
scattergraph.h \
scatterdatamodifier.h \
surfacegraph.h \