qtdoc/examples/demos/graphs_csv/datamodel.cpp

117 lines
3.5 KiB
C++

// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "datamodel.h"
#include "internal/common.hpp"
#include <csv.hpp>
#include <QFileInfo>
#include <QtQml>
#include <qlogging.h>
#include <sstream>
#include <charconv>
#include <string_view>
DataModel::DataModel(QObject *parent) : QAbstractTableModel(parent) { }
DataModel::~DataModel() { }
int DataModel::columnCount(const QModelIndex &parent) const
{
return m_csvData.count() ? m_csvData.at(0).count() : 0;
}
QVariant DataModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole) {
if (index.row() < rowCount() && index.column() < columnCount())
return m_csvData.at(index.row()).at(index.column());
}
return QVariant();
}
QVariant DataModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
if (section < columnCount())
return m_csvData.at(0).at(section);
}
else if (orientation == Qt::Vertical) {
if (section < rowCount() && columnCount() > 0)
return m_csvData.at(section).at(0);
}
}
return QVariant();
}
QHash<int, QByteArray> DataModel::roleNames() const
{
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[CustomRoles::Background] = "background";
return roles;
}
static int tryConvertToInt(std::string_view team, std::string_view fieldName, std::string field)
{
int value = -1;
auto [ptr, ec] = std::from_chars(field.data(), field.data() + field.size(), value);
if (value == -1)
qWarning("%s: error in %s field", team.data(), fieldName.data());
return value;
};
void DataModel::readCsv(const QUrl &csvFile)
{
QAbstractItemModel::beginResetModel();
const auto context = qmlContext(this);
const auto resolvedUrl = context ? context->resolvedUrl(csvFile) : csvFile;
QFile file(QQmlFile::urlToLocalFileOrQrc(resolvedUrl));
if (!file.open(QIODeviceBase::ReadOnly)) {
qWarning("Could not open %s for reading", qUtf8Printable(csvFile.toString()));
return;
}
m_csvData.clear();
std::stringstream ss(file.readAll().toStdString());
csv::CSVReader reader(ss);
auto headers = reader.get_col_names();
QList<QVariant> headersList;
headersList.resize(headers.size());
auto hIt = headersList.begin();
auto it = headers.begin();
while (it != headers.end()) {
*hIt = QString::fromStdString(*it);
++hIt;
++it;
}
if (headersList.count() > 0)
m_csvData.push_back(headersList);
for (const csv::CSVRow &csvRow : reader) {
csv::CSVField teamField = csvRow[headers.at(0)];
csv::CSVField goldField = csvRow[headers.at(1)];
csv::CSVField silverField = csvRow[headers.at(2)];
csv::CSVField bronzeField = csvRow[headers.at(3)];
csv::CSVField totalField = csvRow[headers.at(4)];
QList<QVariant> row;
row.resize(5);
auto team = teamField.get();
row[0] = QString::fromStdString(teamField.get());
row[1] = tryConvertToInt(team, headers.at(1), goldField.get());
row[2] = tryConvertToInt(team, headers.at(2), silverField.get());
row[3] = tryConvertToInt(team, headers.at(3), bronzeField.get());
row[4] = tryConvertToInt(team, headers.at(4), totalField.get());
m_csvData.push_back(row);
}
QAbstractItemModel::endResetModel();
}