File indexing completed on 2024-12-15 03:45:01
0001 /* 0002 SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: MIT 0005 */ 0006 0007 #include "numericaggregationmodel.h" 0008 #include <model/timeaggregationmodel.h> 0009 #include <core/sample.h> 0010 0011 using namespace KUserFeedback::Console; 0012 0013 NumericAggregationModel::NumericAggregationModel(QObject *parent) : 0014 QAbstractTableModel(parent) 0015 { 0016 } 0017 0018 NumericAggregationModel::~NumericAggregationModel() = default; 0019 0020 void NumericAggregationModel::setSourceModel(QAbstractItemModel* model) 0021 { 0022 Q_ASSERT(model); 0023 m_sourceModel = model; 0024 connect(model, &QAbstractItemModel::modelReset, this, &NumericAggregationModel::recompute); 0025 recompute(); 0026 } 0027 0028 void NumericAggregationModel::setAggregation(const AggregationElement& aggr) 0029 { 0030 m_aggr = aggr; 0031 recompute(); 0032 } 0033 0034 int NumericAggregationModel::columnCount(const QModelIndex& parent) const 0035 { 0036 Q_UNUSED(parent); 0037 return 6; 0038 } 0039 0040 int NumericAggregationModel::rowCount(const QModelIndex& parent) const 0041 { 0042 if (parent.isValid() || !m_sourceModel) 0043 return 0; 0044 return m_sourceModel->rowCount(); 0045 } 0046 0047 QVariant NumericAggregationModel::data(const QModelIndex& index, int role) const 0048 { 0049 if (!index.isValid() || !m_sourceModel || index.row()>=m_data.count()) 0050 return {}; 0051 0052 if (role == TimeAggregationModel::MaximumValueRole) 0053 return m_maxValue; 0054 0055 if (index.column() == 0) { 0056 const auto srcIdx = m_sourceModel->index(index.row(), 0); 0057 return m_sourceModel->data(srcIdx, role); 0058 } 0059 if (role == Qt::DisplayRole || role == TimeAggregationModel::DataDisplayRole) { 0060 const auto d = m_data.at(index.row()); 0061 switch (index.column()) { 0062 case 1: return d.lowerExtreme; 0063 case 2: return d.lowerQuartile; 0064 case 3: return d.median; 0065 case 4: return d.upperQuartile; 0066 case 5: return d.upperExtreme; 0067 } 0068 } 0069 0070 return {}; 0071 } 0072 0073 QVariant NumericAggregationModel::headerData(int section, Qt::Orientation orientation, int role) const 0074 { 0075 if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_sourceModel) { 0076 switch (section) { 0077 case 0: return m_sourceModel->headerData(section, orientation, role); 0078 case 1: return tr("Lower Extreme"); 0079 case 2: return tr("Lower Quartile"); 0080 case 3: return tr("Median"); 0081 case 4: return tr("Upper Quartile"); 0082 case 5: return tr("Upper Extreme"); 0083 } 0084 } 0085 0086 return QAbstractTableModel::headerData(section, orientation, role); 0087 } 0088 0089 void NumericAggregationModel::recompute() 0090 { 0091 if (!m_sourceModel) 0092 return; 0093 0094 const auto rowCount = m_sourceModel->rowCount(); 0095 beginResetModel(); 0096 0097 m_data.clear(); 0098 m_maxValue = 0; 0099 0100 if (rowCount <= 0 || !m_aggr.isValid()) { 0101 endResetModel(); 0102 return; 0103 } 0104 0105 m_data.reserve(rowCount); 0106 QVector<double> values; 0107 0108 for (int row = 0; row < rowCount; ++row) { 0109 const auto samples = m_sourceModel->index(row, 0).data(TimeAggregationModel::SamplesRole).value<QVector<Sample>>(); 0110 0111 values.clear(); 0112 values.reserve(samples.size()); 0113 0114 foreach (const auto &sample, samples) 0115 values += sampleValues(sample); 0116 0117 std::sort(values.begin(), values.end()); 0118 0119 Data d; 0120 if (values.size() > 0) { 0121 d.lowerExtreme = values.at(0); 0122 d.lowerQuartile = values.at(values.size() / 4); 0123 d.median = values.at(values.size() / 2); 0124 d.upperQuartile = values.at(values.size() * 3 / 4); 0125 d.upperExtreme = values.last(); 0126 m_maxValue = std::max(m_maxValue, d.upperExtreme); 0127 } 0128 m_data.push_back(d); 0129 } 0130 0131 endResetModel(); 0132 } 0133 0134 QVector<double> NumericAggregationModel::sampleValues(const Sample &s) const 0135 { 0136 switch (m_aggr.schemaEntry().dataType()) { 0137 case SchemaEntry::Scalar: 0138 { 0139 if (m_aggr.type() != AggregationElement::Value) 0140 return {}; 0141 return {s.value(m_aggr.schemaEntry().name() + QLatin1String(".") + m_aggr.schemaEntryElement().name()).toDouble()}; 0142 } 0143 case SchemaEntry::List: 0144 { 0145 const auto l = s.value(m_aggr.schemaEntry().name()).value<QVariantList>(); 0146 if (m_aggr.type() == AggregationElement::Size) 0147 return {(double)l.size()}; 0148 QVector<double> r; 0149 r.reserve(l.size()); 0150 for (const auto &entry : l) 0151 r.push_back(entry.toMap().value(m_aggr.schemaEntryElement().name()).toDouble()); 0152 return r; 0153 } 0154 case SchemaEntry::Map: 0155 { 0156 const auto m = s.value(m_aggr.schemaEntry().name()).toMap(); 0157 if (m_aggr.type() == AggregationElement::Size) 0158 return {(double)m.size()}; 0159 QVector<double> r; 0160 r.reserve(m.size()); 0161 for (auto it = m.begin(); it != m.end(); ++it) 0162 r.push_back(it.value().toMap().value(m_aggr.schemaEntryElement().name()).toDouble()); 0163 return r; 0164 } 0165 } 0166 0167 return {}; 0168 } 0169 0170 #include "moc_numericaggregationmodel.cpp"