File indexing completed on 2024-05-05 05:47:26
0001 /* 0002 This file is part of Massif Visualizer 0003 0004 Copyright 2014 Milian Wolff <mail@milianw.de> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License or (at your option) version 3 or any later version 0010 accepted by the membership of KDE e.V. (or its successor approved 0011 by the membership of KDE e.V.), which shall act as a proxy 0012 defined in Section 14 of version 3 of the license. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 #include "allocatorsmodel.h" 0024 0025 #include "massifdata/snapshotitem.h" 0026 #include "massifdata/filedata.h" 0027 #include "massifdata/treeleafitem.h" 0028 0029 #include <KLocalizedString> 0030 0031 using namespace Massif; 0032 0033 namespace { 0034 0035 ParsedLabel labelForNode(const TreeLeafItem* node) 0036 { 0037 ParsedLabel label; 0038 if (!isBelowThreshold(node->label())) { 0039 label = parseLabel(node->label()); 0040 label.address.clear(); 0041 } 0042 return label; 0043 } 0044 0045 } 0046 0047 AllocatorsModel::AllocatorsModel(const FileData* data, QObject* parent) 0048 : QAbstractItemModel(parent) 0049 { 0050 m_data.reserve(1024); 0051 0052 QHash<ParsedLabel, int> labelToData; 0053 foreach (const SnapshotItem* snapshot, data->snapshots()) { 0054 if (!snapshot->heapTree()) { 0055 continue; 0056 } 0057 foreach (const TreeLeafItem* node, snapshot->heapTree()->children()) { 0058 const ParsedLabel label = labelForNode(node); 0059 0060 int idx = labelToData.value(label, -1); 0061 if (idx == -1) { 0062 idx = m_data.size(); 0063 labelToData[label] = idx; 0064 Data data; 0065 data.label = label; 0066 data.peak = node; 0067 m_data << data; 0068 } 0069 0070 Data& data = m_data[idx]; 0071 if (data.peak->cost() < node->cost()) { 0072 data.peak = node; 0073 } 0074 } 0075 } 0076 } 0077 0078 AllocatorsModel::~AllocatorsModel() 0079 { 0080 0081 } 0082 0083 int AllocatorsModel::columnCount(const QModelIndex& parent) const 0084 { 0085 if (parent.isValid()) { 0086 return 0; 0087 } 0088 return NUM_COLUMNS; 0089 } 0090 0091 int AllocatorsModel::rowCount(const QModelIndex& parent) const 0092 { 0093 if (parent.isValid()) { 0094 return 0; 0095 } 0096 return m_data.size(); 0097 } 0098 0099 QModelIndex AllocatorsModel::index(int row, int column, const QModelIndex& parent) const 0100 { 0101 if (parent.isValid() || row < 0 || column < 0 || row >= m_data.size() || column >= NUM_COLUMNS) { 0102 return QModelIndex(); 0103 } 0104 return createIndex(row, column); 0105 } 0106 0107 QModelIndex AllocatorsModel::parent(const QModelIndex& /*child*/) const 0108 { 0109 return QModelIndex(); 0110 } 0111 0112 QVariant AllocatorsModel::data(const QModelIndex& index, int role) const 0113 { 0114 if (role != Qt::DisplayRole && role != Qt::ToolTipRole && role != SortRole && role != ItemRole) { 0115 return QVariant(); 0116 } 0117 0118 if (!index.isValid() || index.parent().isValid() || index.row() < 0 || index.row() >= m_data.size() 0119 || index.column() < 0 || index.column() >= NUM_COLUMNS) 0120 { 0121 return QVariant(); 0122 } 0123 0124 const Data& data = m_data.value(index.row()); 0125 0126 if (role == Qt::ToolTipRole) { 0127 QString tooltip = i18n("<dt>peak cost:</dt><dd>%1</dd>", prettyCost(data.peak->cost())); 0128 tooltip += formatLabelForTooltip(data.label); 0129 return finalizeTooltip(tooltip); 0130 } else if (role == ItemRole) { 0131 return QVariant::fromValue(ModelItem(data.peak, nullptr)); 0132 } 0133 0134 switch (index.column()) { 0135 case Function: 0136 if (data.label.function.isEmpty()) { 0137 return i18n("below threshold"); 0138 } 0139 return shortenTemplates(data.label.function); 0140 case Location: 0141 return data.label.location; 0142 case Peak: 0143 if (role == SortRole) { 0144 return data.peak->cost(); 0145 } 0146 return prettyCost(data.peak->cost()); 0147 } 0148 0149 return QVariant(); 0150 } 0151 0152 QVariant AllocatorsModel::headerData(int section, Qt::Orientation orientation, int role) const 0153 { 0154 if (role != Qt::DisplayRole || orientation != Qt::Horizontal || section < 0 || section >= NUM_COLUMNS) { 0155 return QVariant(); 0156 } 0157 0158 switch (section) { 0159 case Function: 0160 return i18n("Function"); 0161 case Location: 0162 return i18n("Location"); 0163 case Peak: 0164 return i18n("Peak"); 0165 } 0166 0167 return QVariant(); 0168 } 0169 0170 QModelIndex AllocatorsModel::indexForItem(const ModelItem& item) const 0171 { 0172 if (!item.first) { 0173 return QModelIndex(); 0174 } 0175 0176 const ParsedLabel label = labelForNode(item.first); 0177 0178 for (int i = 0; i < m_data.size(); ++i) { 0179 if (m_data[i].label == label) { 0180 return createIndex(i, Function); 0181 } 0182 } 0183 0184 return QModelIndex(); 0185 } 0186 0187 void AllocatorsModel::settingsChanged() 0188 { 0189 if (m_data.isEmpty()) { 0190 return; 0191 } 0192 // update shorten templates 0193 dataChanged(createIndex(0, Function), 0194 createIndex(m_data.size() - 1, Function)); 0195 } 0196 0197 #include "moc_allocatorsmodel.cpp"