File indexing completed on 2024-04-28 05:41:32

0001 /*
0002     This file is part of KCachegrind.
0003 
0004     SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only
0007 */
0008 
0009 /*
0010  * Items of coverage view.
0011  */
0012 
0013 #include "coverageitem.h"
0014 
0015 
0016 #include "globalguiconfig.h"
0017 #include "listutils.h"
0018 #include "coverage.h"
0019 
0020 
0021 // CallerCoverageItem
0022 
0023 
0024 CallerCoverageItem::CallerCoverageItem(QTreeWidget* parent, Coverage* c,
0025                                        TraceFunction* base,
0026                                        EventType* ct,
0027                                        ProfileContext::Type gt)
0028     : QTreeWidgetItem(parent)
0029 {
0030     _skipped = 0;
0031     _coverage = c;
0032     _function = c->function();
0033     _base = base;
0034     _groupType = ProfileContext::InvalidType;
0035 
0036     setText(3, _function->prettyNameWithLocation());
0037     setTextAlignment(0, Qt::AlignRight);
0038     setTextAlignment(1, Qt::AlignRight);
0039     setTextAlignment(2, Qt::AlignRight);
0040     setCostType(ct);
0041     setGroupType(gt);
0042 }
0043 
0044 CallerCoverageItem::CallerCoverageItem(QTreeWidget* parent, int skipped, Coverage* c,
0045                                        TraceFunction* base,
0046                                        EventType* ct,
0047                                        ProfileContext::Type gt)
0048     : QTreeWidgetItem(parent)
0049 {
0050     _skipped = skipped;
0051     _coverage = c;
0052     _function = c->function();
0053     _base = base;
0054     _groupType = ProfileContext::InvalidType;
0055 
0056     //~ singular (%n function skipped)
0057     //~ plural (%n functions skipped)
0058     setText(3, QObject::tr("(%n function(s) skipped)", "", _skipped));
0059     setTextAlignment(0, Qt::AlignRight);
0060     setTextAlignment(1, Qt::AlignRight);
0061     setTextAlignment(2, Qt::AlignRight);
0062     setCostType(ct);
0063     setGroupType(gt);
0064 }
0065 
0066 void CallerCoverageItem::setGroupType(ProfileContext::Type gt)
0067 {
0068     if (_skipped) return;
0069     if (_groupType == gt) return;
0070     _groupType = gt;
0071 
0072     QColor c = GlobalGUIConfig::functionColor(_groupType, _function);
0073     setIcon(3, colorPixmap(10, 10, c));
0074 }
0075 
0076 void CallerCoverageItem::setCostType(EventType* ct)
0077 {
0078     _costType = ct;
0079     update();
0080 }
0081 
0082 void CallerCoverageItem::update()
0083 {
0084     if (!_coverage) {
0085         setText(0, QString());
0086         setText(1, QString());
0087         return;
0088     }
0089 
0090     _pSum = 100.0 * _coverage->inclusive();
0091     SubCost realSum = _base->inclusive()->subCost(_costType);
0092     _sum = SubCost(realSum * _coverage->inclusive());
0093     QString str;
0094     if (GlobalConfig::showPercentage())
0095         str = QStringLiteral("%1").arg(_pSum, 0, 'f', GlobalConfig::percentPrecision());
0096     else
0097         str = _sum.pretty();
0098 
0099     if (_skipped) {
0100         setText(0, QStringLiteral("< %1").arg(str));
0101         return;
0102     }
0103 
0104     setText(0, str);
0105     setIcon(0, partitionPixmap(25, 10, _coverage->inclusiveHistogram(), nullptr,
0106                                Coverage::maxHistogramDepth, false));
0107 
0108     // call count
0109     _cc  = SubCost(_coverage->callCount());
0110     setText(2, _cc ? _cc.pretty() : QStringLiteral("(0)"));
0111 
0112     // distance (min/max/median)
0113     _distance = _coverage->inclusiveMedian();
0114     QString distString;
0115     if (_coverage->minDistance() == _coverage->maxDistance())
0116         distString = QString::number(_distance);
0117     else
0118         distString = QStringLiteral("%1-%2 (%3)")
0119                      .arg(_coverage->minDistance())
0120                      .arg(_coverage->maxDistance())
0121                      .arg(_distance);
0122     setText(1, distString);
0123 }
0124 
0125 
0126 bool CallerCoverageItem::operator<( const QTreeWidgetItem & other ) const
0127 {
0128     const CallerCoverageItem* ci1 = this;
0129     const CallerCoverageItem* ci2 = (CallerCoverageItem*) &other;
0130     int col = treeWidget()->sortColumn();
0131 
0132     // a skip entry is always sorted last
0133     if (ci1->_skipped) return true;
0134     if (ci2->_skipped) return false;
0135 
0136     if (col==0) {
0137         if (ci1->_pSum < ci2->_pSum) return true;
0138         if (ci1->_pSum > ci2->_pSum) return false;
0139 
0140         // for same percentage (e.g. all 100%), use distance info
0141         return ci1->_distance < ci2->_distance;
0142     }
0143 
0144     if (col==1) {
0145         return ci1->_distance < ci2->_distance;
0146     }
0147 
0148     if (col==2) {
0149         return ci1->_cc < ci2->_cc;
0150     }
0151 
0152     return QTreeWidgetItem::operator <(other);
0153 }
0154 
0155 
0156 
0157 // CalleeCoverageItem
0158 
0159 CalleeCoverageItem::CalleeCoverageItem(QTreeWidget* parent, Coverage* c,
0160                                        TraceFunction* base,
0161                                        EventType* ct,
0162                                        ProfileContext::Type gt)
0163     : QTreeWidgetItem(parent)
0164 {
0165     _skipped = 0;
0166     _coverage = c;
0167     _function = c ? c->function() : nullptr;
0168     _base = base;
0169     _groupType = ProfileContext::InvalidType;
0170 
0171     if ( _function )
0172         setText(4, _function->prettyNameWithLocation());
0173 
0174     setTextAlignment(0, Qt::AlignRight);
0175     setTextAlignment(1, Qt::AlignRight);
0176     setTextAlignment(2, Qt::AlignRight);
0177     setTextAlignment(3, Qt::AlignRight);
0178 
0179     setCostType(ct);
0180     setGroupType(gt);
0181 }
0182 
0183 CalleeCoverageItem::CalleeCoverageItem(QTreeWidget* parent, int skipped, Coverage* c,
0184                                        TraceFunction* base,
0185                                        EventType* ct,
0186                                        ProfileContext::Type gt)
0187     : QTreeWidgetItem(parent)
0188 {
0189     _skipped = skipped;
0190     _coverage = c;
0191     _function = c ? c->function() : nullptr;
0192     _base = base;
0193     _groupType = ProfileContext::InvalidType;
0194 
0195     setText(4, QObject::tr("(%n function(s) skipped)", "", _skipped));
0196 
0197     setTextAlignment(0, Qt::AlignRight);
0198     setTextAlignment(1, Qt::AlignRight);
0199     setTextAlignment(2, Qt::AlignRight);
0200     setTextAlignment(3, Qt::AlignRight);
0201 
0202     setCostType(ct);
0203     setGroupType(gt);
0204 }
0205 
0206 void CalleeCoverageItem::setGroupType(ProfileContext::Type gt)
0207 {
0208     if (_skipped) return;
0209     if (_groupType == gt) return;
0210     _groupType = gt;
0211 
0212     QColor c = GlobalGUIConfig::functionColor(_groupType, _function);
0213     setIcon(4, colorPixmap(10, 10, c));
0214 }
0215 
0216 void CalleeCoverageItem::setCostType(EventType* ct)
0217 {
0218     _costType = ct;
0219     update();
0220 }
0221 
0222 void CalleeCoverageItem::update()
0223 {
0224     if (!_coverage) {
0225         setText(0, QString());
0226         setText(1, QString());
0227         setText(2, QString());
0228         return;
0229     }
0230 
0231     _pSum = 100.0 * _coverage->inclusive();
0232 
0233     // pSum/pSelf are percentages of inclusive cost of base
0234     SubCost realSum = _base->inclusive()->subCost(_costType);
0235     _sum = SubCost(realSum * _coverage->inclusive());
0236 
0237 
0238     QString str;
0239     if (GlobalConfig::showPercentage())
0240         str = QStringLiteral("%1").arg(_pSum, 0, 'f', GlobalConfig::percentPrecision());
0241     else
0242         str = _sum.pretty();
0243 
0244     if (_skipped) {
0245         str = QStringLiteral("< %1").arg(str);
0246         setText(0, str);
0247         setText(1, str);
0248         return;
0249     }
0250     setText(0, str);
0251 
0252     _pSelf = 100.0 * _coverage->self();
0253     _self = SubCost(realSum * _coverage->self());
0254 
0255     if (GlobalConfig::showPercentage()) {
0256         setText(1, QStringLiteral("%1")
0257                 .arg(_pSelf, 0, 'f', GlobalConfig::percentPrecision()));
0258     }
0259     else {
0260         setText(1, _self.pretty());
0261     }
0262 
0263     setIcon(0, partitionPixmap(25, 10, _coverage->inclusiveHistogram(), nullptr,
0264                                Coverage::maxHistogramDepth, false));
0265     setIcon(1, partitionPixmap(25, 10, _coverage->selfHistogram(), nullptr,
0266                                Coverage::maxHistogramDepth, false));
0267 
0268 
0269     _cc  = SubCost(_coverage->callCount());
0270     setText(3, _cc ? _cc.pretty() : QStringLiteral("(0)"));
0271 
0272     // for comparisons
0273     _distance = _coverage->inclusiveMedian();
0274     QString distString;
0275     if (_coverage->minDistance() == _coverage->maxDistance())
0276         distString = QString::number(_distance);
0277     else {
0278         int sMed = _coverage->selfMedian();
0279         QString med;
0280         if (_distance == sMed)
0281             med = QString::number(_distance);
0282         else
0283             med = QStringLiteral("%1/%2").arg(_distance).arg(sMed);
0284 
0285         distString = QStringLiteral("%1-%2 (%3)")
0286                      .arg(_coverage->minDistance())
0287                      .arg(_coverage->maxDistance())
0288                      .arg(med);
0289     }
0290     setText(2, distString);
0291 }
0292 
0293 
0294 bool CalleeCoverageItem::operator<( const QTreeWidgetItem & other ) const
0295 {
0296     CalleeCoverageItem* ci = (CalleeCoverageItem*) &other;
0297     int col = treeWidget()->sortColumn();
0298     // a skip entry is always sorted last
0299     if (_skipped) return true;
0300     if (ci->_skipped) return false;
0301 
0302     if (col==0) {
0303         if (_pSum < ci->_pSum) return true;
0304         if (_pSum > ci->_pSum) return false;
0305 
0306         // for same percentage (e.g. all 100%), use distance info
0307         return _distance < ci->_distance;
0308 
0309     }
0310 
0311     if (col==1) {
0312         if (_pSelf < ci->_pSelf) return true;
0313         if (_pSelf > ci->_pSelf) return false;
0314 
0315         // for same percentage (e.g. all 100%), use distance info
0316         return _distance < ci->_distance;
0317     }
0318 
0319     if (col==2) {
0320         // we want to sort the distance in contra direction to costs
0321         return _distance < ci->_distance;
0322     }
0323 
0324     if (col==3) {
0325         return _cc < ci->_cc;
0326     }
0327     return QTreeWidgetItem::operator <(other);
0328 }
0329 
0330