diff --git a/source/app/ui/qml/Loading/ImportAttributesDialog.qml b/source/app/ui/qml/Loading/ImportAttributesDialog.qml index be9565fd0..5caf008eb 100644 --- a/source/app/ui/qml/Loading/ImportAttributesDialog.qml +++ b/source/app/ui/qml/Loading/ImportAttributesDialog.qml @@ -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; } } @@ -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); } diff --git a/source/shared/loading/qmltabulardataparser.cpp b/source/shared/loading/qmltabulardataparser.cpp index b5d21fcbb..c127b49e8 100644 --- a/source/shared/loading/qmltabulardataparser.cpp +++ b/source/shared/loading/qmltabulardataparser.cpp @@ -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; @@ -53,7 +59,9 @@ 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; @@ -61,30 +69,33 @@ QmlTabularDataHeaderModel::QmlTabularDataHeaderModel(const QmlTabularDataParser* if(!skip.isEmpty() && skip.contains(value)) continue; - _columnIndices.emplace_back(column); + _indices.emplace_back(index); } } int QmlTabularDataHeaderModel::rowCount(const QModelIndex&) const { - return static_cast(_columnIndices.size()); + return static_cast(_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(index.row()); + auto indicesIndex = static_cast(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(columnIndex)}; + if(role == Roles::Index) + return {static_cast(index)}; return {}; } @@ -93,19 +104,19 @@ QHash 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 {}; @@ -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) @@ -168,7 +180,7 @@ bool QmlTabularDataParser::parse(const QUrl& fileUrl) } _dataPtr = std::make_shared(std::move(parser.tabularData())); - updateColumnTypes(); + updateTypes(); emit dataChanged(); return true; @@ -279,7 +291,19 @@ QmlTabularDataHeaderModel* QmlTabularDataParser::rowHeaders(int _valueTypes, con auto valueTypes = static_cast(_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(_valueTypes); + + // Caller takes ownership (usually QML/JS) + return new QmlTabularDataHeaderModel(this, valueTypes, skip, HeaderModelType::Columns); } void QmlTabularDataParser::onDataLoaded() diff --git a/source/shared/loading/qmltabulardataparser.h b/source/shared/loading/qmltabulardataparser.h index c3ef7347b..c086c1c65 100644 --- a/source/shared/loading/qmltabulardataparser.h +++ b/source/shared/loading/qmltabulardataparser.h @@ -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 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 _columnIndices; + HeaderModelType _type = HeaderModelType::Rows; + std::vector _indices; }; class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual public Progressable @@ -84,6 +90,7 @@ class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual TabularDataModel _model; std::vector _columnTypeIdentities; + std::vector _rowTypeIdentities; int _progress = -1; std::atomic _cancellableParser = nullptr; @@ -91,7 +98,7 @@ class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual bool _failed = false; QString _failureReason; - void updateColumnTypes(); + void updateTypes(); public: struct MatrixTypeResult @@ -120,6 +127,10 @@ class QmlTabularDataParser : public QObject, virtual public Cancellable, virtual int _valueTypes = static_cast(ValueType::All), const QStringList& skip = {}) const; + Q_INVOKABLE QmlTabularDataHeaderModel* columnHeaders( + int _valueTypes = static_cast(ValueType::All), + const QStringList& skip = {}) const; + bool busy() const { return _dataParserWatcher.isRunning(); } QAbstractTableModel* tableModel() { return &_model; }