File indexing completed on 2024-05-19 05:44:22

0001 /*
0002     SPDX-FileCopyrightText: 2016-2019 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "callercalleemodel.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 CallerCalleeModel::CallerCalleeModel(QObject* parent)
0012     : HashModel(parent)
0013 {
0014     qRegisterMetaType<CallerCalleeResults>();
0015 }
0016 
0017 CallerCalleeModel::~CallerCalleeModel() = default;
0018 
0019 void CallerCalleeModel::setResults(const CallerCalleeResults& results)
0020 {
0021     Q_ASSERT(results.resultData);
0022     m_results = results;
0023     setRows(results.entries);
0024 }
0025 
0026 void CallerCalleeModel::clearData()
0027 {
0028     m_results = {};
0029     setRows({});
0030 }
0031 
0032 QVariant CallerCalleeModel::headerCell(int column, int role) const
0033 {
0034     if (role == Qt::InitialSortOrderRole) {
0035         return (column > LocationColumn) ? Qt::DescendingOrder : Qt::AscendingOrder;
0036     }
0037     if (role == Qt::DisplayRole) {
0038         switch (static_cast<Columns>(column)) {
0039         case LocationColumn:
0040             return i18n("Location");
0041         case SelfAllocationsColumn:
0042             return i18n("Allocations (Self)");
0043         case SelfTemporaryColumn:
0044             return i18n("Temporary (Self)");
0045         case SelfPeakColumn:
0046             return i18n("Peak (Self)");
0047         case SelfLeakedColumn:
0048             return i18n("Leaked (Self)");
0049         case InclusiveAllocationsColumn:
0050             return i18n("Allocations (Incl.)");
0051         case InclusiveTemporaryColumn:
0052             return i18n("Temporary (Incl.)");
0053         case InclusivePeakColumn:
0054             return i18n("Peak (Incl.)");
0055         case InclusiveLeakedColumn:
0056             return i18n("Leaked (Incl.)");
0057         case NUM_COLUMNS:
0058             break;
0059         }
0060     } else if (role == Qt::ToolTipRole) {
0061         switch (static_cast<Columns>(column)) {
0062         case LocationColumn:
0063             return i18n("<qt>The parent symbol that called an allocation function. "
0064                         "The function name may be unresolved when debug information is missing.</qt>");
0065         case SelfAllocationsColumn:
0066             return i18n("<qt>The number of times an allocation function was directly "
0067                         "called from this location.</qt>");
0068         case SelfTemporaryColumn:
0069             return i18n("<qt>The number of direct temporary allocations. These "
0070                         "allocations are directly followed by a "
0071                         "free without any other allocations in-between.</qt>");
0072         case SelfPeakColumn:
0073             return i18n("<qt>The maximum heap memory in bytes consumed from "
0074                         "allocations originating directly at "
0075                         "this location. "
0076                         "This takes deallocations into account.</qt>");
0077         case SelfLeakedColumn:
0078             return i18n("<qt>The bytes allocated directly at this location that have "
0079                         "not been deallocated.</qt>");
0080         case InclusiveAllocationsColumn:
0081             return i18n("<qt>The inclusive number of times an allocation function "
0082                         "was called from this location or any "
0083                         "functions called from here.</qt>");
0084         case InclusiveTemporaryColumn:
0085             return i18n("<qt>The number of inclusive temporary allocations. These "
0086                         "allocations are directly followed by "
0087                         "a free without any other allocations in-between.</qt>");
0088         case InclusivePeakColumn:
0089             return i18n("<qt>The inclusive maximum heap memory in bytes consumed "
0090                         "from allocations originating at this "
0091                         "location or from functions called from here. "
0092                         "This takes deallocations into account.</qt>");
0093         case InclusiveLeakedColumn:
0094             return i18n("<qt>The bytes allocated at this location that have not been "
0095                         "deallocated.</qt>");
0096         case NUM_COLUMNS:
0097             break;
0098         }
0099     }
0100     return {};
0101 }
0102 
0103 QVariant CallerCalleeModel::cell(int column, int role, const Symbol& symbol, const CallerCalleeEntry& entry) const
0104 {
0105     if (role == SymbolRole) {
0106         return QVariant::fromValue(symbol);
0107     } else if (role == SortRole) {
0108         switch (static_cast<Columns>(column)) {
0109         case LocationColumn:
0110             return Util::toString(symbol, *m_results.resultData, Util::Short);
0111         case SelfAllocationsColumn:
0112             // NOTE: we sort by unsigned absolute value
0113             return QVariant::fromValue<quint64>(std::abs(entry.selfCost.allocations));
0114         case SelfTemporaryColumn:
0115             return QVariant::fromValue<quint64>(std::abs(entry.selfCost.temporary));
0116         case SelfPeakColumn:
0117             return QVariant::fromValue<quint64>(std::abs(entry.selfCost.peak));
0118         case SelfLeakedColumn:
0119             return QVariant::fromValue<quint64>(std::abs(entry.selfCost.leaked));
0120         case InclusiveAllocationsColumn:
0121             return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.allocations));
0122         case InclusiveTemporaryColumn:
0123             return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.temporary));
0124         case InclusivePeakColumn:
0125             return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.peak));
0126         case InclusiveLeakedColumn:
0127             return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.leaked));
0128         case NUM_COLUMNS:
0129             break;
0130         }
0131     } else if (role == TotalCostRole) {
0132         const auto& totalCosts = m_results.resultData->totalCosts();
0133         switch (static_cast<Columns>(column)) {
0134         case SelfAllocationsColumn:
0135         case InclusiveAllocationsColumn:
0136             return QVariant::fromValue<qint64>(totalCosts.allocations);
0137         case SelfTemporaryColumn:
0138         case InclusiveTemporaryColumn:
0139             return QVariant::fromValue<qint64>(totalCosts.temporary);
0140         case SelfPeakColumn:
0141         case InclusivePeakColumn:
0142             return QVariant::fromValue<qint64>(totalCosts.peak);
0143         case SelfLeakedColumn:
0144         case InclusiveLeakedColumn:
0145             return QVariant::fromValue<qint64>(totalCosts.leaked);
0146         case LocationColumn:
0147         case NUM_COLUMNS:
0148             break;
0149         }
0150     } else if (role == Qt::DisplayRole) {
0151         switch (static_cast<Columns>(column)) {
0152         case LocationColumn:
0153             return Util::toString(symbol, *m_results.resultData, Util::Short);
0154         case SelfAllocationsColumn:
0155             return QVariant::fromValue<qint64>(entry.selfCost.allocations);
0156         case SelfTemporaryColumn:
0157             return QVariant::fromValue<qint64>(entry.selfCost.temporary);
0158         case SelfPeakColumn:
0159             return Util::formatBytes(entry.selfCost.peak);
0160         case SelfLeakedColumn:
0161             return Util::formatBytes(entry.selfCost.leaked);
0162         case InclusiveAllocationsColumn:
0163             return QVariant::fromValue<qint64>(entry.inclusiveCost.allocations);
0164         case InclusiveTemporaryColumn:
0165             return QVariant::fromValue<qint64>(entry.inclusiveCost.temporary);
0166         case InclusivePeakColumn:
0167             return Util::formatBytes(entry.inclusiveCost.peak);
0168         case InclusiveLeakedColumn:
0169             return Util::formatBytes(entry.inclusiveCost.leaked);
0170         case NUM_COLUMNS:
0171             break;
0172         }
0173     } else if (role == CalleesRole) {
0174         return QVariant::fromValue(entry.callees);
0175     } else if (role == CallersRole) {
0176         return QVariant::fromValue(entry.callers);
0177     } else if (role == SourceMapRole) {
0178         return QVariant::fromValue(entry.sourceMap);
0179     } else if (role == Qt::ToolTipRole) {
0180         return Util::formatTooltip(symbol, entry.selfCost, entry.inclusiveCost, *m_results.resultData);
0181     } else if (role == ResultDataRole) {
0182         return QVariant::fromValue(m_results.resultData.get());
0183     }
0184 
0185     return {};
0186 }
0187 
0188 QModelIndex CallerCalleeModel::indexForSymbol(const Symbol& symbol) const
0189 {
0190     return indexForKey(symbol);
0191 }
0192 
0193 CallerModel::CallerModel(QObject* parent)
0194     : SymbolCostModelImpl(parent)
0195 {
0196 }
0197 
0198 CallerModel::~CallerModel() = default;
0199 
0200 QString CallerModel::symbolHeader() const
0201 {
0202     return i18n("Caller");
0203 }
0204 
0205 CalleeModel::CalleeModel(QObject* parent)
0206     : SymbolCostModelImpl(parent)
0207 {
0208 }
0209 
0210 CalleeModel::~CalleeModel() = default;
0211 
0212 QString CalleeModel::symbolHeader() const
0213 {
0214     return i18n("Callee");
0215 }
0216 
0217 SourceMapModel::SourceMapModel(QObject* parent)
0218     : LocationCostModelImpl(parent)
0219 {
0220 }
0221 
0222 SourceMapModel::~SourceMapModel() = default;
0223 
0224 int CallerCalleeModel::numColumns() const
0225 {
0226     return NUM_COLUMNS;
0227 }
0228 
0229 #include "moc_callercalleemodel.cpp"