diff --git a/src/datasource/ModelSource.cpp b/src/datasource/ModelSource.cpp index ebc7945..75aa34e 100644 --- a/src/datasource/ModelSource.cpp +++ b/src/datasource/ModelSource.cpp @@ -1,196 +1,200 @@ /* * This file is part of KQuickCharts * SPDX-FileCopyrightText: 2019 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "ModelSource.h" #include ModelSource::ModelSource(QObject *parent) : ChartDataSource(parent) { connect(this, &ModelSource::modelChanged, this, &ModelSource::dataChanged); connect(this, &ModelSource::columnChanged, this, &ModelSource::dataChanged); connect(this, &ModelSource::roleChanged, this, &ModelSource::dataChanged); connect(this, &ModelSource::indexColumnsChanged, this, &ModelSource::dataChanged); } int ModelSource::role() const { + if (!m_model) { + return -1; + } + if (m_role < 0 && !m_roleName.isEmpty()) { m_role = m_model->roleNames().key(m_roleName.toLatin1(), -1); } return m_role; } QString ModelSource::roleName() const { return m_roleName; } int ModelSource::column() const { return m_column; } QAbstractItemModel *ModelSource::model() const { return m_model; } bool ModelSource::indexColumns() const { return m_indexColumns; } int ModelSource::itemCount() const { if (!m_model) return 0; return m_indexColumns ? m_model->columnCount() : m_model->rowCount(); } QVariant ModelSource::item(int index) const { if (!m_model) return QVariant{}; // For certain model (QML ListModel for example), the roleNames() are more // dynamic and may only be valid when this method gets called. So try and // lookup the role first before anything else. if (m_role < 0) { if (m_roleName.isEmpty()) { return QVariant{}; } m_role = m_model->roleNames().key(m_roleName.toLatin1(), -1); if (m_role < 0) { qWarning() << "ModelSource: Invalid role " << m_role << m_roleName; return QVariant{}; } } if (!m_indexColumns && (m_column < 0 || m_column > m_model->columnCount())) { qWarning() << "ModelSource: Invalid column" << m_column; return QVariant{}; } auto modelIndex = m_indexColumns ? m_model->index(0, index) : m_model->index(index, m_column); if (modelIndex.isValid()) { return m_model->data(modelIndex, m_role); } return QVariant{}; } QVariant ModelSource::minimum() const { - if (itemCount() <= 0) + if (!m_model || itemCount() <= 0) return QVariant{}; auto minProperty = m_model->property("minimum"); auto maxProperty = m_model->property("maximum"); if (minProperty.isValid() && minProperty != maxProperty) { return minProperty; } QVariant result = std::numeric_limits::max(); for (int i = 0; i < itemCount(); ++i) { result = qMin(result, item(i)); } return result; } QVariant ModelSource::maximum() const { - if (itemCount() <= 0) + if (!m_model || itemCount() <= 0) return QVariant{}; auto minProperty = m_model->property("minimum"); auto maxProperty = m_model->property("maximum"); if (maxProperty.isValid() && maxProperty != minProperty) { return maxProperty; } QVariant result = std::numeric_limits::min(); for (int i = 0; i < itemCount(); ++i) { result = qMax(result, item(i)); } return result; } void ModelSource::setRole(int role) { if (role == m_role) { return; } m_role = role; if (m_model) { m_roleName = QString::fromLatin1(m_model->roleNames().value(role)); Q_EMIT roleNameChanged(); } Q_EMIT roleChanged(); } void ModelSource::setRoleName(const QString &name) { if (name == m_roleName) { return; } m_roleName = name; if (m_model) { m_role = m_model->roleNames().key(m_roleName.toLatin1(), -1); Q_EMIT roleChanged(); } Q_EMIT roleNameChanged(); } void ModelSource::setColumn(int column) { if (column == m_column) { return; } m_column = column; Q_EMIT columnChanged(); } void ModelSource::setIndexColumns(bool index) { if (index == m_indexColumns) { return; } m_indexColumns = index; Q_EMIT indexColumnsChanged(); } void ModelSource::setModel(QAbstractItemModel *model) { if (m_model == model) { return; } if (m_model) { m_model->disconnect(this); } m_model = model; if (m_model) { connect(m_model, &QAbstractItemModel::rowsInserted, this, &ModelSource::dataChanged); connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ModelSource::dataChanged); connect(m_model, &QAbstractItemModel::rowsMoved, this, &ModelSource::dataChanged); connect(m_model, &QAbstractItemModel::modelReset, this, &ModelSource::dataChanged); connect(m_model, &QAbstractItemModel::dataChanged, this, &ModelSource::dataChanged); connect(m_model, &QAbstractItemModel::layoutChanged, this, &ModelSource::dataChanged); } Q_EMIT modelChanged(); } diff --git a/src/datasource/ModelSource.h b/src/datasource/ModelSource.h index d5a2207..be0798d 100644 --- a/src/datasource/ModelSource.h +++ b/src/datasource/ModelSource.h @@ -1,65 +1,66 @@ /* * This file is part of KQuickCharts * SPDX-FileCopyrightText: 2019 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #ifndef MODELSOURCE_H #define MODELSOURCE_H #include "ChartDataSource.h" #include +#include /** * A data source that reads data from a QAbstractItemModel. * * */ class ModelSource : public ChartDataSource { Q_OBJECT Q_PROPERTY(int role READ role WRITE setRole NOTIFY roleChanged) Q_PROPERTY(QString roleName READ roleName WRITE setRoleName NOTIFY roleNameChanged) Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged) Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(bool indexColumns READ indexColumns WRITE setIndexColumns NOTIFY indexColumnsChanged) public: explicit ModelSource(QObject *parent = nullptr); int role() const; void setRole(int role); Q_SIGNAL void roleChanged(); QString roleName() const; void setRoleName(const QString &name); Q_SIGNAL void roleNameChanged(); int column() const; void setColumn(int column); Q_SIGNAL void columnChanged(); QAbstractItemModel *model() const; void setModel(QAbstractItemModel *model); Q_SIGNAL void modelChanged(); bool indexColumns() const; void setIndexColumns(bool index); Q_SIGNAL void indexColumnsChanged(); virtual int itemCount() const override; virtual QVariant item(int index) const override; virtual QVariant minimum() const override; virtual QVariant maximum() const override; private: mutable int m_role = -1; QString m_roleName; int m_column = 0; bool m_indexColumns = false; - QAbstractItemModel *m_model = nullptr; + QPointer m_model; }; #endif // MODELSOURCE_H