Warning, file /frameworks/kquickcharts/src/datasource/ModelSource.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of KQuickCharts 0003 * SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "ModelSource.h" 0009 0010 #include <QMetaProperty> 0011 0012 #include "charts_datasource_logging.h" 0013 0014 ModelSource::ModelSource(QObject *parent) 0015 : ChartDataSource(parent) 0016 { 0017 connect(this, &ModelSource::modelChanged, this, &ModelSource::dataChanged); 0018 connect(this, &ModelSource::columnChanged, this, &ModelSource::dataChanged); 0019 connect(this, &ModelSource::roleChanged, this, &ModelSource::dataChanged); 0020 connect(this, &ModelSource::indexColumnsChanged, this, &ModelSource::dataChanged); 0021 } 0022 0023 int ModelSource::role() const 0024 { 0025 if (!m_model) { 0026 return -1; 0027 } 0028 0029 if (m_role < 0 && !m_roleName.isEmpty()) { 0030 m_role = m_model->roleNames().key(m_roleName.toLatin1(), -1); 0031 } 0032 0033 return m_role; 0034 } 0035 0036 QString ModelSource::roleName() const 0037 { 0038 return m_roleName; 0039 } 0040 0041 int ModelSource::column() const 0042 { 0043 return m_column; 0044 } 0045 0046 QAbstractItemModel *ModelSource::model() const 0047 { 0048 return m_model; 0049 } 0050 0051 bool ModelSource::indexColumns() const 0052 { 0053 return m_indexColumns; 0054 } 0055 0056 int ModelSource::itemCount() const 0057 { 0058 if (!m_model) { 0059 return 0; 0060 } 0061 0062 return m_indexColumns ? m_model->columnCount() : m_model->rowCount(); 0063 } 0064 0065 QVariant ModelSource::item(int index) const 0066 { 0067 if (!m_model) { 0068 return {}; 0069 } 0070 0071 // For certain model (QML ListModel for example), the roleNames() are more 0072 // dynamic and may only be valid when this method gets called. So try and 0073 // lookup the role first before anything else. 0074 if (m_role < 0) { 0075 if (m_roleName.isEmpty()) { 0076 return QVariant{}; 0077 } 0078 0079 m_role = m_model->roleNames().key(m_roleName.toLatin1(), -1); 0080 if (m_role < 0) { 0081 qCWarning(DATASOURCE) << "ModelSource: Invalid role " << m_role << m_roleName; 0082 return QVariant{}; 0083 } 0084 } 0085 0086 if (!m_indexColumns && (m_column < 0 || m_column > m_model->columnCount())) { 0087 qCDebug(DATASOURCE) << "ModelSource: Invalid column" << m_column; 0088 return QVariant{}; 0089 } 0090 0091 auto modelIndex = m_indexColumns ? m_model->index(0, index) : m_model->index(index, m_column); 0092 if (modelIndex.isValid()) { 0093 return m_model->data(modelIndex, m_role); 0094 } 0095 0096 return QVariant{}; 0097 } 0098 0099 QVariant ModelSource::minimum() const 0100 { 0101 if (!m_model || itemCount() <= 0) { 0102 return {}; 0103 } 0104 0105 if (m_minimum.isValid()) { 0106 return m_minimum; 0107 } 0108 0109 auto minProperty = m_model->property("minimum"); 0110 auto maxProperty = m_model->property("maximum"); 0111 if (minProperty.isValid() && minProperty != maxProperty) { 0112 return minProperty; 0113 } 0114 0115 QVariant result = std::numeric_limits<float>::max(); 0116 for (int i = 0; i < itemCount(); ++i) { 0117 result = std::min(result, item(i), variantCompare); 0118 } 0119 return result; 0120 } 0121 0122 QVariant ModelSource::maximum() const 0123 { 0124 if (!m_model || itemCount() <= 0) { 0125 return {}; 0126 } 0127 0128 if (m_maximum.isValid()) { 0129 return m_maximum; 0130 } 0131 0132 auto minProperty = m_model->property("minimum"); 0133 auto maxProperty = m_model->property("maximum"); 0134 if (maxProperty.isValid() && maxProperty != minProperty) { 0135 return maxProperty; 0136 } 0137 0138 QVariant result = std::numeric_limits<float>::min(); 0139 for (int i = 0; i < itemCount(); ++i) { 0140 result = std::max(result, item(i), variantCompare); 0141 } 0142 return result; 0143 } 0144 0145 void ModelSource::setRole(int role) 0146 { 0147 if (role == m_role) { 0148 return; 0149 } 0150 0151 m_role = role; 0152 if (m_model) { 0153 m_roleName = QString::fromLatin1(m_model->roleNames().value(role)); 0154 Q_EMIT roleNameChanged(); 0155 } 0156 Q_EMIT roleChanged(); 0157 } 0158 0159 void ModelSource::setRoleName(const QString &name) 0160 { 0161 if (name == m_roleName) { 0162 return; 0163 } 0164 0165 m_roleName = name; 0166 if (m_model) { 0167 m_role = m_model->roleNames().key(m_roleName.toLatin1(), -1); 0168 Q_EMIT roleChanged(); 0169 } 0170 Q_EMIT roleNameChanged(); 0171 } 0172 0173 void ModelSource::setColumn(int column) 0174 { 0175 if (column == m_column) { 0176 return; 0177 } 0178 0179 m_column = column; 0180 Q_EMIT columnChanged(); 0181 } 0182 0183 void ModelSource::setIndexColumns(bool index) 0184 { 0185 if (index == m_indexColumns) { 0186 return; 0187 } 0188 0189 m_indexColumns = index; 0190 Q_EMIT indexColumnsChanged(); 0191 } 0192 0193 void ModelSource::setModel(QAbstractItemModel *model) 0194 { 0195 if (m_model == model) { 0196 return; 0197 } 0198 0199 if (m_model) { 0200 m_model->disconnect(this); 0201 m_minimum = QVariant{}; 0202 m_maximum = QVariant{}; 0203 } 0204 0205 m_model = model; 0206 if (m_model) { 0207 connect(m_model, &QAbstractItemModel::rowsInserted, this, &ModelSource::dataChanged); 0208 connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ModelSource::dataChanged); 0209 connect(m_model, &QAbstractItemModel::rowsMoved, this, &ModelSource::dataChanged); 0210 connect(m_model, &QAbstractItemModel::modelReset, this, &ModelSource::dataChanged); 0211 connect(m_model, &QAbstractItemModel::dataChanged, this, &ModelSource::dataChanged); 0212 connect(m_model, &QAbstractItemModel::layoutChanged, this, &ModelSource::dataChanged); 0213 0214 connect(m_model, &QAbstractItemModel::destroyed, this, [this]() { 0215 m_minimum = QVariant{}; 0216 m_maximum = QVariant{}; 0217 m_model = nullptr; 0218 }); 0219 0220 auto minimumIndex = m_model->metaObject()->indexOfProperty("minimum"); 0221 if (minimumIndex != -1) { 0222 auto minimum = m_model->metaObject()->property(minimumIndex); 0223 if (minimum.hasNotifySignal()) { 0224 auto slot = metaObject()->method(metaObject()->indexOfSlot("onMinimumChanged()")); 0225 connect(m_model, minimum.notifySignal(), this, slot); 0226 m_minimum = minimum.read(m_model); 0227 } 0228 } 0229 0230 auto maximumIndex = m_model->metaObject()->indexOfProperty("maximum"); 0231 if (maximumIndex != -1) { 0232 auto maximum = m_model->metaObject()->property(maximumIndex); 0233 if (maximum.hasNotifySignal()) { 0234 auto slot = metaObject()->method(metaObject()->indexOfSlot("onMaximumChanged()")); 0235 connect(m_model, maximum.notifySignal(), this, slot); 0236 m_maximum = maximum.read(m_model); 0237 } 0238 } 0239 } 0240 0241 Q_EMIT modelChanged(); 0242 } 0243 0244 void ModelSource::onMinimumChanged() 0245 { 0246 auto newMinimum = m_model->property("minimum"); 0247 if (newMinimum.isValid() && newMinimum != m_minimum) { 0248 m_minimum = newMinimum; 0249 } 0250 } 0251 0252 void ModelSource::onMaximumChanged() 0253 { 0254 auto newMaximum = m_model->property("maximum"); 0255 if (newMaximum.isValid() && newMaximum != m_maximum) { 0256 m_maximum = newMaximum; 0257 } 0258 } 0259 0260 #include "moc_ModelSource.cpp"