Skip to content

Commit

Permalink
Make QmlTabularDataHeaderModel handle column headers in addition to r…
Browse files Browse the repository at this point in the history
…ow headers
  • Loading branch information
timangus committed Aug 31, 2023
1 parent 0079023 commit 7eee124
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 34 deletions.
6 changes: 3 additions & 3 deletions source/app/ui/qml/Loading/ImportAttributesDialog.qml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Window
if(modelIndex.valid)
keyAttributeList.select(modelIndex);

keyHeaderComboBox.currentIndex = keyHeaderComboBox.model.indexOf(result.column).row;
keyHeaderComboBox.currentIndex = keyHeaderComboBox.model.modelIndexOf(result.column).row;
}
}

Expand Down Expand Up @@ -533,13 +533,13 @@ Window
}

let keyAttributeName = keyAttributeList.selectedValue;
let keyColumnIndex = keyHeaderComboBox.model.columnIndexFor(
let keyColumnIndex = keyHeaderComboBox.model.indexFor(
keyHeaderComboBox.model.index(keyHeaderComboBox.currentIndex, 0));

let attributeColumnIndices = [];
for(let selectedIndex of headersList.selectedIndices)
{
let columnIndex = headersList.model.columnIndexFor(
let columnIndex = headersList.model.indexFor(
headersList.model.index(selectedIndex, 0));
attributeColumnIndices.push(columnIndex);
}
Expand Down
72 changes: 48 additions & 24 deletions source/shared/loading/qmltabulardataparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@
using namespace Qt::Literals::StringLiterals;

QmlTabularDataHeaderModel::QmlTabularDataHeaderModel(const QmlTabularDataParser* parser,
ValueType valueTypes, const QStringList& skip) :
_parser(parser)
ValueType valueTypes, const QStringList& skip, HeaderModelType headerModelType) :
_parser(parser), _type(headerModelType)
{
_columnIndices.reserve(_parser->_dataPtr->numColumns());
size_t num = _type == HeaderModelType::Rows ?
_parser->_dataPtr->numColumns() :
_parser->_dataPtr->numRows();

for(size_t column = 0; column < _parser->_dataPtr->numColumns(); column++)
_indices.reserve(num);

for(size_t index = 0; index < num; index++)
{
auto type = _parser->_columnTypeIdentities.at(column).type();
auto type = _type == HeaderModelType::Rows ?
_parser->_columnTypeIdentities.at(index).type() :
_parser->_rowTypeIdentities.at(index).type();

if(type == TypeIdentity::Type::String && !(valueTypes & ValueType::String))
continue;
Expand All @@ -53,38 +59,43 @@ QmlTabularDataHeaderModel::QmlTabularDataHeaderModel(const QmlTabularDataParser*
if(type == TypeIdentity::Type::Float && !(valueTypes & ValueType::Float))
continue;

const auto& value = _parser->_dataPtr->valueAt(column, 0);
const auto& value = _type == HeaderModelType::Rows ?
_parser->_dataPtr->valueAt(index, 0) :
_parser->_dataPtr->valueAt(0, index);

if(value.isEmpty())
continue;

if(!skip.isEmpty() && skip.contains(value))
continue;

_columnIndices.emplace_back(column);
_indices.emplace_back(index);
}
}

int QmlTabularDataHeaderModel::rowCount(const QModelIndex&) const
{
return static_cast<int>(_columnIndices.size());
return static_cast<int>(_indices.size());
}

QVariant QmlTabularDataHeaderModel::data(const QModelIndex& index, int role) const
QVariant QmlTabularDataHeaderModel::data(const QModelIndex& modelIndex, int role) const
{
// Rows in the model correspond to columns in the data table
auto columnIndicesIndex = static_cast<size_t>(index.row());
auto indicesIndex = static_cast<size_t>(modelIndex.row());

if(columnIndicesIndex >= _columnIndices.size())
if(indicesIndex >= _indices.size())
return {};

auto columnIndex = _columnIndices.at(columnIndicesIndex);
auto index = _indices.at(indicesIndex);

if(role == Qt::DisplayRole)
return _parser->_dataPtr->valueAt(columnIndex, 0);
{
return _type == HeaderModelType::Rows ?
_parser->_dataPtr->valueAt(index, 0) :
_parser->_dataPtr->valueAt(0, index);
}

if(role == Roles::ColumnIndex)
return {static_cast<int>(columnIndex)};
if(role == Roles::Index)
return {static_cast<int>(index)};

return {};
}
Expand All @@ -93,19 +104,19 @@ QHash<int, QByteArray> QmlTabularDataHeaderModel::roleNames() const
{
auto names = QAbstractItemModel::roleNames();

names[Roles::ColumnIndex] = "columnIndex";
names[Roles::Index] = "indexRole";

return names;
}

int QmlTabularDataHeaderModel::columnIndexFor(const QModelIndex& index) const
int QmlTabularDataHeaderModel::indexFor(const QModelIndex& modelIndex) const
{
return data(index, Roles::ColumnIndex).toInt();
return data(modelIndex, Roles::Index).toInt();
}

QModelIndex QmlTabularDataHeaderModel::indexOf(int columnIndex) const
QModelIndex QmlTabularDataHeaderModel::modelIndexOf(int roleIndex) const
{
auto row = u::indexOf(_columnIndices, columnIndex);
auto row = u::indexOf(_indices, roleIndex);

if(row < 0)
return {};
Expand Down Expand Up @@ -136,9 +147,10 @@ QmlTabularDataParser::~QmlTabularDataParser() // NOLINT modernize-use-equals-def
_dataParserWatcher.waitForFinished();
}

void QmlTabularDataParser::updateColumnTypes()
void QmlTabularDataParser::updateTypes()
{
_columnTypeIdentities = _dataPtr->columnTypeIdentities(this);
_rowTypeIdentities = _dataPtr->rowTypeIdentities(this);
}

bool QmlTabularDataParser::parse(const QUrl& fileUrl)
Expand Down Expand Up @@ -168,7 +180,7 @@ bool QmlTabularDataParser::parse(const QUrl& fileUrl)
}

_dataPtr = std::make_shared<TabularData>(std::move(parser.tabularData()));
updateColumnTypes();
updateTypes();
emit dataChanged();

return true;
Expand Down Expand Up @@ -279,7 +291,19 @@ QmlTabularDataHeaderModel* QmlTabularDataParser::rowHeaders(int _valueTypes, con
auto valueTypes = static_cast<ValueType>(_valueTypes);

// Caller takes ownership (usually QML/JS)
return new QmlTabularDataHeaderModel(this, valueTypes, skip);
return new QmlTabularDataHeaderModel(this, valueTypes, skip, HeaderModelType::Rows);
}

QmlTabularDataHeaderModel* QmlTabularDataParser::columnHeaders(int _valueTypes, const QStringList& skip) const
{
Q_ASSERT(_dataPtr != nullptr);
if(_dataPtr == nullptr)
return {};

auto valueTypes = static_cast<ValueType>(_valueTypes);

// Caller takes ownership (usually QML/JS)
return new QmlTabularDataHeaderModel(this, valueTypes, skip, HeaderModelType::Columns);
}

void QmlTabularDataParser::onDataLoaded()
Expand Down
25 changes: 18 additions & 7 deletions source/shared/loading/qmltabulardataparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,35 @@
class QmlTabularDataParser;
class QAbstractTableModel;

DEFINE_QML_ENUM(
Q_GADGET, HeaderModelType,
Rows, Columns);

class QmlTabularDataHeaderModel : public QAbstractListModel
{
Q_OBJECT

public:
explicit QmlTabularDataHeaderModel(const QmlTabularDataParser* parser,
ValueType valueTypes = ValueType::All, const QStringList& skip = {});
ValueType valueTypes = ValueType::All, const QStringList& skip = {},
HeaderModelType headerModelType = HeaderModelType::Rows);

enum Roles
{
ColumnIndex = Qt::UserRole + 1,
Index = Qt::UserRole + 1,
};

int rowCount(const QModelIndex&) const override;
QVariant data(const QModelIndex& index, int role) const override;
QVariant data(const QModelIndex& modelIndex, int role) const override;
QHash<int, QByteArray> roleNames() const override;

Q_INVOKABLE int columnIndexFor(const QModelIndex& index) const;
Q_INVOKABLE QModelIndex indexOf(int columnIndex) const;
Q_INVOKABLE int indexFor(const QModelIndex& modelIndex) const;
Q_INVOKABLE QModelIndex modelIndexOf(int roleIndex) const;

private:
const QmlTabularDataParser* _parser = nullptr;
std::vector<size_t> _columnIndices;
HeaderModelType _type = HeaderModelType::Rows;
std::vector<size_t> _indices;
};

class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual public Progressable
Expand All @@ -84,14 +90,15 @@ class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual
TabularDataModel _model;

std::vector<TypeIdentity> _columnTypeIdentities;
std::vector<TypeIdentity> _rowTypeIdentities;

int _progress = -1;
std::atomic<Cancellable*> _cancellableParser = nullptr;
bool _complete = false;
bool _failed = false;
QString _failureReason;

void updateColumnTypes();
void updateTypes();

public:
struct MatrixTypeResult
Expand Down Expand Up @@ -120,6 +127,10 @@ class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual
int _valueTypes = static_cast<int>(ValueType::All),
const QStringList& skip = {}) const;

Q_INVOKABLE QmlTabularDataHeaderModel* columnHeaders(
int _valueTypes = static_cast<int>(ValueType::All),
const QStringList& skip = {}) const;

bool busy() const { return _dataParserWatcher.isRunning(); }

QAbstractTableModel* tableModel() { return &_model; }
Expand Down

0 comments on commit 7eee124

Please sign in to comment.